diff --git a/.flake8 b/.flake8 new file mode 100644 index 000000000..7da1f9608 --- /dev/null +++ b/.flake8 @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 100 diff --git a/.github/workflows/apply-formatting.yml b/.github/workflows/apply-formatting.yml index 40fd6fda4..1f461677e 100644 --- a/.github/workflows/apply-formatting.yml +++ b/.github/workflows/apply-formatting.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest if: startsWith(github.event.comment.body, '@par-hermes format') steps: - - uses: JoshuaSBrown/cpp-py-formatter/command@v0.2.3 + - uses: JoshuaSBrown/cpp-py-formatter/command@v0.3.8 with: botName: par-hermes clangFormatVersion: 10 diff --git a/.github/workflows/format-check.yml b/.github/workflows/format-check.yml index 7bf00b5dc..8b1378917 100644 --- a/.github/workflows/format-check.yml +++ b/.github/workflows/format-check.yml @@ -1,37 +1 @@ -name: Format Check -on: push -jobs: - check-formatting: - name: Code Formatting - runs-on: ubuntu-latest - steps: - - uses: JoshuaSBrown/cpp-py-formatter/check@v0.2.3 - with: - clangFormatVersion: 10 - token: ${{ secrets.GITHUB_TOKEN }} - format-check: - runs-on: ubuntu-latest - if: ${{ always() }} - # needs: check-formatting - strategy: - matrix: - python-version: [ "3.9" ] - steps: - - uses: actions/checkout@v2 - - name: Update ubuntu - run: sudo apt-get update - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - sudo apt-get install -y python3-sphinx sphinx-rtd-theme-common - pip install sphinx_rtd_theme recommonmark flake8 black pytest pytest-cov black[jupyter] - - name: Black formatting checks - run: black --exclude '/jupyter_notebooks/' --check . - - name: Lint with flake8 - run: | - flake8 --count --select=E9,F63,F7,F82 --show-source --statistics --max-line-length 100 . - flake8 --count --statistics --max-line-length 100 . diff --git a/.github/workflows/javascript-format.yml b/.github/workflows/javascript-format.yml new file mode 100644 index 000000000..e11e5d1e4 --- /dev/null +++ b/.github/workflows/javascript-format.yml @@ -0,0 +1,34 @@ +name: JavaScript Formatter +on: push +jobs: + format-javascript: + runs-on: ubuntu-latest + + steps: + # Step 1: Checkout the repository + - name: Checkout Code + uses: actions/checkout@v4 + + # Step 2: Set up Node.js environment + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' # Specify your Node.js version + + # Step 3: Install Prettier and ESLint globally + - name: Install Prettier + run: | + npm install -g prettier + + # Step 4: Run Prettier to format code + - name: Run prettier + run: | + prettier "**/*.js" --write + git diff + git reset --hard + prettier --check "**/*.js" + + # Step 5: Report status + - name: Complete + run: echo "Formatting completed successfully!" + diff --git a/.github/workflows/javascript-lint.yml b/.github/workflows/javascript-lint.yml new file mode 100644 index 000000000..1aca20a63 --- /dev/null +++ b/.github/workflows/javascript-lint.yml @@ -0,0 +1,28 @@ +name: JavaScript Linter +on: push +jobs: + lint-javascript: + runs-on: ubuntu-latest + + steps: + # Step 1: Checkout the repository + - name: Checkout Code + uses: actions/checkout@v4 + + # Step 2: Set up Node.js environment + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' # MOre up to date version needed for linter + + # Step 3: Instal ESLint and run + - name: Install ESLint + run: | + npm init -y + npm install eslint@latest @babel/eslint-parser@latest eslint-define-config globals eslint-plugin-jsdoc --save + npx eslint "**/*.js" + + # Step 4: Report status + - name: Complete + run: echo "Linting completed successfully!" + diff --git a/.github/workflows/jupyternotebook-lint.yml b/.github/workflows/jupyternotebook-lint.yml new file mode 100644 index 000000000..405cad8ec --- /dev/null +++ b/.github/workflows/jupyternotebook-lint.yml @@ -0,0 +1,40 @@ +name: Jupyter Notebook Linter +on: + push: + paths: + - '**/*.ipynb' + - '.github/workflows/jupyternotebook-lint.yml' + +jobs: + lint-jupyter: + runs-on: ubuntu-latest + + steps: + # Step 1: Checkout the repository + - name: Checkout Code + uses: actions/checkout@v4 + + # Step 2: Set up Python environment + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.10' # Specify the Python version + + # Step 3: Install dependencies + - name: Install nbQA, flake8, and black + run: | + pip install nbqa flake8 black + + # Step 4: Run flake8 and black on notebooks in ./jupyter_notebooks folder + - name: Lint Jupyter Notebooks with flake8 + run: nbqa flake8 . + working-directory: jupyter_notebooks + + - name: Format Jupyter Notebooks with black + run: nbqa black . --check + working-directory: jupyter_notebooks + + # Step 5: Report status + - name: Complete + run: echo "Jupyter Notebook linting completed!" + diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 4b6eede64..7a1677355 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -2,12 +2,22 @@ name: Unit-Testing on: push jobs: unit-test: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 if: ${{ always() }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Update ubuntu run: sudo apt-get update + - name: Install software-properties-common + run: sudo apt install software-properties-common + - name: Add deadsnakes apt repository + run: sudo add-apt-repository ppa:deadsnakes/ppa + - name: Update to bring in deadsnakes packages + run: sudo apt update + - name: Install Python 3.9 + run: sudo apt install python3.9 python3.9-dev python3.9-venv python3.9-distutils + - name: Ensure pip is installed + run: python3.9 -m ensurepip - name: Install dependencies run: | ./scripts/generate_datafed.sh @@ -15,7 +25,7 @@ jobs: ./scripts/generate_datafed.sh - name: Build run: | - cmake -S. -B build -DCMAKE_BUILD_TYPE=Debug + cmake -S. -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_WEB_SERVER=OFF cmake --build build -j4 - name: Run tests run: | diff --git a/.gitignore b/.gitignore index 66dea9c9c..420465cb9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /.idea/ +.venv/ build cmake/sodium_version cmake/curl_version @@ -42,6 +43,7 @@ python/datafed_pkg/datafed/Version_pb2.py python/datafed_pkg/datafed/__pycache__/ python/datafed_pkg/dist/ web/package.json +repository/gridftp/globus5/authz/mock_core/Version.hpp repository/gridftp/globus5/authz/source/Version.hpp repository/server/Version.hpp scripts/globus/datafed-home-repo.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9370351be..5d07be53b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,6 +22,8 @@ include: - local: .gitlab/stage_provision_client.yml - local: .gitlab/stage_image_check.yml - local: .gitlab/stage_build.yml + - local: .gitlab/stage_test.yml + - local: .gitlab/stage_unit.yml - local: .gitlab/end_to_end.yml stages: @@ -34,9 +36,12 @@ stages: - provision-client - image-check - build + - test # Required for gitlab sast templates + - unit - end-to-end-setup-arango - end-to-end-setup - end-to-end-test + - end-to-end-test-finish-signal - log - deploy-pypi-package @@ -50,3 +55,4 @@ variables: HARBOR_USER: 'robot$$datafed+harbor_datafed_gitlab_ci_registry_2' REGISTRY: 'camden.ornl.gov' DATAFED_DEPENDENCIES_INSTALL_PATH: "/shared/install" + DOCKER_TLS_CERTDIR: "" # Required for running docker in docker diff --git a/.gitlab/build/build_core_image.yml b/.gitlab/build/build_core_image.yml index 711d279e2..1e162cabc 100644 --- a/.gitlab/build/build_core_image.yml +++ b/.gitlab/build/build_core_image.yml @@ -9,10 +9,12 @@ build-core: extends: .docker_build_script stage: build variables: - IMAGE_TAG: "datafed/core" + PROJECT: "datafed" + COMPONENT: "core" GIT_STRATEGY: clone DOCKER_FILE_PATH: "core/docker/Dockerfile" DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + BUILD_INTERMEDIATE: "FALSE" tags: - ci-datafed-core - docker @@ -31,8 +33,21 @@ retag-image: extends: .docker_retag_image stage: build variables: - IMAGE_TAG: "datafed/core" + PROJECT: "datafed" + COMPONENT: "core" GIT_STRATEGY: clone DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + BUILD_INTERMEDIATE: "FALSE" tags: - docker + rules: + - changes: + - docker/**/* + - scripts/**/* + - core/**/* + - common/**/* + - CMakeLists.txt + - cmake/**/* + - .gitlab-ci.yml + when: never + - when: on_success diff --git a/.gitlab/build/build_foxx_image.yml b/.gitlab/build/build_foxx_image.yml index d91794276..1b20c4041 100644 --- a/.gitlab/build/build_foxx_image.yml +++ b/.gitlab/build/build_foxx_image.yml @@ -9,27 +9,46 @@ build-foxx: extends: .docker_build_script stage: build variables: - IMAGE_TAG: "datafed/foxx" + PROJECT: "datafed" + COMPONENT: "foxx" GIT_STRATEGY: clone DOCKER_FILE_PATH: "docker/Dockerfile.foxx" DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + BUILD_INTERMEDIATE: "FALSE" tags: - docker rules: - changes: - docker/**/* - scripts/**/* - - web/**/* + - cmake/**/* + - core/database/**/* + - core/CMakeLists.txt - common/proto/**/* - .gitlab-ci.yml + - CMakeLists.txt when: on_success retag-image: extends: .docker_retag_image stage: build variables: - IMAGE_TAG: "datafed/foxx" + PROJECT: "datafed" + COMPONENT: "foxx" GIT_STRATEGY: clone DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + BUILD_INTERMEDIATE: "FALSE" tags: - docker + rules: + - changes: + - docker/**/* + - scripts/**/* + - cmake/**/* + - core/database/**/* + - core/CMakeLists.txt + - common/proto/**/* + - .gitlab-ci.yml + - CMakeLists.txt + when: never + - when: on_success diff --git a/.gitlab/build/build_gcs_base_image.yml b/.gitlab/build/build_gcs_base_image.yml index 13f3b68ad..8e8b2d01b 100644 --- a/.gitlab/build/build_gcs_base_image.yml +++ b/.gitlab/build/build_gcs_base_image.yml @@ -8,10 +8,12 @@ include: build-gcs-base: stage: build variables: - IMAGE_TAG: "datafed/gcs-base" + PROJECT: "datafed" + COMPONENT: "gcs-base" GIT_SUBMODULE_STRATEGY: recursive GIT_STRATEGY: clone DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + BUILD_INTERMEDIATE: "FALSE" tags: - ci-datafed-globus - docker @@ -31,28 +33,41 @@ build-gcs-base: - cd "external/globus-connect-server-deploy/docker" - git checkout "$DATAFED_GCS_SUBMODULE_VERSION" - docker login "${REGISTRY}" -u "${HARBOR_USER}" -p "${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - - docker build --progress plain -t "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:latest" - < "./docker-files/Dockerfile.ubuntu-20.04" - - docker tag "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:latest" "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:$CI_COMMIT_SHA" - - export DATAFED_HARBOR_REPOSITORY="${IMAGE_TAG}-${BRANCH_LOWER}" + - docker build --no-cache --progress plain -t "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:latest" - < "./docker-files/Dockerfile.ubuntu-20.04" + - docker tag "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:latest" "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:$CI_COMMIT_SHA" + - export DATAFED_HARBOR_REPOSITORY="${COMPONENT}-${BRANCH_LOWER}" - export DATAFED_HARBOR_USERNAME="${HARBOR_USER}" - export DATAFED_HARBOR_PASSWORD="${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:latest" - - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + - docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" + - docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + - cd "${CI_PROJECT_DIR}" - | - while [ "$(${CI_PROJECT_DIR}/scripts/ci_harbor_artifact_count.sh)" == "0" ]; do + while [ "$(${CI_PROJECT_DIR}/scripts/ci_harbor_artifact_count.sh -r ${DATAFED_HARBOR_REPOSITORY})" == "0" ]; do echo "Artifact missing from harbor..." - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:latest" - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" + docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" sleep 5 # Optional: Add a sleep to avoid busy waiting done - - cat "./harbor_check.log" + - cat "${CI_PROJECT_DIR}/harbor_check.log" retag-image: extends: .docker_retag_image stage: build variables: - IMAGE_TAG: "datafed/gcs-base" + PROJECT: "datafed" + COMPONENT: "gcs-base" GIT_STRATEGY: clone DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + BUILD_INTERMEDIATE: "FALSE" tags: - docker + rules: + - changes: + - docker/**/* + - scripts/**/* + - common/**/* + - .gitlab-ci.yml + - CMakeLists.txt + - cmake/**/* + when: never + - when: on_success diff --git a/.gitlab/build/build_gcs_image.yml b/.gitlab/build/build_gcs_image.yml index fce4840a3..b2da9fea7 100644 --- a/.gitlab/build/build_gcs_image.yml +++ b/.gitlab/build/build_gcs_image.yml @@ -8,9 +8,11 @@ include: build-gcs: stage: build variables: - IMAGE_TAG: "datafed/gcs" + PROJECT: "datafed" + COMPONENT: "gcs" GIT_STRATEGY: clone DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + BUILD_INTERMEDIATE: "FALSE" tags: - ci-datafed-globus - docker @@ -24,35 +26,53 @@ build-gcs: - cmake/**/* - repository/docker/entrypoint_authz.sh - repository/docker/Dockerfile.gcs + - repository/CMakeLists.txt + - repository/gridftp/**/* when: on_success script: - BRANCH_LOWER=$(echo "$CI_COMMIT_REF_NAME" | tr '[:upper:]' '[:lower:]') - echo "$BRANCH_LOWER" - - ./scripts/generate_datafed.sh + - "${CI_PROJECT_DIR}/scripts/generate_datafed.sh" - docker login "${REGISTRY}" -u "${HARBOR_USER}" -p "${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - - docker build --build-arg DEPENDENCIES="${REGISTRY}/datafed/dependencies-${BRANCH_LOWER}:latest" --build-arg RUNTIME="${REGISTRY}/datafed/runtime-${BRANCH_LOWER}:latest" --build-arg GCS_IMAGE="${REGISTRY}/datafed/gcs-base-${BRANCH_LOWER}:latest" -f repository/docker/Dockerfile.gcs -t "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:latest" . - - docker tag "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:latest" "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:$CI_COMMIT_SHA" - - export DATAFED_HARBOR_REPOSITORY="${IMAGE_TAG}-${BRANCH_LOWER}" + - docker build --build-arg DEPENDENCIES="${REGISTRY}/datafed/dependencies-${BRANCH_LOWER}:latest" --build-arg RUNTIME="${REGISTRY}/datafed/runtime-${BRANCH_LOWER}:latest" --build-arg GCS_IMAGE="${REGISTRY}/datafed/gcs-base-${BRANCH_LOWER}:latest" -f repository/docker/Dockerfile.gcs -t "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:latest" . + - docker tag "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:latest" "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:$CI_COMMIT_SHA" + - export DATAFED_HARBOR_REPOSITORY="${COMPONENT}-${BRANCH_LOWER}" - export DATAFED_HARBOR_USERNAME="${HARBOR_USER}" - export DATAFED_HARBOR_PASSWORD="${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:latest" - - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + - docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" + - docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" - | - while [ "$(./scripts/ci_harbor_artifact_count.sh)" == "0" ]; do + while [ "$(${CI_PROJECT_DIR}/scripts/ci_harbor_artifact_count.sh -r ${DATAFED_HARBOR_REPOSITORY})" == "0" ]; do echo "Artifact missing from harbor..." - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:latest" - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" + docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" sleep 5 # Optional: Add a sleep to avoid busy waiting done - - cat "./harbor_check.log" + - cat "${CI_PROJECT_DIR}/harbor_check.log" retag-image: extends: .docker_retag_image stage: build variables: - IMAGE_TAG: "datafed/gcs" + PROJECT: "datafed" + COMPONENT: "gcs" GIT_STRATEGY: clone DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + BUILD_INTERMEDIATE: "FALSE" tags: - ci-datafed-globus - docker + rules: + - changes: + - docker/**/* + - scripts/**/* + - common/**/* + - .gitlab-ci.yml + - CMakeLists.txt + - cmake/**/* + - repository/docker/entrypoint_authz.sh + - repository/docker/Dockerfile.gcs + - repository/CMakeLists.txt + - repository/gridftp/**/* + when: never + - when: on_success diff --git a/.gitlab/build/build_repo_image.yml b/.gitlab/build/build_repo_image.yml index 4ef4a492e..059b30745 100644 --- a/.gitlab/build/build_repo_image.yml +++ b/.gitlab/build/build_repo_image.yml @@ -9,10 +9,12 @@ build-repo: extends: .docker_build_script stage: build variables: - IMAGE_TAG: "datafed/repo" + PROJECT: "datafed" + COMPONENT: "repo" GIT_STRATEGY: clone DOCKER_FILE_PATH: "repository/docker/Dockerfile" DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + BUILD_INTERMEDIATE: "FALSE" tags: - ci-datafed-repo - docker @@ -20,17 +22,35 @@ build-repo: - changes: - docker/**/* - scripts/**/* - - web/**/* - common/proto/**/* - .gitlab-ci.yml + - CMakeLists.txt + - cmake/**/* + - repository/CMakeLists.txt + - repository/server/**/* when: on_success retag-image: extends: .docker_retag_image stage: build variables: - IMAGE_TAG: "datafed/repo" + PROJECT: "datafed" + COMPONENT: "repo" GIT_STRATEGY: clone DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + BUILD_INTERMEDIATE: "FALSE" tags: - docker + rules: + - changes: + - docker/**/* + - scripts/**/* + - common/proto/**/* + - .gitlab-ci.yml + - CMakeLists.txt + - cmake/**/* + - repository/CMakeLists.txt + - repository/server/**/* + when: never + - when: on_success + diff --git a/.gitlab/build/build_ws_image.yml b/.gitlab/build/build_ws_image.yml index f9253f8db..6c710caa0 100644 --- a/.gitlab/build/build_ws_image.yml +++ b/.gitlab/build/build_ws_image.yml @@ -9,10 +9,14 @@ build-ws: extends: .docker_build_script stage: build variables: - IMAGE_TAG: "datafed/ws" + PROJECT: "datafed" + COMPONENT: "ws" GIT_STRATEGY: clone DOCKER_FILE_PATH: "web/docker/Dockerfile" DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + BUILD_INTERMEDIATE: "TRUE" + INTERMEDIATE_TARGET: "ws-build" # Name of the layer in the dockerfile + INTERMEDIATE_LAYER_NAME: "build" tags: - ci-datafed-core - docker @@ -21,16 +25,33 @@ build-ws: - docker/**/* - scripts/**/* - web/**/* + - cmake/**/* - common/proto/**/* - .gitlab-ci.yml + - CMakeLists.txt when: on_success retag-image: extends: .docker_retag_image stage: build variables: - IMAGE_TAG: "datafed/ws" + PROJECT: "datafed" + COMPONENT: "ws" GIT_STRATEGY: clone DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + BUILD_INTERMEDIATE: "TRUE" + INTERMEDIATE_TARGET: "ws-build" # Name of the layer in the dockerfile + INTERMEDIATE_LAYER_NAME: "build" tags: - docker + rules: + - changes: + - docker/**/* + - scripts/**/* + - web/**/* + - cmake/**/* + - common/proto/**/* + - .gitlab-ci.yml + - CMakeLists.txt + when: never + - when: on_success diff --git a/.gitlab/build/force_build_core_image.yml b/.gitlab/build/force_build_core_image.yml index 9525dc434..4458ada62 100644 --- a/.gitlab/build/force_build_core_image.yml +++ b/.gitlab/build/force_build_core_image.yml @@ -9,10 +9,12 @@ build-core: extends: .docker_build_script stage: build variables: - IMAGE_TAG: "datafed/core" + PROJECT: "datafed" + COMPONENT: "core" GIT_STRATEGY: clone DOCKER_FILE_PATH: "core/docker/Dockerfile" DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + BUILD_INTERMEDIATE: "FALSE" tags: - ci-datafed-core - docker diff --git a/.gitlab/build/force_build_foxx_image.yml b/.gitlab/build/force_build_foxx_image.yml index efd851f6e..afe90f1e6 100644 --- a/.gitlab/build/force_build_foxx_image.yml +++ b/.gitlab/build/force_build_foxx_image.yml @@ -9,9 +9,11 @@ build-foxx: extends: .docker_build_script stage: build variables: - IMAGE_TAG: "datafed/foxx" + PROJECT: "datafed" + COMPONENT: "foxx" GIT_STRATEGY: clone DOCKER_FILE_PATH: "docker/Dockerfile.foxx" DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + BUILD_INTERMEDIATE: "FALSE" tags: - docker diff --git a/.gitlab/build/force_build_gcs_base_image.yml b/.gitlab/build/force_build_gcs_base_image.yml index 9d948646b..6499ed226 100644 --- a/.gitlab/build/force_build_gcs_base_image.yml +++ b/.gitlab/build/force_build_gcs_base_image.yml @@ -5,7 +5,8 @@ stages: build-gcs-base: stage: build variables: - IMAGE_TAG: "datafed/gcs-base" + PROJECT: "datafed" + COMPONENT: "gcs-base" GIT_SUBMODULE_STRATEGY: recursive GIT_STRATEGY: clone DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count @@ -19,18 +20,19 @@ build-gcs-base: - cd "external/globus-connect-server-deploy/docker" - git checkout "$DATAFED_GCS_SUBMODULE_VERSION" - docker login "${REGISTRY}" -u "${HARBOR_USER}" -p "${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - - docker build --progress plain -t "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:latest" - < "./docker-files/Dockerfile.ubuntu-20.04" - - docker tag "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:latest" "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:$CI_COMMIT_SHA" - - export DATAFED_HARBOR_REPOSITORY="${IMAGE_TAG}-${BRANCH_LOWER}" + - docker build --no-cache --progress plain -t "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:latest" - < "./docker-files/Dockerfile.ubuntu-20.04" + - docker tag "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:latest" "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:$CI_COMMIT_SHA" + - export DATAFED_HARBOR_REPOSITORY="${COMPONENT}-${BRANCH_LOWER}" - export DATAFED_HARBOR_USERNAME="${HARBOR_USER}" - export DATAFED_HARBOR_PASSWORD="${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:latest" - - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + - docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" + - docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + - cd "${CI_PROJECT_DIR}" - | - while [ "$(${CI_PROJECT_DIR}/scripts/ci_harbor_artifact_count.sh)" == "0" ]; do + while [ "$(${CI_PROJECT_DIR}/scripts/ci_harbor_artifact_count.sh -r ${DATAFED_HARBOR_REPOSITORY})" == "0" ]; do echo "Artifact missing from harbor..." - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:latest" - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" + docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" sleep 5 # Optional: Add a sleep to avoid busy waiting done - - cat "./harbor_check.log" + - cat "${CI_PROJECT_DIR}/harbor_check.log" diff --git a/.gitlab/build/force_build_gcs_image.yml b/.gitlab/build/force_build_gcs_image.yml index b35f089cb..4cae5d148 100644 --- a/.gitlab/build/force_build_gcs_image.yml +++ b/.gitlab/build/force_build_gcs_image.yml @@ -5,9 +5,11 @@ stages: build-gcs: stage: build variables: - IMAGE_TAG: "datafed/gcs" + PROJECT: "datafed" + COMPONENT: "gcs" GIT_STRATEGY: clone DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + BUILD_INTERMEDIATE: "FALSE" tags: - ci-datafed-globus - docker @@ -16,19 +18,19 @@ build-gcs: - echo "$BRANCH_LOWER" - ./scripts/generate_datafed.sh - docker login "${REGISTRY}" -u "${HARBOR_USER}" -p "${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - - docker build --build-arg DEPENDENCIES="${REGISTRY}/datafed/dependencies-${BRANCH_LOWER}:latest" --build-arg RUNTIME="${REGISTRY}/datafed/runtime-${BRANCH_LOWER}:latest" --build-arg GCS_IMAGE="${REGISTRY}/datafed/gcs-base-${BRANCH_LOWER}:latest" -f repository/docker/Dockerfile.gcs -t "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:latest" . - - docker tag "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:latest" "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:$CI_COMMIT_SHA" - - export DATAFED_HARBOR_REPOSITORY="${IMAGE_TAG}-${BRANCH_LOWER}" + - docker build --no-cache --build-arg DEPENDENCIES="${REGISTRY}/datafed/dependencies-${BRANCH_LOWER}:latest" --build-arg RUNTIME="${REGISTRY}/datafed/runtime-${BRANCH_LOWER}:latest" --build-arg GCS_IMAGE="${REGISTRY}/datafed/gcs-base-${BRANCH_LOWER}:latest" -f repository/docker/Dockerfile.gcs -t "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:latest" . + - docker tag "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:latest" "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:$CI_COMMIT_SHA" + - export DATAFED_HARBOR_REPOSITORY="${COMPONENT}-${BRANCH_LOWER}" - export DATAFED_HARBOR_USERNAME="${HARBOR_USER}" - export DATAFED_HARBOR_PASSWORD="${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:latest" - - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + - docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" + - docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" - | - while [ "$(./scripts/ci_harbor_artifact_count.sh)" == "0" ]; do + while [ "$(${CI_PROJECT_DIR}/scripts/ci_harbor_artifact_count.sh -r ${DATAFED_HARBOR_REPOSITORY})" == "0" ]; do echo "Artifact missing from harbor..." - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:latest" - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" + docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" sleep 5 # Optional: Add a sleep to avoid busy waiting done - - cat "./harbor_check.log" + - cat "${CI_PROJECT_DIR}/harbor_check.log" diff --git a/.gitlab/build/force_build_repo_image.yml b/.gitlab/build/force_build_repo_image.yml index 8b244369f..3c21cf10e 100644 --- a/.gitlab/build/force_build_repo_image.yml +++ b/.gitlab/build/force_build_repo_image.yml @@ -9,10 +9,12 @@ build-repo: extends: .docker_build_script stage: build variables: - IMAGE_TAG: "datafed/repo" + PROJECT: "datafed" + COMPONENT: "repo" GIT_STRATEGY: clone DOCKER_FILE_PATH: "repository/docker/Dockerfile" DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + BUILD_INTERMEDIATE: "FALSE" tags: - ci-datafed-repo - docker diff --git a/.gitlab/build/force_build_ws_image.yml b/.gitlab/build/force_build_ws_image.yml index dde2cf21f..0355bfbc8 100644 --- a/.gitlab/build/force_build_ws_image.yml +++ b/.gitlab/build/force_build_ws_image.yml @@ -9,10 +9,14 @@ build-ws: extends: .docker_build_script stage: build variables: - IMAGE_TAG: "datafed/ws" + PROJECT: "datafed" + COMPONENT: "ws" GIT_STRATEGY: clone DOCKER_FILE_PATH: "web/docker/Dockerfile" DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + BUILD_INTERMEDIATE: "TRUE" + INTERMEDIATE_TARGET: "ws-build" # Name of the layer in the dockerfile + INTERMEDIATE_LAYER_NAME: "build" tags: - ci-datafed-core - docker diff --git a/.gitlab/common.yml b/.gitlab/common.yml index 4508d6c8e..d9de9589f 100644 --- a/.gitlab/common.yml +++ b/.gitlab/common.yml @@ -1,5 +1,63 @@ --- +# Description +# +# This file contains several anchors and templates that are reusued across the +# project. A definition of the variables that are used in this file are shown +# below +# +# Variables +# +# DOCKER_FILE_PATH +# The path to the 'Dockerfile' used in image building, +# assuming you are located at the root of the project. e.g. +# ./web/docker/Dockerfile +# +# REGISTRY +# The name of the image registry build images are placed in. i.e. camden.ornl.gov +# +# PROJECT +# The name of the project in the image registry will probably +# be datafed, used to to upload to the right registry location +# +# DATAFED_HARBOR_REPOSITORY +# This is the name of the image that is being checked. e.g. ws-devel for the +# web image created on the development branch +# +# CI_COMMIT_REF_NAME +# Used for getting the branch name, which is used in docker image tagging +# +# REGISTRY +# The name of the image registry build images are placed in +# +# PROJECT +# The name of the project in the image registry will probably +# be datafed, used to to upload to the right registry location +# +# COMPONENT +# The component of datafed associated with the image, used to tag the image. +# +# HARBOR_USER +# The user account needed for pushing to the harbor image registry +# +# HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN +# The token needed to upload the image to the registry. +# +# BUILD_INTERMEDIATE +# A boolean value indicating if there is an intermediate image that needs to +# be pushed to the image repository. Sometimes this is wanted for testing. For +# instance you may want an intermediate file that has all the build files, where +# the final image does not contain this files. Can be set to string "TRUE" or +# "FALSE" +# +# INTERMEDIATE_TARGET +# This is the name of the layer that exists in the Dockerfile that we are tagging +# an intermediate docker image after. +# +# INTERMEDIATE_LAYER_NAME +# This is used when tagging the image to help differentiate different layers + + .image_check: tags: - docker @@ -9,9 +67,16 @@ docker login "${REGISTRY}" -u "${HARBOR_USER}" -p "${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" FORCE_BUILD="FALSE" set +e - docker pull --quiet "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:latest" + docker pull --quiet "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:latest" if [ $? -eq 0 ]; then echo "Image exists"; else FORCE_BUILD="TRUE"; fi; set -e + if [ "${BUILD_INTERMEDIATE}" == "TRUE" ] + then + set +e + docker pull --quiet "${REGISTRY}/${PROJECT}/${COMPONENT}-${INTERMEDIATE_LAYER_NAME}-${BRANCH_LOWER}:latest" + if [ $? -eq 0 ]; then echo "Image exists"; else FORCE_BUILD="TRUE"; fi; + set -e + fi if [ "$FORCE_BUILD" == "TRUE" ] then cp .gitlab/build/force_build_${COMPONENT}_image.yml ${COMPONENT}_image.yml @@ -28,100 +93,253 @@ reports: dotenv: build.env +# The purpose of this anchor is to check that an image has been uploaded correctly +# to the registry and if it has not attempt to upload it again. +# +# Inputs +# +# REGISTRY - needed to push to registry and ci_harbor_artifact_count +# PROJECT - needed to push to registry and ci_harbor_artifact_count +# DATAFED_HARBOR_REPOSITORY - needed to run ci_harbor_artifact_count and push to registry +# DATAFED_HARBOR_USERNAME - needed to run ci_harbor_artifact_count +# DATAFED_HARBOR_PASSWORD - needed to run ci_harbor_artifact_count +.verify_image_upload: &verify_image_upload | + first_iteration="TRUE" + artifact_count="0" + while [ "$artifact_count" == "0" ]; do + artifact_count=$( "${CI_PROJECT_DIR}/scripts/ci_harbor_artifact_count.sh" -r "${DATAFED_HARBOR_REPOSITORY}") + error_code="$?" + if [ "$error_code" -ne 0 ] + then + echo "Error encountered in ci_harbor_artifact_count $error_code" + cat "${CI_PROJECT_DIR}/harbor_check.log" + exit 1 + fi; + echo "Artifact missing from harbor..." + docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" + docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + if [ "$first_iteration" == "FALSE" ] + then + sleep 5 # Optional: Add a sleep to avoid busy waiting + else + first_iteration="FALSE" + fi + done + # NOTE # # Cases have been observed where an image has been pushed to the image registry but # but the image for some reason is not registered with the Harbor instance. The # retry loop is used to retry pushing to the registry to add some resliency to the # ci pipeline in the case of poor networking issues while attempting to upload +# +# Outputs +# +# DATAFED_HARBOR_USERNAME - needed to run verify_image_upload +# DATAFED_HARBOR_PASSWORD - needed to run verify_image_upload .docker_base_build_script: script: - BRANCH_LOWER=$(echo "$CI_COMMIT_REF_NAME" | tr '[:upper:]' '[:lower:]') - docker system prune -f - - docker build -f "${DOCKER_FILE_PATH}" -t "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:latest" . - - docker tag "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:latest" "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:$CI_COMMIT_SHA" + - docker build --no-cache -f "${DOCKER_FILE_PATH}" -t "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:latest" . + - echo "Tagging ${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:latest as ${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:$CI_COMMIT_SHA" + - docker tag "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:latest" "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:$CI_COMMIT_SHA" - docker login "${REGISTRY}" -u "${HARBOR_USER}" -p "${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - - export DATAFED_HARBOR_REPOSITORY="${IMAGE_TAG}-${BRANCH_LOWER}" + - export DATAFED_HARBOR_REPOSITORY="${COMPONENT}-${BRANCH_LOWER}" - export DATAFED_HARBOR_USERNAME="${HARBOR_USER}" - export DATAFED_HARBOR_PASSWORD="${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:latest" - - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" - - | - first_iteration="TRUE" - while [ "$(./scripts/ci_harbor_artifact_count.sh)" == "0" ]; do - echo "Artifact missing from harbor..." - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:latest" - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" - if [ "$first_iteration" == "FALSE" ] - then - sleep 5 # Optional: Add a sleep to avoid busy waiting - else - first_iteration="FALSE" - fi - done - - cat "./harbor_check.log" + - docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" + - docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + - *verify_image_upload + after_script: + # Needed if the harbor check script errors out. + - if [ -f "${CI_PROJECT_DIR}/harbor_check.log" ]; then cat "${CI_PROJECT_DIR}/harbor_check.log"; fi; +# Variables that need to be defined to use the anchor. +# +# Inputs +# +# COMPONENT - used for image tag +# DOCKER_FILE_PATH - used to build the image +# REGISTRY - used for image tag and pushing to registry +# PROJECT - used for image tag and pushing to registry +# +# Outputs +# +# DATAFED_HARBOR_REPOSITORY +.build_image: &build_image | + BRANCH_LOWER=$(echo "$CI_COMMIT_REF_NAME" | tr '[:upper:]' '[:lower:]') + export DATAFED_HARBOR_REPOSITORY="${COMPONENT}-${BRANCH_LOWER}" + docker build --no-cache --build-arg DEPENDENCIES="${REGISTRY}/datafed/dependencies-${BRANCH_LOWER}:latest" --build-arg RUNTIME="${REGISTRY}/datafed/runtime-${BRANCH_LOWER}:latest" -f "${DOCKER_FILE_PATH}" -t "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:latest" . + docker tag "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:latest" "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:$CI_COMMIT_SHA" + docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" + docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + +# Variables that need to be defined to use the anchor. +# +# Inputs +# +# INTERMEDIATE_TARGET - used to know which layer in the Dockerfile is being built +# DOCKER_FILE_PATH - used to build the image +# BUILD_INTERMEDIATE - used for to determine if intermediate needs to be retagged +# INTERMEDIATE_LAYER_NAME - used for image tag +# COMPONENT - used for image tag +# REGISTRY - used for image tag and pushing to registry +# PROJECT - used for image tag and pushing to registry +# +# Outputs +# +# DATAFED_HARBOR_REPOSITORY +# BRANCH_LOWER - lowercase name of the branch used for image tagging +.build_intermediate: &build_intermediate | + if [ "${BUILD_INTERMEDIATE}" == "TRUE" ] + then + BRANCH_LOWER=$(echo "$CI_COMMIT_REF_NAME" | tr '[:upper:]' '[:lower:]') + export DATAFED_HARBOR_REPOSITORY="${COMPONENT}-${INTERMEDIATE_LAYER_NAME}-${BRANCH_LOWER}" + docker build --no-cache --build-arg DEPENDENCIES="${REGISTRY}/${PROJECT}/dependencies-${BRANCH_LOWER}:latest" --build-arg RUNTIME="${REGISTRY}/${PROJECT}/runtime-${BRANCH_LOWER}:latest" --target "${INTERMEDIATE_TARGET}" -f "${DOCKER_FILE_PATH}" -t "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" . + echo "Tagging ${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest ${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + docker tag "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" + docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + fi + +# Variables that need to be defined to use the anchor. +# +# Inputs +# +# BUILD_INTERMEDIATE - used for to determine if intermediate needs to be retagged +# INTERMEDIATE_LAYER_NAME - used for image tag +# COMPONENT - used for image tag +# REGISTRY - used for image tag and pushing to registry +# PROJECT - used for image tag and pushing to registry +# +# Outputs +# +# DATAFED_HARBOR_REPOSITORY - the tag of the image excluding the registry and the project +# BRANCH_LOWER - lowercase name of the branch used for image tagging +.retag_intermediate: &retag_intermediate | + if [ "${BUILD_INTERMEDIATE}" == "TRUE" ] + then + echo "Branch lower" + export BRANCH_LOWER=$(echo "$CI_COMMIT_REF_NAME" | tr '[:upper:]' '[:lower:]') + echo "Harbor repo" + export DATAFED_HARBOR_REPOSITORY="${COMPONENT}-${INTERMEDIATE_LAYER_NAME}-${BRANCH_LOWER}" + echo "pull" + docker pull "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" + echo "Tagging ${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest as ${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + docker tag "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + echo "push" + docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + fi + +# Variables that need to be defined to use the anchor. +# +# Inputs +# +# COMPONENT - used for image tag +# REGISTRY - used for image tag and pushing to registry +# PROJECT - used for image tag and pushing to registry +# +# Outputs +# +# DATAFED_HARBOR_REPOSITORY - the tag of the image excluding the registry and the project +# BRANCH_LOWER - lowercase name of the branch used for image tagging +.retag_image: &retag_image | + export BRANCH_LOWER=$(echo "$CI_COMMIT_REF_NAME" | tr '[:upper:]' '[:lower:]') + export DATAFED_HARBOR_REPOSITORY="${COMPONENT}-${BRANCH_LOWER}" + docker pull "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" + echo "Tagging ${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest as ${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + docker tag "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:latest" "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + docker push "${REGISTRY}/${PROJECT}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" + +# The following are a list of variables that are needed to use the below template +# +# Inputs +# +# CI_COMMIT_REF_NAME +# REGISTRY +# PROJECT +# COMPONENT +# HARBOR_USER +# HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN +# BUILD_INTERMEDIATE +# +# Outputs +# +# DATAFED_HARBOR_REPOSITORY +# DATAFED_HARBOR_USERNAME +# DATAFED_HARBOR_PASSWORD .docker_build_script: script: - - BRANCH_LOWER=$(echo "$CI_COMMIT_REF_NAME" | tr '[:upper:]' '[:lower:]') - - echo "$BRANCH_LOWER" - - ./scripts/generate_datafed.sh - - docker login "${REGISTRY}" -u "${HARBOR_USER}" -p "${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - - docker build --build-arg DEPENDENCIES="${REGISTRY}/datafed/dependencies-${BRANCH_LOWER}:latest" --build-arg RUNTIME="${REGISTRY}/datafed/runtime-${BRANCH_LOWER}:latest" -f ${DOCKER_FILE_PATH} -t "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:latest" . - - docker tag "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:latest" "${REGISTRY}/${IMAGE_TAG}-${BRANCH_LOWER}:$CI_COMMIT_SHA" - - export DATAFED_HARBOR_REPOSITORY="${IMAGE_TAG}-${BRANCH_LOWER}" - export DATAFED_HARBOR_USERNAME="${HARBOR_USER}" - export DATAFED_HARBOR_PASSWORD="${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:latest" - - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" - - | - first_iteration="TRUE" - while [ "$(./scripts/ci_harbor_artifact_count.sh)" == "0" ]; do - echo "Artifact missing from harbor..." - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:latest" - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" - if [ "$first_iteration" == "FALSE" ] - then - sleep 5 # Optional: Add a sleep to avoid busy waiting - else - first_iteration="FALSE" - fi - done - - cat "./harbor_check.log" + - ./scripts/generate_datafed.sh + - docker login "${REGISTRY}" -u "${HARBOR_USER}" -p "${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" + - *build_image + - *verify_image_upload + - *build_intermediate + - *verify_image_upload + after_script: + # Needed if the harbor check script errors out. + - if [ -f "${CI_PROJECT_DIR}/harbor_check.log" ]; then cat "${CI_PROJECT_DIR}/harbor_check.log"; fi; .error_logs_client_end_to_end: stage: log script: - BRANCH_LOWER=$(echo "$CI_COMMIT_REF_NAME" | tr '[:upper:]' '[:lower:]') - - docker logs $(docker ps --filter "ancestor=${REGISTRY}/${IMAGE_TAG}${BRANCH_LOWER}" --format "{{.Names}}") - rules: - - when: always + - FULL_IMAGE_NAME="${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}" + - echo "Full image name is $FULL_IMAGE_NAME" + - ANCESTOR_CONTAINERS=$(docker ps -a --filter "ancestor=${FULL_IMAGE_NAME}" --format "{{.Names}}") + - echo "${ANCESTOR_CONTAINERS}" + # It is possible to return more than one container with the same ancestor + # for instance if two different branches have the exact same build but + # different names. Or one image was built on top of another and share the + # same base. + - MATCHING_CONTAINERS=$( echo "$ANCESTOR_CONTAINERS" | grep "${COMPONENT}-${BRANCH_LOWER}" || echo "") + - > + if [ -z "$MATCHING_CONTAINERS" ]; then + echo "No matching containers found for image ${FULL_IMAGE_NAME} and component ${COMPONENT}-${BRANCH_LOWER}"; + else + echo "Getting log output for the following."; + echo "$MATCHING_CONTAINERS"; + while IFS= read -r container_id; do + if [ -n "$container_id" ]; then # Ensure the line is not empty + echo "--- Logs for container: $container_id ---"; + docker logs "$container_id"; + echo "--- End of logs for container: $container_id ---"; + echo; # Add a blank line for separation + fi + done <<< "$MATCHING_CONTAINERS" # Feed the variable's content as stdin to the while loop + fi -# In the case that we are not needing to actually rebuild the image we want to retag the image that already exists -# in harbor with the current commit, this is so that when we are running tests that are dependent on the container -# we know that it is the right container. +# In the case that we are not needing to actually rebuild the image we want to +# retag the image that already exists in harbor with the current commit, this +# is so that when we are running tests that are dependent on the container we +# know that it is the right container. +# +# Inputs +# +# CI_COMMIT_SHA - for tagging container +# HARBOR_USER - for pushing and pulling from harbor image registry +# HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN - Token for pushing and pulling from registry +# REGISTRY +# PROJECT +# COMPONENT +# BUILD_INTERMEDIATE +# +# DATAFED_HARBOR_REPOSITORY +# DATAFED_HARBOR_USERNAME +# DATAFED_HARBOR_PASSWORD .docker_retag_image: script: - - BRANCH_LOWER=$(echo "$CI_COMMIT_REF_NAME" | tr '[:upper:]' '[:lower:]') - - export DATAFED_HARBOR_REPOSITORY="${IMAGE_TAG}-${BRANCH_LOWER}" - export DATAFED_HARBOR_IMAGE_TAG=${CI_COMMIT_SHA} - export DATAFED_HARBOR_USERNAME="${HARBOR_USER}" - export DATAFED_HARBOR_PASSWORD="${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - - echo "$BRANCH_LOWER" - docker login "${REGISTRY}" -u "${HARBOR_USER}" -p "${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - - docker pull "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:latest" - - docker tag "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:latest" "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" - - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" - - | - first_iteration="TRUE" - while [ "$(./scripts/ci_harbor_artifact_count.sh)" == "0" ]; do - echo "Artifact missing from harbor..." - docker push "${REGISTRY}/${DATAFED_HARBOR_REPOSITORY}:$CI_COMMIT_SHA" - if [ "$first_iteration" == "FALSE" ] - then - sleep 5 # Optional: Add a sleep to avoid busy waiting - else - first_iteration="FALSE" - fi - done - - cat "./harbor_check.log" + - *retag_image + - *verify_image_upload + - *retag_intermediate + - *verify_image_upload + after_script: + # Needed if the harbor check script errors out. + - if [ -f "${CI_PROJECT_DIR}/harbor_check.log" ]; then cat "${CI_PROJECT_DIR}/harbor_check.log"; fi; diff --git a/.gitlab/end_to_end.yml b/.gitlab/end_to_end.yml index 38a597b2d..9b4fa5711 100644 --- a/.gitlab/end_to_end.yml +++ b/.gitlab/end_to_end.yml @@ -15,7 +15,8 @@ end-to-end-arango-setup: end-to-end-foxx-setup: variables: - IMAGE_TAG: "datafed/foxx-" + PROJECT: "datafed" + COMPONENT: "foxx" GIT_STRATEGY: clone HOST_LOG_FILE_PATH: "/shared/logs" CONTAINER_LOG_FILE_PATH: "/datafed/logs" @@ -28,6 +29,8 @@ end-to-end-foxx-setup: script: - sudo apt-get install jq -y - BRANCH_LOWER=$(echo "$CI_COMMIT_REF_NAME" | tr '[:upper:]' '[:lower:]') + # Echo into GITLAB_ENV is needed so after_script has access + - echo "BRANCH_LOWER=${BRANCH_LOWER}" >> $GITLAB_ENV - mkdir -p "$HOST_LOG_FILE_PATH" - chmod o+w "${HOST_LOG_FILE_PATH}" - USER_ID=$(id -u) @@ -41,10 +44,14 @@ end-to-end-foxx-setup: - docker login "${REGISTRY}" -u "${HARBOR_USER}" -p "${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - ./scripts/container_stop.sh -n "foxx-" -p - random_string=$(bash -c "cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w "10" | head -n 1") + # Echo into GITLAB_ENV is needed so after_script has access + - echo "random_string=${random_string}" >> $GITLAB_ENV + - CONTAINER_NAME="foxx-${BRANCH_LOWER}-${CI_COMMIT_SHORT_SHA}-${random_string}" - echo "#!/bin/bash" > "${RUN_FILE}" - echo "docker run -d \\" >> "${RUN_FILE}" - - echo "--name \"foxx-${BRANCH_LOWER}-${CI_COMMIT_SHORT_SHA}-${random_string}\" \\" >> "${RUN_FILE}" + - echo "--name \"${CONTAINER_NAME}\" \\" >> "${RUN_FILE}" - echo "-e DATAFED_ZEROMQ_SYSTEM_SECRET=\"$CI_DATAFED_ZEROMQ_SYSTEM_SECRET\" \\" >> "${RUN_FILE}" + - echo "-e ENABLE_FOXX_TESTS=\"TRUE\" \\" >> "${RUN_FILE}" - echo "-e DATAFED_DOMAIN=\"$CI_DATAFED_DOMAIN\" \\" >> "${RUN_FILE}" - echo "-e DATAFED_DATABASE_PASSWORD=\"$CI_DATAFED_DATABASE_PASSWORD\" \\" >> "${RUN_FILE}" - echo "-e DATAFED_DATABASE_IP_ADDRESS_PORT=\"$CI_DATAFED_DATABASE_IP_ADDRESS_PORT\" \\" >> "${RUN_FILE}" @@ -53,16 +60,31 @@ end-to-end-foxx-setup: - echo "-e UID=\"$USER_ID\" \\" >> "${RUN_FILE}" - echo "-v \"${HOST_LOG_FILE_PATH}:${CONTAINER_LOG_FILE_PATH}\" \\" >> "${RUN_FILE}" - echo "-v \"./foxx_tmp:/tmp\" \\" >> "${RUN_FILE}" - - echo "-t \"${REGISTRY}/${IMAGE_TAG}${BRANCH_LOWER}:latest\"" >> "${RUN_FILE}" + - echo "-t \"${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:${CI_COMMIT_SHA}\"" >> "${RUN_FILE}" - chmod +x "${RUN_FILE}" - "./${RUN_FILE}" - sleep 10 # Make sure container is running immediately after because it is meant to # be ephermal anyway, this is not the same for the other containers - - ./scripts/container_run_test.sh -e -c "1" -t "${REGISTRY}/${IMAGE_TAG}${BRANCH_LOWER}:latest" - - while [ ! -f "foxx_tmp/.foxx_is_installed" ]; do echo "Waiting for foxx_tmp/.foxx_is_installed"; sleep 10; done + - ./scripts/container_run_test.sh -e -c "1" -t "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:${CI_COMMIT_SHA}" + - while [ ! -f "foxx_tmp/.foxx_is_installed" ]; do + # Container is found to be running + - if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then + - echo "Waiting for foxx_tmp/.foxx_is_installed" + - docker logs "foxx-${BRANCH_LOWER}-${CI_COMMIT_SHORT_SHA}-${random_string}"; + - sleep 10 + - else + # Container is not running get exit code + - exit_code=$(docker inspect -f '{{.State.ExitCode}}' "$CONTAINER_NAME") + - if [ "$exit_code" != "0" ]; then + - docker logs "foxx-${BRANCH_LOWER}-${CI_COMMIT_SHORT_SHA}-${random_string}"; + - exit "$exit_code" + - fi + - fi + - done - ./scripts/ci_database_health_check.sh after_script: + - docker logs "foxx-${BRANCH_LOWER}-${CI_COMMIT_SHORT_SHA}-${random_string}"; - rm -rf foxx_tmp ################################################################################ @@ -79,6 +101,9 @@ end-to-end-gcs-node-clean: - ci-datafed-globus - docker script: + - mkdir -p "${DATAFED_GLOBUS_DIR}" + - cp "${CI_DATAFED_GCS_DEPLOYMENT_KEY}" "${DATAFED_GLOBUS_DIR}/deployment-key.json" + - cp "${CI_DATAFED_GCS_CLIENT_CRED}" "${DATAFED_GLOBUS_DIR}/client_cred.json" - cat "${DATAFED_GLOBUS_DIR}/deployment-key.json" | jq .node_key > "${DATAFED_GLOBUS_DIR}/node_deletion_key.json" - SECRET=$(cat "${DATAFED_GLOBUS_DIR}/deployment-key.json" | jq -r .secret) - CLIENT=$(cat "${DATAFED_GLOBUS_DIR}/deployment-key.json" | jq -r .client_id) @@ -86,7 +111,8 @@ end-to-end-gcs-node-clean: end-to-end-core-setup: variables: - IMAGE_TAG: "datafed/core-" + PROJECT: "datafed" + COMPONENT: "core" GIT_STRATEGY: clone HOST_LOG_FILE_PATH: "/shared/logs" CONTAINER_LOG_FILE_PATH: "/datafed/logs" @@ -123,20 +149,22 @@ end-to-end-core-setup: - echo "-e DATAFED_DATABASE_IP_ADDRESS_PORT=\"$CI_DATAFED_DATABASE_IP_ADDRESS_PORT\" \\" >> run_core.sh - echo "-e DATAFED_DEFAULT_LOG_PATH=\"$CONTAINER_LOG_FILE_PATH\" \\" >> run_core.sh - echo "-e UID=\"$USER_ID\" \\" >> run_core.sh + - echo "-e DATAFED_CORE_LOG_LEVEL=\"$DATAFED_CORE_LOG_LEVEL\" \\" >> run_core.sh - echo "-p 7513:7513 \\" >> run_core.sh - echo "-p 7512:7512 \\" >> run_core.sh - echo "-v \"${HOST_LOG_FILE_PATH}:${CONTAINER_LOG_FILE_PATH}\" \\" >> run_core.sh - echo "-v \"/shared/keys/datafed-core-key.pub\":/opt/datafed/keys/datafed-core-key.pub \\" >> run_core.sh - echo "-v \"/shared/keys/datafed-core-key.priv\":/opt/datafed/keys/datafed-core-key.priv \\" >> run_core.sh - - echo "-t \"${REGISTRY}/${IMAGE_TAG}${BRANCH_LOWER}:latest\"" >> run_core.sh + - echo "-t \"${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:${CI_COMMIT_SHA}\"" >> run_core.sh - chmod +x run_core.sh - ./run_core.sh - sleep 10 - - ./scripts/container_run_test.sh -e -c "1" -t "${REGISTRY}/${IMAGE_TAG}${BRANCH_LOWER}:latest" + - ./scripts/container_run_test.sh -e -c "1" -t "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:${CI_COMMIT_SHA}" end-to-end-ws-setup: variables: - IMAGE_TAG: "datafed/ws-" + PROJECT: "datafed" + COMPONENT: "ws" GIT_STRATEGY: clone HOST_LOG_FILE_PATH: "/shared/logs" CONTAINER_LOG_FILE_PATH: "/datafed/logs" @@ -186,17 +214,18 @@ end-to-end-ws-setup: - echo "-v \"/shared/keys/datafed-core-key.pub:/opt/datafed/keys/datafed-core-key.pub\" \\" >> run_web.sh - echo "-v \"${DATAFED_WEB_CERT_PATH}:/opt/datafed/keys/${DATAFED_WEB_CERT_NAME}\" \\" >> run_web.sh - echo "-v \"${DATAFED_WEB_KEY_PATH}:/opt/datafed/keys/${DATAFED_WEB_KEY_NAME}\" \\" >> run_web.sh - - echo "-t \"${REGISTRY}/${IMAGE_TAG}${BRANCH_LOWER}:latest\" " >> run_web.sh + - echo "-t \"${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:${CI_COMMIT_SHA}\" " >> run_web.sh - chmod +x run_web.sh - ./run_web.sh - sleep 30 - - ./scripts/container_run_test.sh -e -c "1" -t "${REGISTRY}/${IMAGE_TAG}${BRANCH_LOWER}:latest" + - ./scripts/container_run_test.sh -e -c "1" -t "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:${CI_COMMIT_SHA}" # Repo server currently will crash on startup if it cannot connect to the core # server. end-to-end-repo-setup: variables: - IMAGE_TAG: "datafed/repo-" + PROJECT: "datafed" + COMPONENT: "repo" GIT_STRATEGY: clone HOST_LOG_FILE_PATH: "/shared/logs" CONTAINER_LOG_FILE_PATH: "/datafed/logs" @@ -221,8 +250,8 @@ end-to-end-repo-setup: - docker login "${REGISTRY}" -u "${HARBOR_USER}" -p "${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - ./scripts/container_stop.sh -n "repo-" -p - random_string=$(bash -c "cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w "10" | head -n 1") - - cat $CI_DATAFED_CORE_PUB_KEY > /shared/datafed-repo-key.pub - - cat $CI_DATAFED_CORE_PRIV_KEY > /shared/datafed-repo-key.priv + - cat $CI_DATAFED_REPO_PUB_KEY > /shared/datafed-repo-key.pub + - cat $CI_DATAFED_REPO_PRIV_KEY > /shared/datafed-repo-key.priv - echo "#!/bin/bash" > "${RUN_FILE}" - echo "docker run -d \\" >> "${RUN_FILE}" - echo "--name \"repo-${BRANCH_LOWER}-${CI_COMMIT_SHORT_SHA}-${random_string}\" \\" >> "${RUN_FILE}" @@ -242,16 +271,16 @@ end-to-end-repo-setup: - echo "-v \"${DATAFED_HOST_COLLECTION_MOUNT}:/mnt/datafed\" \\" >> "${RUN_FILE}" - echo "-v \"/shared/datafed-repo-key.pub\":/opt/datafed/keys/datafed-repo-key.pub \\" >> "${RUN_FILE}" - echo "-v \"/shared/datafed-repo-key.priv\":/opt/datafed/keys/datafed-repo-key.priv \\" >> "${RUN_FILE}" - - echo "-t \"${REGISTRY}/${IMAGE_TAG}${BRANCH_LOWER}:latest\"" >> "${RUN_FILE}" + - echo "-t \"${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:${CI_COMMIT_SHA}\"" >> "${RUN_FILE}" - chmod +x "${RUN_FILE}" - ./${RUN_FILE} - sleep 10 - - ./scripts/container_run_test.sh -e -c "1" -t "${REGISTRY}/${IMAGE_TAG}${BRANCH_LOWER}:latest" + - ./scripts/container_run_test.sh -e -c "1" -t "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:${CI_COMMIT_SHA}" # Requires setting up Globus Connect Server, requires firewall exceptions on # the machine running this. -# Note we need the certificates to be available on the gcs-authz container +# Note we need the certificates to be available on the gcs container # if it is meant to be run on the same machine as the metadata services # because the Apache web server can then route traffic appropriately, if # run separate from the metadata services it should not be needed. @@ -259,7 +288,8 @@ end-to-end-repo-setup: # generated, it requires the repo server public key. end-to-end-gcs-authz-setup: variables: - IMAGE_TAG: "datafed/gcs-" + PROJECT: "datafed" + COMPONENT: "gcs" HOST_LOG_FILE_PATH: "/shared/logs" CONTAINER_LOG_FILE_PATH: "/datafed/logs" GIT_STRATEGY: clone @@ -282,13 +312,13 @@ end-to-end-gcs-authz-setup: - chown gitlab-runner "$HOST_LOG_FILE_PATH" - ./scripts/generate_datafed.sh - docker login "${REGISTRY}" -u "${HARBOR_USER}" -p "${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - - ./scripts/container_stop.sh -n "gcs-authz" -p + - ./scripts/container_stop.sh -n "${COMPONENT}" -p - random_string=$(bash -c "cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w "10" | head -n 1") - - cat $CI_DATAFED_CORE_PUB_KEY > /shared/datafed-repo-key.pub - - cat $CI_DATAFED_CORE_PRIV_KEY > /shared/datafed-repo-key.priv + - cat $CI_DATAFED_REPO_PUB_KEY > /shared/datafed-repo-key.pub + - cat $CI_DATAFED_REPO_PRIV_KEY > /shared/datafed-repo-key.priv - echo "#!/bin/bash" > run_globus.sh - echo "docker run -d \\" >> run_globus.sh - - echo "--name \"gcs-authz-${BRANCH_LOWER}-${CI_COMMIT_SHORT_SHA}-${random_string}\" \\" >> run_globus.sh + - echo "--name \"${COMPONENT}-${BRANCH_LOWER}-${CI_COMMIT_SHORT_SHA}-${random_string}\" \\" >> run_globus.sh - echo "--network host \\" >> run_globus.sh - echo "-e DATAFED_GLOBUS_APP_SECRET=\"$CI_DATAFED_GLOBUS_APP_SECRET\" \\" >> run_globus.sh - echo "-e DATAFED_GLOBUS_APP_ID=\"$CI_DATAFED_GLOBUS_APP_ID\" \\" >> run_globus.sh @@ -315,13 +345,21 @@ end-to-end-gcs-authz-setup: - echo "-v \"${DATAFED_HOST_COLLECTION_MOUNT}:/mnt/datafed\" \\" >> run_globus.sh - echo "-v \"/shared/datafed-repo-key.pub\":/opt/datafed/keys/datafed-repo-key.pub \\" >> run_globus.sh - echo "-v \"/shared/datafed-repo-key.priv\":/opt/datafed/keys/datafed-repo-key.priv \\" >> run_globus.sh - - echo "-t \"${REGISTRY}/${IMAGE_TAG}${BRANCH_LOWER}:latest\"" >> run_globus.sh + - echo "-t \"${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:${CI_COMMIT_SHA}\"" >> run_globus.sh - if [ -f "${DATAFED_GLOBUS_DIR}/${CI_DATAFED_REPO_ID_AND_DIR}-repo-form.sh" ]; then rm "${DATAFED_GLOBUS_DIR}/${CI_DATAFED_REPO_ID_AND_DIR}-repo-form.sh"; fi - chmod +x run_globus.sh - ./run_globus.sh - - while [ ! -f "${DATAFED_GLOBUS_DIR}/${CI_DATAFED_REPO_ID_AND_DIR}-repo-form.sh" ]; do echo "Waiting for ${DATAFED_GLOBUS_DIR}/${CI_DATAFED_REPO_ID_AND_DIR}-repo-form.sh"; sleep 10; done + # Check that repo form has been created before saying job is a success the + # repo-form is needed before the next job can move forward. In addition + # ensure that the container has not died due to an error. + - | + while [ ! -f "${DATAFED_GLOBUS_DIR}/${CI_DATAFED_REPO_ID_AND_DIR}-repo-form.sh" ] + do + echo "Waiting for ${DATAFED_GLOBUS_DIR}/${CI_DATAFED_REPO_ID_AND_DIR}-repo-form.sh" + sleep 10 + ./scripts/container_run_test.sh -e -c "1" -t "${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:${CI_COMMIT_SHA}" + done - cat "${DATAFED_GLOBUS_DIR}/${CI_DATAFED_REPO_ID_AND_DIR}-repo-form.sh" - - ./scripts/container_run_test.sh -e -c "1" -t "${REGISTRY}/${IMAGE_TAG}${BRANCH_LOWER}:latest" - cp ${DATAFED_GLOBUS_DIR}/${CI_DATAFED_REPO_ID_AND_DIR}-repo-form.sh . - cp ${DATAFED_GLOBUS_DIR}/${CI_DATAFED_REPO_ID_AND_DIR}-repo-form.json . artifacts: @@ -381,12 +419,16 @@ end_to_end_web_test: DATAFED_WEB_TEST_USERNAME: "datafed89" DATAFED_WEB_TEST_PASSWORD: "${CI_DATAFED_USER89_GLOBUSID_PASSWORD}" DATAFED_DOMAIN: "${CI_DATAFED_DOMAIN}" + NVM_DIR: "/shared/install/nvm" stage: end-to-end-test needs: ["end_to_end_client-test"] tags: - ci-datafed-client script: - cd tests/end-to-end/web-UI + - "[ -s \"$NVM_DIR/nvm.sh\" ] && . \"$NVM_DIR/nvm.sh\"" # This loads nvm + - nvm install 18 + - nvm use 18 - npm install - sudo npx playwright install-deps - npx playwright install @@ -405,43 +447,66 @@ end_to_end_web_test: -DINSTALL_FOXX=OFF - cmake --build build --target end_to_end_web_tests +################################################################################ +# Signal end to end to end tests +################################################################################ +end-to-end-signal: + stage: end-to-end-test-finish-signal + tags: + - datafed-infrastructure + script: + - echo "Signal end of end to end tests" + when: always +################################################################################ +# Log output +################################################################################ +# We don't want to run the log jobs if the infrastructure was never stood up +# because the jobs will hang indefinately + end_to_end_error_discovery_arango: + needs: ["check-ci-infrastructure", "end-to-end-arango-setup", "end-to-end-signal"] stage: log tags: - ci-datafed-arango script: - sudo journalctl --no-pager -u arangodb3.service - rules: - - when: always end_to_end_error_discovery_gcs: + needs: ["check-ci-infrastructure", "end-to-end-gcs-authz-setup", "end-to-end-signal"] extends: .error_logs_client_end_to_end variables: - IMAGE_TAG: "datafed/gcs-" + PROJECT: "datafed" + COMPONENT: "gcs" tags: - ci-datafed-globus - docker end_to_end_error_discovery_repo: + needs: ["check-ci-infrastructure", "end-to-end-repo-setup", "end-to-end-signal"] extends: .error_logs_client_end_to_end variables: - IMAGE_TAG: "datafed/repo-" + PROJECT: "datafed" + COMPONENT: "repo" tags: - ci-datafed-globus - docker end_to_end_error_discovery_core: + needs: ["check-ci-infrastructure", "end-to-end-core-setup", "end-to-end-signal"] extends: .error_logs_client_end_to_end variables: - IMAGE_TAG: "datafed/core-" + PROJECT: "datafed" + COMPONENT: "core" tags: - ci-datafed-core - docker end_to_end_error_discovery_web: + needs: ["check-ci-infrastructure", "end-to-end-ws-setup", "end-to-end-signal"] extends: .error_logs_client_end_to_end variables: - IMAGE_TAG: "datafed/ws-" + PROJECT: "datafed" + COMPONENT: "ws" tags: - ci-datafed-core - docker diff --git a/.gitlab/stage_build_base.yml b/.gitlab/stage_build_base.yml index 81add58c2..ab153788f 100644 --- a/.gitlab/stage_build_base.yml +++ b/.gitlab/stage_build_base.yml @@ -6,7 +6,9 @@ build-dependencies: extends: .docker_base_build_script stage: build-base variables: - IMAGE_TAG: "datafed/dependencies" + DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + PROJECT: "datafed" + COMPONENT: "dependencies" GIT_STRATEGY: clone DOCKER_FILE_PATH: "docker/Dockerfile.dependencies" tags: @@ -16,7 +18,9 @@ build-runtime: extends: .docker_base_build_script stage: build-base variables: - IMAGE_TAG: "datafed/runtime" + DATAFED_HARBOR_REGISTRY: "$REGISTRY" # needed by c_harbor_artifact_count + PROJECT: "datafed" + COMPONENT: "runtime" GIT_STRATEGY: clone DOCKER_FILE_PATH: "docker/Dockerfile.runtime" tags: diff --git a/.gitlab/stage_clear_cache.yml b/.gitlab/stage_clear_cache.yml index 6ed8d2431..640395f65 100644 --- a/.gitlab/stage_clear_cache.yml +++ b/.gitlab/stage_clear_cache.yml @@ -7,8 +7,9 @@ script: - docker login "${REGISTRY}" -u "${HARBOR_USER}" -p "${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" - if [[ $(docker ps -q | wc -l) != "0" ]]; then docker stop $(docker ps -q); fi; - - docker system prune -f + - docker system prune -f --all - ./scripts/ci_purge_images.sh + - df -h clear-core-cache: extends: .clear_cache diff --git a/.gitlab/stage_image_check.yml b/.gitlab/stage_image_check.yml index 7a5284876..1c4604a74 100644 --- a/.gitlab/stage_image_check.yml +++ b/.gitlab/stage_image_check.yml @@ -7,40 +7,47 @@ check-ws-image: extends: .image_check stage: image-check variables: + PROJECT: "datafed" COMPONENT: "ws" - IMAGE_TAG: "datafed/ws" + BUILD_INTERMEDIATE: "TRUE" + INTERMEDIATE_LAYER_NAME: "build" check-core-image: extends: .image_check stage: image-check variables: + PROJECT: "datafed" COMPONENT: "core" - IMAGE_TAG: "datafed/core" + BUILD_INTERMEDIATE: "FALSE" check-repo-image: extends: .image_check stage: image-check variables: + PROJECT: "datafed" COMPONENT: "repo" - IMAGE_TAG: "datafed/repo" + BUILD_INTERMEDIATE: "FALSE" check-gcs-base-image: extends: .image_check stage: image-check variables: + PROJECT: "datafed" COMPONENT: "gcs_base" - IMAGE_TAG: "datafed/gcs-base" + BUILD_INTERMEDIATE: "FALSE" check-gcs-image: extends: .image_check stage: image-check variables: + PROJECT: "datafed" COMPONENT: "gcs" - IMAGE_TAG: "datafed/gcs" + BUILD_INTERMEDIATE: "FALSE" check-foxx-image: extends: .image_check stage: image-check variables: + PROJECT: "datafed" COMPONENT: "foxx" - IMAGE_TAG: "datafed/foxx" + BUILD_INTERMEDIATE: "FALSE" diff --git a/.gitlab/stage_pipeline_serialize.yml b/.gitlab/stage_pipeline_serialize.yml index 558d9c222..ce71ed417 100644 --- a/.gitlab/stage_pipeline_serialize.yml +++ b/.gitlab/stage_pipeline_serialize.yml @@ -11,5 +11,17 @@ wait: tags: - datafed-infrastructure script: + # Why is sleep necessary, ci_pipeline_serializer ensures there are only + # two active pipelines at a time, it will wait until one frees up before + # continuing the job. + # + # However, if the number of active pipelines was reduced to 1 and and a new + # pipeline starts, it takes a bit of time for the new pipeline to be + # registered thus its possible to have more than 2 active pipelines. Two running + # and one held by the resource_group + # + # By sleeping for some random amount of seconds it gives the GitLab database + # a moment to update the number of active pipelines. + - sleep $((RANDOM % 30 + 10)) - chmod +x ./scripts/ci_pipeline_serializer.sh && ./scripts/ci_pipeline_serializer.sh resource_group: pipeline_serializer diff --git a/.gitlab/stage_provision_client.yml b/.gitlab/stage_provision_client.yml index 097a93250..f396598e6 100644 --- a/.gitlab/stage_provision_client.yml +++ b/.gitlab/stage_provision_client.yml @@ -7,11 +7,13 @@ provision-client: needs: ["signal"] variables: GIT_STRATEGY: clone + DATAFED_PYTHON_DEPENDENCIES_DIR: /opt/datafed/dependencies/python stage: provision-client tags: - ci-datafed-client before_script: - export PATH=/opt/datafed/dependencies/bin:$PATH + - rm -rf $DATAFED_PYTHON_DEPENDENCIES_DIR script: - ./scripts/generate_datafed.sh - ./scripts/install_client_dependencies.sh diff --git a/.gitlab/stage_test.yml b/.gitlab/stage_test.yml new file mode 100644 index 000000000..757c78bc1 --- /dev/null +++ b/.gitlab/stage_test.yml @@ -0,0 +1,34 @@ +--- + +# You can override the included template(s) by including variable overrides +# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings +# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/pipeline/#customization +# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings +# Note that environment variables can be set in several places +# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence +semgrep-sast: + tags: + - docker-exec + variables: + SECURE_LOG_LEVEL: "debug" + rules: + - if: $CI_PIPELINE_SOURCE == "push" + +secret_detection: + stage: test + tags: + - docker-exec + rules: + - if: $CI_PIPELINE_SOURCE == "push" + +gemnasium-dependency_scanning: + stage: test + tags: + - docker-exec + rules: + - if: $CI_PIPELINE_SOURCE == "push" + +include: +- template: Security/Secret-Detection.gitlab-ci.yml +- template: Security/SAST.gitlab-ci.yml +- template: Security/Dependency-Scanning.gitlab-ci.yml diff --git a/.gitlab/stage_unit.yml b/.gitlab/stage_unit.yml new file mode 100644 index 000000000..1aa8906cb --- /dev/null +++ b/.gitlab/stage_unit.yml @@ -0,0 +1,130 @@ +--- + +include: + - local: .gitlab/stage_build.yml + +run-ws-unit-job: + # Either the web container needs to be rebuilt or the container needs to be + # retagged with the current git commit hash. + needs: ["run-ws-build-job"] + stage: unit + variables: + PROJECT: "datafed" + COMPONENT: "ws" + GIT_STRATEGY: clone + HOST_LOG_FILE_PATH: "/shared/logs" + CONTAINER_LOG_FILE_PATH: "/datafed/logs" + DATAFED_WEB_KEY_DIR: "/shared/keys" + DATAFED_WEB_CERT_NAME: "cert.crt" + DATAFED_WEB_KEY_NAME: "cert.key" + DATAFED_WEB_CERT_PATH: "${DATAFED_WEB_KEY_DIR}/${DATAFED_WEB_CERT_NAME}" + DATAFED_WEB_CSR_PATH: "${DATAFED_WEB_KEY_DIR}/cert.csr" + DATAFED_WEB_KEY_PATH: "${DATAFED_WEB_KEY_DIR}/${DATAFED_WEB_KEY_NAME}" + INTERMEDIATE_LAYER_NAME: "build" + tags: + - docker + script: + - BRANCH_LOWER=$(echo "$CI_COMMIT_REF_NAME" | tr '[:upper:]' '[:lower:]') + - echo "$BRANCH_LOWER" + - mkdir -p "$HOST_LOG_FILE_PATH" + - mkdir -p "${DATAFED_WEB_KEY_DIR}" + - ./scripts/ci_setup_web_certs.sh + - chmod o+w "${HOST_LOG_FILE_PATH}" + - chown gitlab-runner "$HOST_LOG_FILE_PATH" + - ./scripts/generate_datafed.sh + - docker login "${REGISTRY}" -u "${HARBOR_USER}" -p "${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" + - USER_ID=$(id -u) + - GROUP_ID=$(id -g) + - CORE_ADDRESS=$(hostname -I | awk '{print $1}') + - cat $CI_DATAFED_CORE_PUB_KEY > /shared/keys/datafed-core-key.pub + - env + - ./scripts/container_stop.sh -n "ws-" -p + - random_string=$(bash -c "cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w "10" | head -n 1") + # Don't run in daemon mode this is just a unit test + - echo "#!/bin/bash" > run_web.sh + - echo "docker run \\" >> run_web.sh + - echo "--name \"ws-${BRANCH_LOWER}-${INTERMEDIATE_LAYER_NAME}-${CI_COMMIT_SHORT_SHA}-${random_string}\" \\" >> run_web.sh + - echo "-e NVM_INC=/opt/datafed/dependencies/nvm/versions/node/v14.21.3/include/node \\" >> run_web.sh + - echo "-e PATH=/opt/datafed/dependencies/nvm/versions/node/v14.21.3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \\" >> run_web.sh + - echo "-e NVM_INC=/opt/datafed/dependencies/nvm/versions/node/v14.21.3/include/node \\" >> run_web.sh + - echo "-e DATAFED_GLOBUS_APP_SECRET=\"$CI_DATAFED_GLOBUS_APP_SECRET\" \\" >> run_web.sh + - echo "-e DATAFED_GLOBUS_APP_ID=\"$CI_DATAFED_GLOBUS_APP_ID\" \\" >> run_web.sh + - echo "-e DATAFED_ZEROMQ_SESSION_SECRET=\"$CI_DATAFED_ZEROMQ_SESSION_SECRET\" \\" >> run_web.sh + - echo "-e DATAFED_ZEROMQ_SYSTEM_SECRET=\"$CI_DATAFED_ZEROMQ_SYSTEM_SECRET\" \\" >> run_web.sh + - echo "-e DATAFED_DOMAIN=\"$CI_DATAFED_DOMAIN\" \\" >> run_web.sh + - echo "-e DATAFED_WEB_CERT_PATH=\"/opt/datafed/keys/${DATAFED_WEB_CERT_NAME}\" \\" >> run_web.sh + - echo "-e DATAFED_WEB_KEY_PATH=\"/opt/datafed/keys/${DATAFED_WEB_KEY_NAME}\" \\" >> run_web.sh + - echo "-e DATAFED_DEFAULT_LOG_PATH=\"${CONTAINER_LOG_FILE_PATH}\" \\" >> run_web.sh + - echo "-e DATAFED_CORE_ADDRESS_PORT_INTERNAL=\"$CORE_ADDRESS:7513\" \\" >> run_web.sh + - echo "-e UID=\"$USER_ID\" \\" >> run_web.sh + - echo "-p 443:443 \\" >> run_web.sh + - echo "-v \"${HOST_LOG_FILE_PATH}:${CONTAINER_LOG_FILE_PATH}\" \\" >> run_web.sh + - echo "-v \"/shared/keys/datafed-core-key.pub:/opt/datafed/keys/datafed-core-key.pub\" \\" >> run_web.sh + - echo "-v \"${DATAFED_WEB_CERT_PATH}:/opt/datafed/keys/${DATAFED_WEB_CERT_NAME}\" \\" >> run_web.sh + - echo "-v \"${DATAFED_WEB_KEY_PATH}:/opt/datafed/keys/${DATAFED_WEB_KEY_NAME}\" \\" >> run_web.sh + - echo "-t \"${REGISTRY}/${PROJECT}/${COMPONENT}-${INTERMEDIATE_LAYER_NAME}-${BRANCH_LOWER}:${CI_COMMIT_SHA}\" " >> run_web.sh + - chmod +x run_web.sh + - ./run_web.sh + +# This unit test uses the same container as the gcs prod container. Instead +# of running the entrypoint file, this container when launched overrides +# the entrypoint file and instead runs the unit tests. +run-authz-unit-job: + variables: + PROJECT: "datafed" + COMPONENT: "gcs" + HOST_LOG_FILE_PATH: "/shared/logs" + CONTAINER_LOG_FILE_PATH: "/datafed/logs" + GIT_STRATEGY: clone + DATAFED_HOST_COLLECTION_MOUNT: "/shared/collections" + DATAFED_GLOBUS_DIR: "/shared/globus" + needs: ["run-gcs-build-job"] + stage: unit + tags: + - docker + script: + - BRANCH_LOWER=$(echo "$CI_COMMIT_REF_NAME" | tr '[:upper:]' '[:lower:]') + - echo "$BRANCH_LOWER" + - mkdir -p "$HOST_LOG_FILE_PATH" + - mkdir -p "${DATAFED_GLOBUS_DIR}" + - cp "${CI_DATAFED_GCS_DEPLOYMENT_KEY}" "${DATAFED_GLOBUS_DIR}/deployment-key.json" + - cp "${CI_DATAFED_GCS_CLIENT_CRED}" "${DATAFED_GLOBUS_DIR}/client_cred.json" + - USER_ID=$(id -u) + - chmod o+w "${HOST_LOG_FILE_PATH}" + - chown gitlab-runner "$HOST_LOG_FILE_PATH" + - ./scripts/generate_datafed.sh + - docker login "${REGISTRY}" -u "${HARBOR_USER}" -p "${HARBOR_DATAFED_GITLAB_CI_REGISTRY_TOKEN}" + - ./scripts/container_stop.sh -n "${COMPONENT}" -p + - random_string=$(bash -c "cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w "10" | head -n 1") + - echo "#!/bin/bash" > run_globus.sh + - echo "docker run \\" >> run_globus.sh + - echo "--name \"${COMPONENT}-${BRANCH_LOWER}-${CI_COMMIT_SHORT_SHA}-${random_string}\" \\" >> run_globus.sh + - echo "--network host \\" >> run_globus.sh + - echo "-e DATAFED_GLOBUS_APP_SECRET=\"$CI_DATAFED_GLOBUS_APP_SECRET\" \\" >> run_globus.sh + - echo "-e DATAFED_GLOBUS_APP_ID=\"$CI_DATAFED_GLOBUS_APP_ID\" \\" >> run_globus.sh + - echo "-e DATAFED_ZEROMQ_SESSION_SECRET=\"$CI_DATAFED_ZEROMQ_SESSION_SECRET\" \\" >> run_globus.sh + - echo "-e DATAFED_ZEROMQ_SYSTEM_SECRET=\"$CI_DATAFED_ZEROMQ_SYSTEM_SECRET\" \\" >> run_globus.sh + - echo "-e DATAFED_DOMAIN=\"$CI_DATAFED_DOMAIN\" \\" >> run_globus.sh + - echo "-e DATAFED_HTTPS_SERVER_PORT=\"443\" \\" >> run_globus.sh + - echo "-e DATAFED_DEFAULT_LOG_PATH=\"$CONTAINER_LOG_FILE_PATH\" \\" >> run_globus.sh + - echo "-e DATAFED_CORE_ADDRESS_PORT_INTERNAL=\"${CI_DATAFED_DOMAIN}:7513\" \\" >> run_globus.sh + - echo "-e DATAFED_GCS_ROOT_NAME=\"${CI_DATAFED_GCS_ROOT_NAME}\" \\" >> run_globus.sh + - echo "-e DATAFED_GCS_COLLECTION_BASE_PATH=\"/mnt\" \\" >> run_globus.sh + - echo "-e DATAFED_GCS_COLLECTION_ROOT_PATH=\"/mnt/datafed\" \\" >> run_globus.sh + - echo "-e DATAFED_GLOBUS_SUBSCRIPTION=\"${CI_DATAFED_GLOBUS_SUBSCRIPTION}\" \\" >> run_globus.sh + - echo "-e DATAFED_GLOBUS_CONTROL_PORT=\"443\" \\" >> run_globus.sh + - echo "-e DATAFED_REPO_USER=\"datafed\" \\" >> run_globus.sh + - echo "-e DATAFED_AUTHZ_USER=\"datafed\" \\" >> run_globus.sh + - echo "-e UID=\"$USER_ID\" \\" >> run_globus.sh + - echo "-e BUILD_WITH_METADATA_SERVICES=\"FALSE\" \\" >> run_globus.sh + - echo "-e DATAFED_REPO_ID_AND_DIR=\"${CI_DATAFED_REPO_ID_AND_DIR}\" \\" >> run_globus.sh + - echo "-e DATAFED_GCS_IP=\"${CI_DATAFED_GCS_IP}\" \\" >> run_globus.sh + - echo "-e DATAFED_REPO_DOMAIN=\"${CI_DATAFED_REPO_DOMAIN}\" \\" >> run_globus.sh + - echo "-v \"${DATAFED_GLOBUS_DIR}:/opt/datafed/globus\" \\" >> run_globus.sh + - echo "-v \"${HOST_LOG_FILE_PATH}:${CONTAINER_LOG_FILE_PATH}\" \\" >> run_globus.sh + - echo "-v \"${DATAFED_HOST_COLLECTION_MOUNT}:/mnt/datafed\" \\" >> run_globus.sh + - echo "--entrypoint bash \\" >> run_globus.sh + - echo "-t \"${REGISTRY}/${PROJECT}/${COMPONENT}-${BRANCH_LOWER}:${CI_COMMIT_SHA}\" \\" >> run_globus.sh + - echo "-c 'cd /datafed/source; /opt/datafed/dependencies/bin/cmake --build build --target test'" >> run_globus.sh + - chmod +x run_globus.sh + - ./run_globus.sh diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 000000000..46252c0e3 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,21 @@ +{ + "arrowParens": "always", + "bracketSameLine": false, + "bracketSpacing": true, + "semi": true, + "experimentalTernaries": false, + "singleQuote": false, + "jsxSingleQuote": false, + "quoteProps": "as-needed", + "trailingComma": "all", + "singleAttributePerLine": true, + "htmlWhitespaceSensitivity": "css", + "vueIndentScriptAndStyle": false, + "proseWrap": "preserve", + "insertPragma": false, + "printWidth": 100, + "requirePragma": false, + "tabWidth": 4, + "useTabs": false, + "embeddedLanguageFormatting": "auto" +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f829ea90..10a0e687a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ 2. [918] - Add admin script for making a user an admin 3. [1009] - Add collections to database for holding Globus tokens. 4. [1002] - Add backoff for task worker when database fails to prevent log overflow. +5. [1109] - Add support for Globus token association to Globus collection and user. +6. [1215] - Add support for fetching Globus tokens associated with Globus collection and user. +7. [1214] - Add support for mapped collections on transfer tasks ## PATCH Bug fixes/Technical Debt/Documentation 1. [984] - Fixes {server_default} from showing up in path. @@ -22,6 +25,22 @@ 11. [1012] - Allow customized base build image for Docker dependencies and runtime Dockerfiles 12. [986] - Design improvement to upload and download transfer box. 13. [985] - Handles longer than needed timeouts on ui pages. +14. [1053] - Set CMake to enable foxx tests when built in the CI. +15. [1086] - Address XML-RPC bug from deprecated client +16. [1149] - Docker container GCS Collection Mount Bug Fix +17. [1168] - Add authz unit testing to the CI +18. [1200] - Add JavaScript linter (eslint) and (prettier) formatter for JavaScript +19. [1180] - Refactor of authz foxx module, split into objects and added unit tests +20. [1223] - Fix deprecated method usage for Protobuf in Python client library +21. [1257] - Bug in authz library parsing of authz.conf file, globus paths incorrectly sanitized when using just '/' +22. [1255] - Fixes bug, in libauthz with log_path var not being read in from config file. +23. [1268] - Bug fixes unbound variable in foxx entrypoint file. +24. [1269] - Update Arangodb to 3.12.4 +25. [1288] - Bug Jupyter Notebook in documentation were fixed. +26. [1321] - Refactor, allow core config threads via env vars +22. [1241] - Adds a bug fix resulting from a race condition in the global + configuration struct in the globus callout library, makes + globus_collection_path consistent in conf file # v2024.6.17.10.40 diff --git a/CMakeLists.txt b/CMakeLists.txt index 769fd1570..019f389ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ if( NOT DEFINED GLOBUS_VERSION ) set(GLOBUS_VERSION 5) endif() OPTION(BUILD_AUTHZ "Build DataFed Authz library" FALSE) +OPTION(BUILD_AUTHZ_TESTS "Build DataFed Authz Tests" FALSE) OPTION(BUILD_AUTHZ_WITH_SYSLOG "Build Authz without syslog" TRUE) OPTION(BUILD_CORE_SERVER "Build DataFed Core Server" TRUE) OPTION(BUILD_COMMON "Build DataFed common library" TRUE) @@ -26,6 +27,7 @@ OPTION(BUILD_PYTHON_CLIENT "Build python client" TRUE) OPTION(BUILD_TESTS "Build Tests" TRUE) OPTION(BUILD_WEB_SERVER "Build DataFed Web Server" TRUE) OPTION(ENABLE_UNIT_TESTS "Enable unit tests" TRUE) +OPTION(ENABLE_MEMORY_TESTS "Enable memory tests" FALSE) OPTION(BUILD_SHARED_LIBS "By default DataFed tries to build static libraries with the exception of libdatafed-authz which must always be a shared library, it will also try to link with as many static libraries as possible. However, @@ -35,6 +37,8 @@ setting is turned on DataFed will build it's libraries as shared and try to link to shared libraries." OFF) OPTION(ENABLE_END_TO_END_API_TESTS "Enable end-to-end API testing" FALSE) OPTION(ENABLE_END_TO_END_WEB_TESTS "Enable end-to-end web testing with Playwright" FALSE) +OPTION(ENABLE_FOXX_TESTS "Enable Foxx testing, off by default because it + will overwrite the test database." FALSE) set(INSTALL_REPO_SERVER ${BUILD_REPO_SERVER}) set(INSTALL_AUTHZ ${BUILD_AUTHZ}) @@ -60,6 +64,7 @@ get_version_from_script(${DEPENDENCY_VERSIONS} "DATAFED_OPENSSL" LOCAL_OPENSSL_V get_version_from_script(${DEPENDENCY_VERSIONS} "DATAFED_LIBCURL" LOCAL_CURL_VERSION) get_version_from_script(${DEPENDENCY_VERSIONS} "DATAFED_BOOST" LOCAL_BOOST_VERSION) get_version_from_script(${DEPENDENCY_VERSIONS} "DATAFED_ZLIB_VERSION" LOCAL_ZLIB_VERSION) +get_version_from_script(${DEPENDENCY_VERSIONS} "DATAFED_NODE_VERSION" LOCAL_NODE_VERSION) # Prioritize the CMD line argument over config file if(NOT DEFINED DATAFED_INSTALL_PATH) get_value_from_datafed_sh("DATAFED_INSTALL_PATH" DATAFED_INSTALL_PATH) @@ -114,6 +119,17 @@ file( GLOB ProtoFiles "${PROJECT_SOURCE_DIR}/common/proto/common/*.proto" ) if( BUILD_WEB_SERVER ) include(./cmake/Web.cmake) file(COPY ${ProtoFiles} DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/web/") + + if( ENABLE_UNIT_TESTS ) + add_test(NAME unit_tests_web COMMAND "${DEPENDENCY_INSTALL_PATH}/nvm/versions/node/${LOCAL_NODE_VERSION}/bin/npm" "test") + set_tests_properties(unit_tests_web PROPERTIES WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/web) + endif() + +endif() + +if( BUILD_AUTHZ_TESTS ) + include(./cmake/GSSAPI.cmake) + include(./cmake/GlobusCommon.cmake) endif() if ( BUILD_REPO_SERVER OR BUILD_CORE_SERVER OR BUILD_AUTHZ OR BUILD_COMMON OR BUILD_PYTHON_CLIENT) @@ -204,7 +220,14 @@ if( INSTALL_WEB_SERVER ) endif() if( INSTALL_FOXX ) - install( CODE "execute_process(COMMAND ${PROJECT_SOURCE_DIR}/scripts/install_foxx.sh )") + install(CODE "execute_process(COMMAND ${DataFed_SOURCE_DIR}/scripts/install_foxx.sh + OUTPUT_VARIABLE _out + ERROR_VARIABLE _err + RESULT_VARIABLE _res) + If (NOT \${_res} EQUAL \"0\") + message( FATAL_ERROR \"out: \${_out} install_foxx failed: \${_err}\") + endif()" + ) endif() if (ENABLE_END_TO_END_TESTS) @@ -276,5 +299,7 @@ message(" boost system Library: ${DATAFED_BOOST_SYSTEM_LIBRARY_PATH} message(" boost filesystem Library: ${DATAFED_BOOST_FILESYSTEM_LIBRARY_PATH}") message(" boost program_options Library: ${DATAFED_BOOST_PROGRAM_OPTIONS_LIBRARY_PATH}") message(" zlib Library: ${DATAFED_ZLIB_LIBRARIES}") +message(" gssapi Library: ${DATAFED_GSSAPI_LIBRARIES}") +message(" globus_common Library: ${DATAFED_GLOBUS_COMMON_LIBRARIES}") message("") diff --git a/cmake/GSSAPI.cmake b/cmake/GSSAPI.cmake new file mode 100644 index 000000000..ec31d3342 --- /dev/null +++ b/cmake/GSSAPI.cmake @@ -0,0 +1,14 @@ + +function(find_gssapi_library) + + find_library(GSSAPI_LIBRARIES NAMES libgssapi.so.3 libgssapi.so gssapi gssapi libgssapi_krb5.so ) + + if(NOT GSSAPI_LIBRARIES) + set(GSSAPI_LIBRARIES "") + endif() + + set(DATAFED_GSSAPI_LIBRARIES "${GSSAPI_LIBRARIES}" PARENT_SCOPE) + +endfunction() + +find_gssapi_library() diff --git a/cmake/GlobusCommon.cmake b/cmake/GlobusCommon.cmake new file mode 100644 index 000000000..742965ba9 --- /dev/null +++ b/cmake/GlobusCommon.cmake @@ -0,0 +1,14 @@ + +function(find_globus_common_library) + + find_library(GLOBUS_COMMON_LIBRARIES globus_common) + + if(NOT GLOBUS_COMMON_LIBRARIES) + set(GLOBUS_COMMON_LIBRARIES "") + endif() + + set(DATAFED_GLOBUS_COMMON_LIBRARIES "${GLOBUS_COMMON_LIBRARIES}" PARENT_SCOPE) + +endfunction() + +find_globus_common_library() diff --git a/cmake/JSON.cmake b/cmake/JSON.cmake index 61014280c..d4b9d3e19 100644 --- a/cmake/JSON.cmake +++ b/cmake/JSON.cmake @@ -7,13 +7,12 @@ function(find_json_library) set(JSON_LIBRARY_PATH "" ) if(EXISTS ${DEPENDENCY_INSTALL_PATH}) - set(JSON_LIB_CMAKE_DIR "${DEPENDENCY_INSTALL_PATH}/lib/cmake") + set(JSON_LIB_CMAKE_DIR "${DEPENDENCY_INSTALL_PATH}/share/cmake ${DEPENDENCY_INSTALL_PATH}/lib/cmake") set(JSON_INCLUDE_DIR "${DEPENDENCY_INSTALL_PATH}/include") set(JSON_LIB_DIR "${DEPENDENCY_INSTALL_PATH}/lib") endif() - - find_package(nlohmann_json CONFIG REQUIRED PATHS "${JSON_LIB_CMAKE_DIR}") + find_package(nlohmann_json REQUIRED PATHS "${JSON_LIB_CMAKE_DIR}") # NOTE interfaces do not have a physical location associated with the library get_target_property(JSON_INCLUDE_PATH nlohmann_json::nlohmann_json INTERFACE_INCLUDE_DIRECTORIES ) diff --git a/cmake/JSONSchema.cmake b/cmake/JSONSchema.cmake index c326982ea..82d691d7c 100644 --- a/cmake/JSONSchema.cmake +++ b/cmake/JSONSchema.cmake @@ -1,22 +1,25 @@ - function(find_json_schema_library) set(JSON_SCHEMA_INCLUDE_DIR "" ) set(JSON_SCHEMA_LIB_DIR "" ) set(JSON_SCHEMA_LIB_CMAKE_DIR "" ) set(JSON_SCHEMA_LIBRARY_PATH "" ) - if(EXISTS ${DEPENDENCY_INSTALL_PATH}) set(JSON_SCHEMA_LIB_CMAKE_DIR "${DEPENDENCY_INSTALL_PATH}/lib/cmake") set(JSON_SCHEMA_INCLUDE_DIR "${DEPENDENCY_INSTALL_PATH}/include") set(JSON_SCHEMA_LIB_DIR "${DEPENDENCY_INSTALL_PATH}/lib") endif() - - find_package(nlohmann_json_schema_validator CONFIG REQUIRED VERSION "${JSON_SCHEMA_VALIDATOR_VERSION}" PATHS "${JSON_SCHEMA_LIB_CMAKE_DIR}") + # Specifying the VERSION with find_package commands since updating the json schema version from + # version "2.1.0" to "2.3.0" is no longer supported. + find_package(nlohmann_json_schema_validator REQUIRED PATHS "${JSON_SCHEMA_LIB_CMAKE_DIR}") # NOTE interfaces do not have a physical location associated with the library - get_target_property(JSON_SCHEMA_INCLUDE_PATH nlohmann_json_schema_validator INTERFACE_INCLUDE_DIRECTORIES) - get_target_property(JSON_SCHEMA_LIBRARY_PATH nlohmann_json_schema_validator IMPORTED_LOCATION_NOCONFIG) + get_target_property(JSON_SCHEMA_INCLUDE_PATH nlohmann_json_schema_validator::validator INTERFACE_INCLUDE_DIRECTORIES) + get_target_property(JSON_SCHEMA_LIBRARY_PATH nlohmann_json_schema_validator::validator LOCATION) + + if(NOT "${JSON_SCHEMA_VALIDATOR_VERSION}" STREQUAL "${nlohmann_json_schema_validator_VERSION}") + message(FATAL_ERROR "REQUIRED Nlohmann JSON Schema Validator version ${JSON_SCHEMA_VALIDATOR_VERSION}, not satisfied. Found version ${nlohmann_json_schema_validator_VERSION}") + endif() set(DATAFED_JSON_SCHEMA_INCLUDE_PATH "${JSON_SCHEMA_INCLUDE_PATH}" PARENT_SCOPE) set(DATAFED_JSON_SCHEMA_LIBRARY_PATH "${JSON_SCHEMA_LIBRARY_PATH}" PARENT_SCOPE) diff --git a/cmake/Version.cmake b/cmake/Version.cmake index 93c5c0aa0..f21d866ab 100644 --- a/cmake/Version.cmake +++ b/cmake/Version.cmake @@ -1,32 +1,33 @@ -set(DATAFED_RELEASE_YEAR 2024) -set(DATAFED_RELEASE_MONTH 6) -set(DATAFED_RELEASE_DAY 17) -set(DATAFED_RELEASE_HOUR 10) -set(DATAFED_RELEASE_MINUTE 40) + +set(DATAFED_RELEASE_YEAR 2025) +set(DATAFED_RELEASE_MONTH 3) +set(DATAFED_RELEASE_DAY 12) +set(DATAFED_RELEASE_HOUR 14) +set(DATAFED_RELEASE_MINUTE 1) set(DATAFED_COMMON_LIB_MAJOR 1) set(DATAFED_COMMON_LIB_MINOR 0) -set(DATAFED_COMMON_LIB_PATCH 0) +set(DATAFED_COMMON_LIB_PATCH 1) set(DATAFED_COMMON_PROTOCOL_API_MAJOR 1) -set(DATAFED_COMMON_PROTOCOL_API_MINOR 0) +set(DATAFED_COMMON_PROTOCOL_API_MINOR 1) set(DATAFED_COMMON_PROTOCOL_API_PATCH 0) set(DATAFED_CORE_MAJOR 1) set(DATAFED_CORE_MINOR 0) -set(DATAFED_CORE_PATCH 0) +set(DATAFED_CORE_PATCH 2) set(DATAFED_FOXX_MAJOR 1) -set(DATAFED_FOXX_MINOR 0) +set(DATAFED_FOXX_MINOR 1) set(DATAFED_FOXX_PATCH 0) set(DATAFED_FOXX_API_MAJOR 1) -set(DATAFED_FOXX_API_MINOR 0) +set(DATAFED_FOXX_API_MINOR 1) set(DATAFED_FOXX_API_PATCH 0) set(DATAFED_WEB_MAJOR 1) -set(DATAFED_WEB_MINOR 0) +set(DATAFED_WEB_MINOR 1) set(DATAFED_WEB_PATCH 0) set(DATAFED_REPO_MAJOR 1) @@ -35,10 +36,10 @@ set(DATAFED_REPO_PATCH 0) set(DATAFED_AUTHZ_MAJOR 1) set(DATAFED_AUTHZ_MINOR 0) -set(DATAFED_AUTHZ_PATCH 0) +set(DATAFED_AUTHZ_PATCH 1) set(DATAFED_PYTHON_CLIENT_MAJOR 3) set(DATAFED_PYTHON_CLIENT_MINOR 0) -set(DATAFED_PYTHON_CLIENT_PATCH 0) -set(DATAFED_PYTHON_CLIENT_RELEASE_TYPE "b") -set(DATAFED_PYTHON_CLIENT_PRE_RELEASE_IDENTIFER "1") +set(DATAFED_PYTHON_CLIENT_PATCH 3) +set(DATAFED_PYTHON_CLIENT_RELEASE_TYPE "") +set(DATAFED_PYTHON_CLIENT_PRE_RELEASE_IDENTIFER "") diff --git a/common/include/common/DynaLog.hpp b/common/include/common/DynaLog.hpp index 0f8814a98..150b4f749 100644 --- a/common/include/common/DynaLog.hpp +++ b/common/include/common/DynaLog.hpp @@ -9,10 +9,10 @@ // Standard includes #include #include +#include #include #include #include -#include // Have to use macros for the line and func macros to work #define DL_LOG(level, context, message) \ @@ -90,7 +90,11 @@ enum class LogLevel : unsigned int { WARNING, INFO, DEBUG, - TRACE + TRACE, + + LAST_SENTINEL // Used to check that unsigned int conversions fall in valid + // range E.g. + // value < static_cast(LogLevel::LAST_SENTINEL) }; std::string toString(const LogLevel level); @@ -112,13 +116,27 @@ class LogLine { std::ostream &operator<<(std::ostream &out, const LogLine &log_line); class Logger { +public: + // Define the structure for each element of list used to track + // streams. + struct StreamEntry { + std::reference_wrapper + stream; // Reference wrapper for the stream + std::unique_ptr mutex; // Mutex for thread-safe operations + + StreamEntry(std::ostream &out_stream) + : stream(out_stream), mutex(std::make_unique()) {} + }; + private: // Parameters - std::vector> m_streams; LogLevel m_log_level = LogLevel::INFO; bool m_output_to_syslog = false; - mutable std::vector> m_mutexes; - + // List was chosen because we will need to be adding and removing streams + // as classes are created and destroyed this does not work well in a + // vector datastructure. + mutable std::list m_streams; // List to hold stream entries + mutable std::mutex m_streams_mutex; // Mutex to protect the list // Internal Methods void output(const LogLevel, std::string, std::string, int, const LogContext &context, const std::string &message); @@ -126,7 +144,18 @@ class Logger { public: // Methods void setLevel(LogLevel) noexcept; - void addStream(std::ostream &stream); + + // Add a new stream and return an iterator to it for easy removal + // in the future. + // NOTE care should be taken when adding streams because they are + // are stored as references, if the object goes out of scope the + // stored reference becomes invalid. removeStream should be called + // befor a stream goes out of scope.. + std::list::iterator addStream(std::ostream &stream); + + // Remove a stream by iterator, this is fast for a linked list. + void removeStream(std::list::iterator it); + void setSysLog(bool on_or_off) noexcept { m_output_to_syslog = on_or_off; } void log(const LogLevel, std::string file_name, std::string func_name, int, diff --git a/common/include/common/ICredentials.hpp b/common/include/common/ICredentials.hpp index 1394a9d2f..1572f8408 100644 --- a/common/include/common/ICredentials.hpp +++ b/common/include/common/ICredentials.hpp @@ -14,6 +14,7 @@ enum class CredentialType { PUBLIC_KEY, PRIVATE_KEY, SERVER_KEY }; class ICredentials { public: + virtual ~ICredentials() {}; virtual ProtocolType getType() const noexcept = 0; virtual std::string get(const CredentialType) const = 0; virtual bool has(CredentialType) const noexcept = 0; diff --git a/common/include/common/IMessage.hpp b/common/include/common/IMessage.hpp index 06e7b0069..7d455feca 100644 --- a/common/include/common/IMessage.hpp +++ b/common/include/common/IMessage.hpp @@ -52,6 +52,8 @@ const std::string CONTEXT = "context"; class IMessage { public: + + virtual ~IMessage() {}; virtual bool exists(MessageAttribute) const = 0; virtual bool exists(const std::string &) const = 0; diff --git a/common/include/common/IMessageMapper.hpp b/common/include/common/IMessageMapper.hpp index 110c81877..20e44766e 100644 --- a/common/include/common/IMessageMapper.hpp +++ b/common/include/common/IMessageMapper.hpp @@ -4,6 +4,7 @@ // Standard includes #include +#include namespace SDMS { diff --git a/common/include/common/IOperator.hpp b/common/include/common/IOperator.hpp index c3307215b..47a92e2c9 100644 --- a/common/include/common/IOperator.hpp +++ b/common/include/common/IOperator.hpp @@ -11,6 +11,8 @@ class IMessage; class IOperator { public: + + virtual ~IOperator() {}; virtual OperatorType type() const noexcept = 0; virtual void execute(IMessage &message) = 0; }; diff --git a/common/include/common/IServer.hpp b/common/include/common/IServer.hpp index 16070eebd..d94729493 100644 --- a/common/include/common/IServer.hpp +++ b/common/include/common/IServer.hpp @@ -17,6 +17,7 @@ enum class SocketRole; class IServer { public: + virtual ~IServer() {}; virtual ServerType type() const noexcept = 0; /** * By default will run forever you can specify a time to run the for instead diff --git a/common/include/common/ISocket.hpp b/common/include/common/ISocket.hpp index bbaf69286..f5ffc698c 100644 --- a/common/include/common/ISocket.hpp +++ b/common/include/common/ISocket.hpp @@ -15,9 +15,13 @@ namespace SDMS { class ISocket { public: + + virtual ~ISocket() {}; /********************************************************* * Getters *********************************************************/ + + virtual URIScheme getSocketScheme() const noexcept = 0; virtual SocketClassType getSocketClassType() const noexcept = 0; virtual SocketCommunicationType getSocketCommunicationType() const noexcept = 0; diff --git a/common/include/common/ProtoBufMap.hpp b/common/include/common/ProtoBufMap.hpp index 1640269ae..08d92b739 100644 --- a/common/include/common/ProtoBufMap.hpp +++ b/common/include/common/ProtoBufMap.hpp @@ -12,6 +12,7 @@ // Standard includes #include #include +#include namespace SDMS { diff --git a/common/include/common/SocketOptions.hpp b/common/include/common/SocketOptions.hpp index a61f21c0d..f09a11196 100644 --- a/common/include/common/SocketOptions.hpp +++ b/common/include/common/SocketOptions.hpp @@ -8,6 +8,7 @@ // Standard includes #include #include +#include namespace SDMS { diff --git a/common/include/common/Util.hpp b/common/include/common/Util.hpp index da5d4330f..a309892cd 100644 --- a/common/include/common/Util.hpp +++ b/common/include/common/Util.hpp @@ -3,6 +3,7 @@ #include #include +#include std::string exec(const char *cmd); diff --git a/common/proto/common/SDMS.proto b/common/proto/common/SDMS.proto index 486fccb83..f173cdde1 100644 --- a/common/proto/common/SDMS.proto +++ b/common/proto/common/SDMS.proto @@ -86,6 +86,16 @@ enum ProjectRole PROJ_ADMIN = 3; } +// Used to specify type of access token contained within message +enum AccessTokenType { + GENERIC = 1; + GLOBUS = 2; + GLOBUS_AUTH = 3; + GLOBUS_TRANSFER = 4; + GLOBUS_DEFAULT = 5; + ACCESS_SENTINEL = 255; +} + // ============================ Data Structures // Allocation-specific statistics data diff --git a/common/proto/common/SDMS_Auth.proto b/common/proto/common/SDMS_Auth.proto index 7226ecc09..38c57f29c 100644 --- a/common/proto/common/SDMS_Auth.proto +++ b/common/proto/common/SDMS_Auth.proto @@ -21,7 +21,6 @@ enum Protocol ID = 2; } - // ============================================================================ // ----------- Setup/Config Messages ------------------------------------------ // ============================================================================ @@ -116,6 +115,8 @@ message UserSetAccessTokenRequest required string access = 1; // Access token required uint32 expires_in = 2; // Access expiration time in seconds required string refresh = 3; // Refresh token (never expires) + optional AccessTokenType type = 4 [default = GLOBUS_DEFAULT]; + optional string other = 5; // Other information relevant to the set access token } // Get user access token (from Globus OAuth). This token will allow client to @@ -123,14 +124,17 @@ message UserSetAccessTokenRequest // Reply: UserAccessTokenReply on success, NackReply on error message UserGetAccessTokenRequest { + optional string collection_id = 1; + optional string collection_type = 2; // TODO: use enum } // Reply containing the user Globus access token and expiration time (in // seconds) for authenticated user. message UserAccessTokenReply { - required string access = 1; // Globus access token - required uint32 expires_in = 2; // Access token expiration in seconds + required string access = 1; // Globus access token + required uint32 expires_in = 2; // Access token expiration in seconds + optional bool needs_consent = 3; // Indicate requirement of consent flow } // Request to create a new DataFed user account. @@ -421,11 +425,13 @@ message RecordOwnerChangeReply // Reply: DataGetReply on success, NackReply on error message DataGetRequest { - repeated string id = 1; // ID/alias of data records and or collections - optional string path = 2; // Globus path to download to (not required if check option is set) - optional Encryption encrypt = 3; // Optional encryption mode (none, if available, required) - optional bool orig_fname = 4; // Optional flag to download to original filenames - optional bool check = 5; // Optional flag to perform initial validation only if true + repeated string id = 1; // ID/alias of data records and or collections + optional string path = 2; // Globus path to download to (not required if check option is set) + optional Encryption encrypt = 3; // Optional encryption mode (none, if available, required) + optional bool orig_fname = 4; // Optional flag to download to original filenames + optional bool check = 5; // Optional flag to perform initial validation only if true + optional string collection_id = 6; // Globus Collection ID + optional string collection_type = 7; // Globus Collection Type } // Request to upload raw data to a data records. Auth user must have WRITE_DATA @@ -434,11 +440,13 @@ message DataGetRequest // Reply: DataPutReply on success, NackReply on error message DataPutRequest { - required string id = 1; // ID/alias of data record - optional string path = 2; // Globus path to upload from - optional Encryption encrypt = 3; // Optional encryption mode (none, if available, required) - optional string ext = 4; // Optional extension override - optional bool check = 5; // Optional flag to perform initial validation only if true + required string id = 1; // ID/alias of data record + optional string path = 2; // Globus path to upload from + optional Encryption encrypt = 3; // Optional encryption mode (none, if available, required) + optional string ext = 4; // Optional extension override + optional bool check = 5; // Optional flag to perform initial validation only if true + optional string collection_id = 6; // Globus Collection ID + optional string collection_type = 7; // Globus Collection Type } // Reply containing data download information, including associated background task. diff --git a/common/source/DynaLog.cpp b/common/source/DynaLog.cpp index f89ccee95..1626a07c3 100644 --- a/common/source/DynaLog.cpp +++ b/common/source/DynaLog.cpp @@ -79,19 +79,20 @@ void Logger::output(const LogLevel level, std::string file, std::string func, int line_num, const LogContext &context, const std::string &message) { - size_t index = 0; + std::lock_guard lock(m_streams_mutex); // Lock the list mutex + for (auto &output_stream : m_streams) { - std::lock_guard lock(*m_mutexes.at(index)); - index++; + std::lock_guard stream_lock( + *output_stream.mutex); // Lock individual stream mutex boost::posix_time::ptime time = boost::posix_time::microsec_clock::universal_time(); - output_stream.get() << boost::posix_time::to_iso_extended_string(time) - << "Z "; - output_stream.get() << toString(level) << " "; - output_stream.get() << file << ":" << func << ":" << line_num << " "; + output_stream.stream.get() + << boost::posix_time::to_iso_extended_string(time) << "Z "; + output_stream.stream.get() << toString(level) << " "; + output_stream.stream.get() << file << ":" << func << ":" << line_num << " "; LogLine log_line(context, message); - output_stream.get() << log_line; - output_stream.get() << std::endl; + output_stream.stream.get() << log_line; + output_stream.stream.get() << std::endl; } if (m_output_to_syslog) { @@ -107,10 +108,24 @@ void Logger::output(const LogLevel level, std::string file, std::string func, void Logger::setLevel(LogLevel level) noexcept { m_log_level = level; } -void Logger::addStream(std::ostream &stream) { - m_streams.push_back(std::ref(stream)); - m_mutexes.emplace_back(std::make_unique()); +std::list::iterator +Logger::addStream(std::ostream &stream) { + std::lock_guard lock(m_streams_mutex); // Lock the list mutex + auto it = m_streams.insert(m_streams.end(), + StreamEntry{stream}); // Insert and get iterator + return it; // Return the iterator pointing to the new stream element +} + +void Logger::removeStream(std::list::iterator it) { + std::lock_guard lock(m_streams_mutex); // Lock the list mutex + if (it != m_streams.end()) { + m_streams.erase(it); + } } +// void Logger::addStream(std::ostream &stream) { +// m_streams.push_back(std::ref(stream)); +// m_mutexes.emplace_back(std::make_unique()); +//} void Logger::trace(std::string file, std::string func, int line_num, const LogContext &context, const std::string &message) { diff --git a/common/source/communicators/ZeroMQCommunicator.cpp b/common/source/communicators/ZeroMQCommunicator.cpp index 5de631421..424ee32fd 100644 --- a/common/source/communicators/ZeroMQCommunicator.cpp +++ b/common/source/communicators/ZeroMQCommunicator.cpp @@ -38,24 +38,24 @@ void sendDelimiter(void *outgoing_zmq_socket) { // Send NULL delimiter zmq_msg_t zmq_msg; zmq_msg_init(&zmq_msg); - int number_of_bytes = 0; - if ((number_of_bytes = - zmq_msg_send(&zmq_msg, outgoing_zmq_socket, ZMQ_SNDMORE)) < 0) { + int number_of_bytes = zmq_msg_send(&zmq_msg, outgoing_zmq_socket, ZMQ_SNDMORE); + + zmq_msg_close(&zmq_msg); + if(number_of_bytes < 0) { EXCEPT(1, "zmq_msg_send (delimiter) failed."); } - zmq_msg_close(&zmq_msg); } void sendFinalDelimiter(void *outgoing_zmq_socket) { // Send NULL delimiter zmq_msg_t zmq_msg; zmq_msg_init(&zmq_msg); - int number_of_bytes = 0; - // INDICATES no more parts - if ((number_of_bytes = zmq_msg_send(&zmq_msg, outgoing_zmq_socket, 0)) < 0) { + int number_of_bytes = zmq_msg_send(&zmq_msg, outgoing_zmq_socket, 0); + + zmq_msg_close(&zmq_msg); + if( number_of_bytes < 0 ) { EXCEPT(1, "zmq_msg_send (delimiter) failed."); } - zmq_msg_close(&zmq_msg); } /** @@ -118,11 +118,13 @@ void receiveRoute(IMessage &msg, void *incoming_zmq_socket, int number_of_bytes = 0; if ((number_of_bytes = zmq_msg_recv(&zmq_msg, incoming_zmq_socket, ZMQ_DONTWAIT)) < 0) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "receiveRoute zmq_msg_recv (route) failed."); } size_t len = zmq_msg_size(&zmq_msg); if (len) { if (len > 255) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "Message route segment exceeds max allowed length."); } received_part = @@ -146,11 +148,13 @@ void receiveRoute(IMessage &msg, void *incoming_zmq_socket, int number_of_bytes = 0; if ((number_of_bytes = zmq_msg_recv(&zmq_msg, incoming_zmq_socket, ZMQ_DONTWAIT)) < 0) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "receiveRoute zmq_msg_recv (route) failed."); } size_t len = zmq_msg_size(&zmq_msg); if (len != sizeof(uint32_t)) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "Expected a number indicating the number of routes to follow " "but nothing was provided."); } @@ -169,16 +173,19 @@ void receiveRoute(IMessage &msg, void *incoming_zmq_socket, int number_of_bytes = 0; if ((number_of_bytes = zmq_msg_recv(&zmq_msg, incoming_zmq_socket, ZMQ_DONTWAIT)) < 0) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "receiveRoute zmq_msg_recv (route) failed."); } size_t len = zmq_msg_size(&zmq_msg); // Stop when delimiter is read if (len == 0) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "Message route should not be an empty message."); } if (len > 255) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "Message route segment exceeds max allowed length."); } @@ -199,10 +206,12 @@ void receiveRoute(IMessage &msg, void *incoming_zmq_socket, int number_of_bytes = 0; if ((number_of_bytes = zmq_msg_recv(&zmq_msg, incoming_zmq_socket, ZMQ_DONTWAIT)) < 0) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "receiveRoute zmq_msg_recv (route) failed."); } size_t len = zmq_msg_size(&zmq_msg); if (len != 0) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "Expected a null frame following route section."); } zmq_msg_close(&zmq_msg); @@ -227,13 +236,14 @@ void sendRoute(IMessage &msg, void *outgoing_zmq_socket, zmq_msg_init_size(&zmq_msg, route.size()); memcpy(zmq_msg_data(&zmq_msg), route.data(), route.size()); - int number_of_bytes = 0; - if ((number_of_bytes = - zmq_msg_send(&zmq_msg, outgoing_zmq_socket, ZMQ_SNDMORE)) < 0) { - EXCEPT(1, "sendRoute zmq_msg_send (route) failed."); - } + int number_of_bytes = + zmq_msg_send(&zmq_msg, outgoing_zmq_socket, ZMQ_SNDMORE); zmq_msg_close(&zmq_msg); + + if ( number_of_bytes < 0 ) { + EXCEPT(1, "sendRoute zmq_msg_send (route) failed."); + } routes.pop_front(); } } @@ -244,12 +254,12 @@ void sendRoute(IMessage &msg, void *outgoing_zmq_socket, std::string header = "BEGIN_DATAFED"; zmq_msg_init_size(&zmq_msg, header.size()); memcpy(zmq_msg_data(&zmq_msg), header.data(), header.size()); - int number_of_bytes = 0; - if ((number_of_bytes = - zmq_msg_send(&zmq_msg, outgoing_zmq_socket, ZMQ_SNDMORE)) < 0) { + int number_of_bytes = + zmq_msg_send(&zmq_msg, outgoing_zmq_socket, ZMQ_SNDMORE); + zmq_msg_close(&zmq_msg); + if ( number_of_bytes < 0 ) { EXCEPT(1, "sendRoute count zmq_msg_send (route) failed."); } - zmq_msg_close(&zmq_msg); } { // Send number of routes @@ -260,12 +270,12 @@ void sendRoute(IMessage &msg, void *outgoing_zmq_socket, (unsigned char *)zmq_msg_data(&zmq_msg); *((uint32_t *)msg_route_count_allocation) = htonl(number_of_routes); - int number_of_bytes = 0; - if ((number_of_bytes = - zmq_msg_send(&zmq_msg, outgoing_zmq_socket, ZMQ_SNDMORE)) < 0) { + int number_of_bytes = + zmq_msg_send(&zmq_msg, outgoing_zmq_socket, ZMQ_SNDMORE); + zmq_msg_close(&zmq_msg); + if ( number_of_bytes < 0 ) { EXCEPT(1, "sendRoute count zmq_msg_send (route) failed."); } - zmq_msg_close(&zmq_msg); } for (auto &route : routes) { @@ -278,12 +288,12 @@ void sendRoute(IMessage &msg, void *outgoing_zmq_socket, zmq_msg_init_size(&zmq_msg, route.size()); memcpy(zmq_msg_data(&zmq_msg), route.data(), route.size()); - int number_of_bytes = 0; - if ((number_of_bytes = - zmq_msg_send(&zmq_msg, outgoing_zmq_socket, ZMQ_SNDMORE)) < 0) { + int number_of_bytes = + zmq_msg_send(&zmq_msg, outgoing_zmq_socket, ZMQ_SNDMORE); + zmq_msg_close(&zmq_msg); + if ( number_of_bytes < 0 ) { EXCEPT(1, "sendRoute zmq_msg_send (route) failed."); } - zmq_msg_close(&zmq_msg); } sendDelimiter(outgoing_zmq_socket); @@ -300,6 +310,7 @@ void receiveFrame(IMessage &msg, void *incoming_zmq_socket, zmq_msg_init_size(&zmq_msg, 8); if ((number_of_bytes = zmq_msg_recv(&zmq_msg, incoming_zmq_socket, ZMQ_DONTWAIT)) < 0) { + zmq_msg_close(&zmq_msg); EXCEPT_PARAM( 1, "RCV zmq_msg_recv (frame) failed: " << zmq_strerror(zmq_errno())); } else if (number_of_bytes == 8) { @@ -334,14 +345,12 @@ void sendFrame(IMessage &msg, void *outgoing_zmq_socket) { // Convert host binary to network (endian) format converter.copy(FrameConverter::CopyDirection::FROM_FRAME, zmq_msg, frame); - int number_of_bytes = 0; - - // Should always be sending a key - if ((number_of_bytes = - zmq_msg_send(&zmq_msg, outgoing_zmq_socket, ZMQ_SNDMORE)) < 0) { + int number_of_bytes = + zmq_msg_send(&zmq_msg, outgoing_zmq_socket, ZMQ_SNDMORE); + zmq_msg_close(&zmq_msg); + if ( number_of_bytes < 0 ) { EXCEPT(1, "zmq_msg_send (frame) failed."); } - zmq_msg_close(&zmq_msg); } /** @@ -360,6 +369,7 @@ void receiveBody(IMessage &msg, Buffer &buffer, ProtoBufFactory &factory, int number_of_bytes = 0; if ((number_of_bytes = zmq_msg_recv(&zmq_msg, incoming_zmq_socket, ZMQ_DONTWAIT)) < 0) { + zmq_msg_close(&zmq_msg); EXCEPT_PARAM(1, "RCV zmq_msg_recv (body) failed. Frame size: " << frame_size << " received " << number_of_bytes); } @@ -368,6 +378,7 @@ void receiveBody(IMessage &msg, Buffer &buffer, ProtoBufFactory &factory, if (frame_size > 0) { if (zmq_msg_size(&zmq_msg) != frame_size) { + zmq_msg_close(&zmq_msg); EXCEPT_PARAM(1, "RCV Invalid message body received. Expected: " << frame_size << ", got: " << zmq_msg_size(&zmq_msg)); @@ -377,6 +388,7 @@ void receiveBody(IMessage &msg, Buffer &buffer, ProtoBufFactory &factory, uint16_t desc_type = std::get(msg.get(MSG_TYPE)); std::unique_ptr payload = factory.create(desc_type); if (payload == nullptr) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "No payload was assigned something is wrong"); } copyFromBuffer(payload.get(), buffer); @@ -395,12 +407,14 @@ void receiveBody(IMessage &msg, Buffer &buffer, ProtoBufFactory &factory, std::unique_ptr payload = factory.create(msg_type); msg.setPayload(std::move(payload)); } else { + zmq_msg_close(&zmq_msg); EXCEPT(1, "Unrecognized message type specified unable to identify " "message body/payload"); } } if (zmq_msg_more(&zmq_msg)) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "There should not be additional messages after the body has " "been sent but there are...!"); } @@ -428,6 +442,7 @@ void sendBody(IMessage &msg, Buffer &buffer, void *outgoing_zmq_socket) { if (payload) { auto size = payload->ByteSizeLong(); if (size != frame_size) { + zmq_msg_close(&zmq_msg); EXCEPT_PARAM(1, "Frame and message sizes differ message size: " << size << " frame size: " << frame_size); } @@ -437,9 +452,11 @@ void sendBody(IMessage &msg, Buffer &buffer, void *outgoing_zmq_socket) { int number_of_bytes = 0; if ((number_of_bytes = zmq_msg_send(&zmq_msg, outgoing_zmq_socket, 0)) < 0) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "zmq_msg_send (body) failed."); } } else { + zmq_msg_close(&zmq_msg); EXCEPT(1, "Payload not defined... something went wrong"); } @@ -461,6 +478,7 @@ void receiveCorrelationID(IMessage &msg, void *incoming_zmq_socket, int number_of_bytes = 0; if ((number_of_bytes = zmq_msg_recv(&zmq_msg, incoming_zmq_socket, ZMQ_DONTWAIT)) < 0) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "RCV zmq_msg_recv (correlation id) failed."); } @@ -474,6 +492,7 @@ void receiveCorrelationID(IMessage &msg, void *incoming_zmq_socket, // Check to see if there are more parts if there are we are not currently set // up to handle it so you should throw an error if (!zmq_msg_more(&zmq_msg)) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "Should be receiving messages after correlation id. The key " "should follow but is not."); } @@ -488,6 +507,7 @@ void receiveKey(IMessage &msg, void *incoming_zmq_socket, int number_of_bytes = 0; if ((number_of_bytes = zmq_msg_recv(&zmq_msg, incoming_zmq_socket, ZMQ_DONTWAIT)) < 0) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "RCV zmq_msg_recv (key) failed."); } @@ -501,6 +521,7 @@ void receiveKey(IMessage &msg, void *incoming_zmq_socket, // Check to see if there are more parts if there are we are not currently set // up to handle it so you should throw an error if (!zmq_msg_more(&zmq_msg)) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "Should be receiving messages after key. The user ID should " "follow but is not."); } @@ -516,6 +537,7 @@ void sendCorrelationID(IMessage &msg, void *outgoing_zmq_socket) { memcpy(zmq_msg_data(&zmq_msg), correlation_id.c_str(), correlation_id.size()); } else { + zmq_msg_close(&zmq_msg); EXCEPT(1, "zmq_msg_send (correlation id) failed. Message missing " "correlation id, something is really wrong."); } @@ -523,6 +545,7 @@ void sendCorrelationID(IMessage &msg, void *outgoing_zmq_socket) { int number_of_bytes = 0; if ((number_of_bytes = zmq_msg_send(&zmq_msg, outgoing_zmq_socket, ZMQ_SNDMORE)) < 0) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "zmq_msg_send (correlation_id) failed."); } @@ -543,13 +566,13 @@ void sendKey(IMessage &msg, void *outgoing_zmq_socket) { memcpy(zmq_msg_data(&zmq_msg), no_key.c_str(), no_key.size()); } - int number_of_bytes = 0; - if ((number_of_bytes = - zmq_msg_send(&zmq_msg, outgoing_zmq_socket, ZMQ_SNDMORE)) < 0) { - EXCEPT(1, "zmq_msg_send (uid) failed."); - } + int number_of_bytes = + zmq_msg_send(&zmq_msg, outgoing_zmq_socket, ZMQ_SNDMORE); zmq_msg_close(&zmq_msg); + if( number_of_bytes < 0 ) { + EXCEPT(1, "zmq_msg_send (uid) failed."); + } } void receiveID(IMessage &msg, void *incoming_zmq_socket, @@ -560,6 +583,7 @@ void receiveID(IMessage &msg, void *incoming_zmq_socket, int number_of_bytes = 0; if ((number_of_bytes = zmq_msg_recv(&zmq_msg, incoming_zmq_socket, ZMQ_DONTWAIT)) < 0) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "RCV zmq_msg_recv (uid) failed."); } if (zmq_msg_size(&zmq_msg)) { @@ -572,6 +596,7 @@ void receiveID(IMessage &msg, void *incoming_zmq_socket, // Check to see if there are more parts if there are we are not currently set // up to handle it so you should throw an error if (!zmq_msg_more(&zmq_msg)) { + zmq_msg_close(&zmq_msg); EXCEPT(1, "Should be receiving messages after id. The frame should follow " "but is not."); } @@ -591,12 +616,12 @@ void sendID(IMessage &msg, void *outgoing_zmq_socket) { memcpy(zmq_msg_data(&zmq_msg), no_id.c_str(), no_id.size()); } - int number_of_bytes = 0; - if ((number_of_bytes = - zmq_msg_send(&zmq_msg, outgoing_zmq_socket, ZMQ_SNDMORE)) < 0) { + int number_of_bytes = + zmq_msg_send(&zmq_msg, outgoing_zmq_socket, ZMQ_SNDMORE); + zmq_msg_close(&zmq_msg); + if( number_of_bytes < 0 ) { EXCEPT(1, "zmq_msg_send (uid) failed."); } - zmq_msg_close(&zmq_msg); } } // namespace @@ -644,7 +669,15 @@ ZeroMQCommunicator::ZeroMQCommunicator(const SocketOptions &socket_options, m_log_context = log_context; auto socket_factory = SocketFactory(); m_socket = socket_factory.create(socket_options, credentials); - m_zmq_ctx = getContext(); + + // If running INPROC, each ZeroMQ socket should use the same context, other + // wise they should use a different context. + if ( socket_options.scheme == URIScheme::INPROC ) { + m_zmq_ctx = InprocContext::getContext(); + InprocContext::increment(); + } else { + m_zmq_ctx = zmq_ctx_new(); + } m_zmq_socket_type = translateToZMQSocket(m_socket.get()); m_zmq_socket = zmq_socket(m_zmq_ctx, m_zmq_socket_type); @@ -657,7 +690,12 @@ ZeroMQCommunicator::ZeroMQCommunicator(const SocketOptions &socket_options, const int keep_alive_intvl = 5; const int reconnect_ivl = 500; const int reconnect_ivl_max = 4000; - const int linger_milliseconds = 100; + + const int linger_milliseconds = 1000; + const int num_messages = 10000000; + + zmq_setsockopt(m_zmq_socket, ZMQ_RCVHWM, &num_messages, sizeof(const int)); + zmq_setsockopt(m_zmq_socket, ZMQ_SNDHWM, &num_messages, sizeof(const int)); zmq_setsockopt(m_zmq_socket, ZMQ_TCP_KEEPALIVE, &keep_alive, sizeof(const int)); @@ -731,6 +769,24 @@ ZeroMQCommunicator::~ZeroMQCommunicator() { err_message += m_socket->getAddress().c_str(); DL_WARNING(m_log_context, err_message); } + + rc = 0; + if ( m_socket->getSocketScheme() == URIScheme::INPROC ) { + InprocContext::decrement(); + // Only call terminate if counter is at 0; + if( InprocContext::get() == 0 ) { + rc = InprocContext::resetContext(); + } + } else { + rc = zmq_ctx_term(m_zmq_ctx); + } + if (rc) { + std::string err_message = + "Problem closing zmq context in Communicator destruct. Socket address: "; + err_message += m_socket->getAddress().c_str(); + DL_WARNING(m_log_context, err_message); + } + } ICommunicator::Response @@ -780,12 +836,24 @@ ZeroMQCommunicator::poll(const MessageType message_type) { void ZeroMQCommunicator::send(IMessage &message) { + uint16_t msg_type = std::get(message.get(constants::message::google::MSG_TYPE)); ProtoBufMap proto_map; LogContext log_context = m_log_context; log_context.correlation_id = std::get(message.get(MessageAttribute::CORRELATION_ID)); + + int events; + size_t events_size = sizeof(events); + zmq_getsockopt(m_zmq_socket, ZMQ_EVENTS, &events, &events_size); + + if (events & ZMQ_POLLOUT) { + DL_INFO(log_context, "Socket is ready to send data."); + } else { + DL_WARNING(log_context,"Socket send buffer is full! Messages may be dropped."); + } + std::string err_message = "Sending message on communicator id: " + id(); err_message += ", to address: " + address() + ", msg type: " + proto_map.toString(msg_type); diff --git a/common/source/communicators/ZeroMQCommunicatorSecure.cpp b/common/source/communicators/ZeroMQCommunicatorSecure.cpp index 48d1da2ac..3ae342f2f 100644 --- a/common/source/communicators/ZeroMQCommunicatorSecure.cpp +++ b/common/source/communicators/ZeroMQCommunicatorSecure.cpp @@ -149,11 +149,28 @@ ZeroMQCommunicatorSecure::ZeroMQCommunicatorSecure( auto socket_factory = SocketFactory(); m_socket = socket_factory.create(socket_options, credentials); - m_zmq_ctx = getContext(); + + // If running INPROC, each ZeroMQ socket should use the same context, other + // wise they should a different context. + if ( socket_options.scheme == URIScheme::INPROC ) { + m_zmq_ctx = InprocContext::getContext(); + InprocContext::increment(); + } else { + m_zmq_ctx = zmq_ctx_new(); + } + m_zmq_socket_type = translateToZMQSocket(m_socket.get()); m_zmq_socket = zmq_socket(m_zmq_ctx, m_zmq_socket_type); - // Order matters must occur after m_zmq_socket has be been created + if (m_zmq_socket == nullptr) { + int err = zmq_errno(); + std::string error_message = zmq_strerror(err); + EXCEPT_PARAM(1, "Error creating ZeroMQ socket (type: " + << zmqSocketTypeToString(m_zmq_socket_type) + << "): [" << err << "] " << error_message); + } + + // Order matters must occur after m_zmq_socket has been created zmqCurveSetup(credentials); // -1 - Leave to OS // Not sure what 0 and 1 do other than mean you are going to overide @@ -164,7 +181,9 @@ ZeroMQCommunicatorSecure::ZeroMQCommunicatorSecure( const int keep_alive_intvl = 5; const int reconnect_ivl = 500; const int reconnect_ivl_max = 4000; - const int linger_milliseconds = 100; + // How long messages wait in the queue before being dropped + const int linger_milliseconds = 1000; + const int num_messages = 10000000; zmq_setsockopt(m_zmq_socket, ZMQ_TCP_KEEPALIVE, &keep_alive, sizeof(const int)); @@ -181,6 +200,9 @@ ZeroMQCommunicatorSecure::ZeroMQCommunicatorSecure( zmq_setsockopt(m_zmq_socket, ZMQ_LINGER, &linger_milliseconds, sizeof(const int)); + zmq_setsockopt(m_zmq_socket, ZMQ_RCVHWM, &num_messages, sizeof(const int)); + zmq_setsockopt(m_zmq_socket, ZMQ_SNDHWM, &num_messages, sizeof(const int)); + std::string id = m_socket->getID(); if (id.size() > constants::communicator::MAX_COMMUNICATOR_IDENTITY_SIZE) { diff --git a/common/source/communicators/ZeroMQCommunicatorSecure.hpp b/common/source/communicators/ZeroMQCommunicatorSecure.hpp index 083ab8b29..d4c64230d 100644 --- a/common/source/communicators/ZeroMQCommunicatorSecure.hpp +++ b/common/source/communicators/ZeroMQCommunicatorSecure.hpp @@ -22,6 +22,8 @@ class ZeroMQCommunicatorSecure : public ZeroMQCommunicator { LogContext m_log_context; public: + virtual ~ZeroMQCommunicatorSecure() {}; + ZeroMQCommunicatorSecure(const SocketOptions &socket_options, const ICredentials &credentials, uint32_t timeout_on_receive_milliseconds, diff --git a/common/source/credentials/ZeroMQSocketCredentials.hpp b/common/source/credentials/ZeroMQSocketCredentials.hpp index a65b2dbd4..39c0cdc20 100644 --- a/common/source/credentials/ZeroMQSocketCredentials.hpp +++ b/common/source/credentials/ZeroMQSocketCredentials.hpp @@ -22,6 +22,9 @@ class ZeroMQSocketCredentials : public ICredentials { void validate(); public: + + virtual ~ZeroMQSocketCredentials() {}; + ZeroMQSocketCredentials() = default; ZeroMQSocketCredentials( diff --git a/common/source/messages/GoogleProtoMessage.hpp b/common/source/messages/GoogleProtoMessage.hpp index 081b564ae..6620ba88b 100644 --- a/common/source/messages/GoogleProtoMessage.hpp +++ b/common/source/messages/GoogleProtoMessage.hpp @@ -40,6 +40,7 @@ class GoogleProtoMessage : public IMessage { public: GoogleProtoMessage(); + virtual ~GoogleProtoMessage() {}; private: MessageState m_state = MessageState::REQUEST; diff --git a/common/source/operators/AuthenticationOperator.cpp b/common/source/operators/AuthenticationOperator.cpp index 9c9113f09..3c230d974 100644 --- a/common/source/operators/AuthenticationOperator.cpp +++ b/common/source/operators/AuthenticationOperator.cpp @@ -3,6 +3,7 @@ #include "AuthenticationOperator.hpp" // Local public includes +#include "common/DynaLog.hpp" #include "common/TraceException.hpp" // Standard includes @@ -31,10 +32,18 @@ void AuthenticationOperator::execute(IMessage &message) { std::string key = std::get(message.get(MessageAttribute::KEY)); std::string uid = "anon"; + + LogContext log_context; + log_context.thread_name = "authentication_manager"; + log_context.thread_id = 0; + log_context.correlation_id = std::get( + message.get(MessageAttribute::CORRELATION_ID)); + if (m_authentication_manager->hasKey(key)) { m_authentication_manager->incrementKeyAccessCounter(key); uid = m_authentication_manager->getUID(key); } + DL_INFO(log_context, "Attempt to map key to " << key << " uid set to: " << uid ); message.set(MessageAttribute::ID, uid); } diff --git a/common/source/operators/AuthenticationOperator.hpp b/common/source/operators/AuthenticationOperator.hpp index ae3b5bc58..ee949d275 100644 --- a/common/source/operators/AuthenticationOperator.hpp +++ b/common/source/operators/AuthenticationOperator.hpp @@ -40,6 +40,7 @@ class AuthenticationOperator : public IOperator { : m_authentication_manager(&auth_manager){}; static std::unique_ptr create(std::any options); + virtual ~AuthenticationOperator() {}; private: IAuthenticationManager *m_authentication_manager; diff --git a/common/source/operators/RouterBookKeepingOperator.hpp b/common/source/operators/RouterBookKeepingOperator.hpp index a83459881..445844741 100644 --- a/common/source/operators/RouterBookKeepingOperator.hpp +++ b/common/source/operators/RouterBookKeepingOperator.hpp @@ -20,6 +20,9 @@ class RouterBookKeepingOperator : public IOperator { * combination is not being used **/ public: + + virtual ~RouterBookKeepingOperator(){}; + explicit RouterBookKeepingOperator(std::any options); static std::unique_ptr create(std::any options); diff --git a/common/source/servers/Proxy.cpp b/common/source/servers/Proxy.cpp index 11894df0a..e7b4cc5a7 100644 --- a/common/source/servers/Proxy.cpp +++ b/common/source/servers/Proxy.cpp @@ -60,16 +60,27 @@ Proxy::Proxy( CommunicatorFactory communication_factory(m_log_context); - m_communicators[SocketRole::CLIENT] = communication_factory.create( - socket_options.at(SocketRole::CLIENT), - *socket_credentials.at(SocketRole::CLIENT), - m_timeout_on_receive_milliseconds, m_timeout_on_poll_milliseconds); - + // WARNING: Do not reorder the communication creation order, the server and a call to bind + // when using INPROC must occur before a client connect call can be + // made. + // + // https://zguide.zeromq.org/docs/chapter2/ + // + // > The inter-thread transport, inproc, is a connected signaling transport. + // > It is much faster than tcp or ipc. This transport has a specific + // > limitation compared to tcp and ipc: the server must issue a bind before + // > any client issues a connect. This was fixed in ZeroMQ v4.0 and later + // > versions. m_communicators[SocketRole::SERVER] = communication_factory.create( socket_options.at(SocketRole::SERVER), *socket_credentials.at(SocketRole::SERVER), m_timeout_on_receive_milliseconds, m_timeout_on_poll_milliseconds); + m_communicators[SocketRole::CLIENT] = communication_factory.create( + socket_options.at(SocketRole::CLIENT), + *socket_credentials.at(SocketRole::CLIENT), + m_timeout_on_receive_milliseconds, m_timeout_on_poll_milliseconds); + m_addresses[SocketRole::CLIENT] = m_communicators[SocketRole::CLIENT]->address(); m_addresses[SocketRole::SERVER] = diff --git a/common/source/servers/Proxy.hpp b/common/source/servers/Proxy.hpp index c8442d400..4cff894c3 100644 --- a/common/source/servers/Proxy.hpp +++ b/common/source/servers/Proxy.hpp @@ -44,6 +44,8 @@ class Proxy : public IServer { std::vector> incoming_operators, LogContext log_context); + virtual ~Proxy() {}; + virtual ServerType type() const noexcept final { return ServerType::PROXY_CUSTOM; } diff --git a/common/source/servers/ProxyBasicZMQ.cpp b/common/source/servers/ProxyBasicZMQ.cpp index eda7f3bfe..0de100417 100644 --- a/common/source/servers/ProxyBasicZMQ.cpp +++ b/common/source/servers/ProxyBasicZMQ.cpp @@ -137,48 +137,41 @@ void ProxyBasicZMQ::setRunDuration(std::chrono::duration duration) { void ProxyBasicZMQ::run() { - void *ctx = getContext(); + void *ctx = InprocContext::getContext(); /** - * Control socket receives terminate command from main over inproc + * WARNING: Best practice is to bind sockets before creating connections + * Specifically for INPROC channels. * - * In the case that we need to exit early or run the proxy for a fixed - * amount of time. + * https://zguide.zeromq.org/docs/chapter2/ * - * WARNING the order matters the SUB only works for sockets bind and or - * connects made to it after it has been created and connected + * > The inter-thread transport, inproc, is a connected signaling transport. + * > It is much faster than tcp or ipc. This transport has a specific + * > limitation compared to tcp and ipc: the server must issue a bind before + * > any client issues a connect. This was fixed in ZeroMQ v4.0 and later + * > versions. **/ - void *control_socket = nullptr; - if (m_run_infinite_loop == false) { - control_socket = zmq_socket(ctx, ZMQ_SUB); - if (not control_socket) { - EXCEPT(1, "Problem creating control socket"); - } - int rc = zmq_setsockopt(control_socket, ZMQ_SUBSCRIBE, "", 0); - if (rc) { - EXCEPT(1, "Problem subscribing control socket"); - } - rc = zmq_connect(control_socket, m_addresses[SocketRole::CONTROL].c_str()); - if (rc) { - EXCEPT(1, "Problem connecting control socket"); - } - int linger = 100; - zmq_setsockopt(control_socket, ZMQ_LINGER, &linger, sizeof(linger)); + void *router_frontend_socket = zmq_socket(ctx, ZMQ_ROUTER); + if (not router_frontend_socket) { + EXCEPT(1, "Problem creating frontend ROUTER socket"); } - - void *capture_socket = nullptr; - if (m_debug_output) { - capture_socket = zmq_socket(ctx, ZMQ_PUB); - if (not capture_socket) { - EXCEPT(1, "Problem creating capture socket"); - } - int rc = - zmq_connect(capture_socket, m_addresses[SocketRole::MONITOR].c_str()); - if (rc) { - EXCEPT(1, "Problem connecting capture socket"); - } - int linger = 100; - zmq_setsockopt(capture_socket, ZMQ_LINGER, &linger, sizeof(linger)); + int router_linger = 100; + zmq_setsockopt(router_frontend_socket, ZMQ_LINGER, &router_linger, + sizeof(int)); + /** + * NOTE + * + * The socket on the proxy that will connect with the frontend is a + * server socket. The proxy serves the frontend. + **/ + DL_DEBUG(m_log_context, + "Binding ROUTER to address: " << m_server_socket->getAddress()); + int rc = + zmq_bind(router_frontend_socket, m_server_socket->getAddress().c_str()); + if (rc) { + EXCEPT_PARAM(1, "Problem binding frontend ROUTER socket, address: " + << m_server_socket->getAddress() + << " zmq_error: " << zmq_strerror(zmq_errno())); } /** @@ -192,7 +185,7 @@ void ProxyBasicZMQ::run() { log_context.thread_id = thread_id; DL_INFO(log_context, "Launching control thread for duration: " << duration.count()); - void *context = getContext(); + void *context = InprocContext::getContext(); auto control_local = zmq_socket(context, ZMQ_PUB); DL_INFO(log_context, "CONTROL: Sleeping"); std::this_thread::sleep_for(duration); @@ -206,6 +199,14 @@ void ProxyBasicZMQ::run() { } }; + std::thread control_thread; + if (m_run_infinite_loop == false) { + control_thread = std::thread(terminate_call, m_run_duration, + m_addresses[SocketRole::CONTROL], + m_thread_count, m_log_context); + ++m_thread_count; + } + /** * Thread is for debugging purposes mostly, for logging the messages * that are sent through the steerable proxy. @@ -214,7 +215,7 @@ void ProxyBasicZMQ::run() { LogContext log_context) { log_context.thread_name += "-capture_thread"; log_context.thread_id = thread_id; - void *context = getContext(); + void *context = InprocContext::getContext(); auto capture_local = zmq_socket(context, ZMQ_SUB); zmq_bind(capture_local, address.c_str()); zmq_setsockopt(capture_local, ZMQ_SUBSCRIBE, "", 0); @@ -256,20 +257,13 @@ void ProxyBasicZMQ::run() { } } } + int rc_local = zmq_close(capture_local); if (rc_local) { EXCEPT(1, "Problem closing capture socket from SUBSCRIBING thread"); } }; - std::thread control_thread; - if (m_run_infinite_loop == false) { - control_thread = std::thread(terminate_call, m_run_duration, - m_addresses[SocketRole::CONTROL], - m_thread_count, m_log_context); - ++m_thread_count; - } - std::thread capture_thread; if (m_debug_output) { capture_thread = @@ -278,32 +272,9 @@ void ProxyBasicZMQ::run() { ++m_thread_count; } - void *router_frontend_socket = zmq_socket(ctx, ZMQ_ROUTER); - if (not router_frontend_socket) { - EXCEPT(1, "Problem creating frontend ROUTER socket"); - } - int router_linger = 100; - zmq_setsockopt(router_frontend_socket, ZMQ_LINGER, &router_linger, - sizeof(int)); - /** - * NOTE - * - * The socket on the proxy that will connect with the frontend is a - * server socket. The proxy serves the frontend. - **/ - DL_DEBUG(m_log_context, - "Binding ROUTER to address: " << m_server_socket->getAddress()); - int rc = - zmq_bind(router_frontend_socket, m_server_socket->getAddress().c_str()); - if (rc) { - EXCEPT_PARAM(1, "Problem binding frontend ROUTER socket, address: " - << m_server_socket->getAddress() - << " zmq_error: " << zmq_strerror(zmq_errno())); - } - // Backend socket talks to workers over inproc void *dealer_backend_socket = zmq_socket(ctx, ZMQ_DEALER); - if (not router_frontend_socket) { + if (not dealer_backend_socket) { EXCEPT(1, "Problem creating backend DEALER socket"); } int dealer_linger = 100; @@ -323,6 +294,48 @@ void ProxyBasicZMQ::run() { << m_client_socket->getAddress()); } + /** + * Control socket receives terminate command from main over inproc + * + * In the case that we need to exit early or run the proxy for a fixed + * amount of time. + * + * WARNING the order matters the SUB only works for sockets bind and or + * connects made to it after it has been created and connected + **/ + void *control_socket = nullptr; + if (m_run_infinite_loop == false) { + control_socket = zmq_socket(ctx, ZMQ_SUB); + if (not control_socket) { + EXCEPT(1, "Problem creating control socket"); + } + int rc = zmq_setsockopt(control_socket, ZMQ_SUBSCRIBE, "", 0); + if (rc) { + EXCEPT(1, "Problem subscribing control socket"); + } + rc = zmq_connect(control_socket, m_addresses[SocketRole::CONTROL].c_str()); + if (rc) { + EXCEPT(1, "Problem connecting control socket"); + } + int linger = 100; + zmq_setsockopt(control_socket, ZMQ_LINGER, &linger, sizeof(linger)); + } + + void *capture_socket = nullptr; + if (m_debug_output) { + capture_socket = zmq_socket(ctx, ZMQ_PUB); + if (not capture_socket) { + EXCEPT(1, "Problem creating capture socket"); + } + int rc = + zmq_connect(capture_socket, m_addresses[SocketRole::MONITOR].c_str()); + if (rc) { + EXCEPT(1, "Problem connecting capture socket"); + } + int linger = 100; + zmq_setsockopt(capture_socket, ZMQ_LINGER, &linger, sizeof(linger)); + } + // Connect backend to frontend via a proxy zmq_proxy_steerable(router_frontend_socket, dealer_backend_socket, capture_socket, control_socket); diff --git a/common/source/servers/ProxyBasicZMQ.hpp b/common/source/servers/ProxyBasicZMQ.hpp index b4fc644e7..e3dbdf003 100644 --- a/common/source/servers/ProxyBasicZMQ.hpp +++ b/common/source/servers/ProxyBasicZMQ.hpp @@ -40,6 +40,8 @@ class ProxyBasicZMQ : public IServer { const std::unordered_map &socket_credentials, LogContext log_context); + virtual ~ProxyBasicZMQ() {}; + virtual ServerType type() const noexcept final { return ServerType::PROXY_BASIC_ZMQ; } diff --git a/common/source/sockets/ZeroMQSocket.hpp b/common/source/sockets/ZeroMQSocket.hpp index 03c806d63..cba748c2e 100644 --- a/common/source/sockets/ZeroMQSocket.hpp +++ b/common/source/sockets/ZeroMQSocket.hpp @@ -31,6 +31,7 @@ class ZeroMQSocket : public ISocket { ZeroMQSocket(const SocketOptions &socket_options); + ~ZeroMQSocket() {}; /********************************************************* * Getters *********************************************************/ @@ -57,6 +58,10 @@ class ZeroMQSocket : public ISocket { return ProtocolType::ZQTP; }; + virtual URIScheme getSocketScheme() const noexcept final { + return m_scheme; + } + virtual std::string getAddress() const noexcept final; virtual std::string get(const CredentialType credential_type) const final; diff --git a/common/source/support/zeromq/Context.hpp b/common/source/support/zeromq/Context.hpp index 178d63d6f..99bf9dda9 100644 --- a/common/source/support/zeromq/Context.hpp +++ b/common/source/support/zeromq/Context.hpp @@ -5,14 +5,52 @@ // Third party includes #include +// Standard library includes +#include +#include + namespace SDMS { -/** - * Singleton Pattern for Security Context of zmq. - **/ -inline void *getContext() { - static void *context = zmq_ctx_new(); - return context; -} + + +class InprocContext { +public: + static int get() { + return counter.load(); + } + + static void increment() { + counter++; + } + + static void decrement() { + counter--; + } + + static void *getContext() { + if (context == nullptr) { + context = zmq_ctx_new(); + } + return context; + } + + static int resetContext() { + int rc = 0; + if (context != nullptr) { + std::cout << "Terminating and resetting context" << std::endl; + rc = zmq_ctx_term(context); + // zmq_ctx_destroy(context); // Consider if you need this (deprecated) + context = nullptr; + } else { + std::cout << "Context is already null" << std::endl; + } + return rc; + } + +private: + inline static std::atomic counter = 0; + inline static void *context = nullptr; +}; + } // namespace SDMS #endif // ZMQCONTEXT_HPP diff --git a/common/tests/CMakeLists.txt b/common/tests/CMakeLists.txt index b451c65d1..7e46fa87b 100644 --- a/common/tests/CMakeLists.txt +++ b/common/tests/CMakeLists.txt @@ -1,4 +1,4 @@ -if( ENABLE_UNIT_TESTS ) +if( ENABLE_UNIT_TESTS OR ENABLE_MEMORY_TESTS ) add_subdirectory(unit) -endif( ENABLE_UNIT_TESTS ) +endif( ENABLE_UNIT_TESTS OR ENABLE_MEMORY_TESTS ) add_subdirectory(security) diff --git a/common/tests/unit/CMakeLists.txt b/common/tests/unit/CMakeLists.txt index 5e318b6d9..60f169546 100644 --- a/common/tests/unit/CMakeLists.txt +++ b/common/tests/unit/CMakeLists.txt @@ -27,7 +27,11 @@ foreach(PROG common libzmq-static protobuf::libprotobuf Threads::Threads) endif() # Only want this if using shared boost libraries - add_test(unit_${PROG} unit_${PROG}) - + if ( ENABLE_UNIT_TESTS ) + add_test(unit_${PROG} unit_${PROG}) + endif( ENABLE_UNIT_TESTS ) + if ( ENABLE_MEMORY_TESTS ) + add_test(NAME memory_${PROG} COMMAND valgrind --leak-check=full --error-exitcode=1 $) + endif( ENABLE_MEMORY_TESTS ) endforeach(PROG) diff --git a/common/tests/unit/test_Buffer.cpp b/common/tests/unit/test_Buffer.cpp index 9b9fbe82b..74ff9dec8 100644 --- a/common/tests/unit/test_Buffer.cpp +++ b/common/tests/unit/test_Buffer.cpp @@ -16,6 +16,16 @@ using namespace SDMS; +struct GlobalProtobufTeardown { + ~GlobalProtobufTeardown() { + // This is the teardown function that runs once at the end + google::protobuf::ShutdownProtobufLibrary(); + } +}; + +// Declare a global fixture instance +BOOST_GLOBAL_FIXTURE(GlobalProtobufTeardown); + BOOST_AUTO_TEST_SUITE(BufferTest) BOOST_AUTO_TEST_CASE(testing_Buffer) { diff --git a/common/tests/unit/test_CommunicatorFactory.cpp b/common/tests/unit/test_CommunicatorFactory.cpp index 53ff86680..a5c6f3a77 100644 --- a/common/tests/unit/test_CommunicatorFactory.cpp +++ b/common/tests/unit/test_CommunicatorFactory.cpp @@ -45,6 +45,16 @@ SocketOptions generateCommonOptions(const std::string channel) { return socket_options; } +struct GlobalProtobufTeardown { + ~GlobalProtobufTeardown() { + // This is the teardown function that runs once at the end + google::protobuf::ShutdownProtobufLibrary(); + } +}; + +// Declare a global fixture instance +BOOST_GLOBAL_FIXTURE(GlobalProtobufTeardown); + BOOST_AUTO_TEST_SUITE(CommunicatorFactoryTest) BOOST_AUTO_TEST_CASE(testing_CommunicatorFactory) { diff --git a/common/tests/unit/test_Frame.cpp b/common/tests/unit/test_Frame.cpp index de7ec896f..2ee80b09e 100644 --- a/common/tests/unit/test_Frame.cpp +++ b/common/tests/unit/test_Frame.cpp @@ -19,6 +19,16 @@ using namespace SDMS; +struct GlobalProtobufTeardown { + ~GlobalProtobufTeardown() { + // This is the teardown function that runs once at the end + google::protobuf::ShutdownProtobufLibrary(); + } +}; + +// Declare a global fixture instance +BOOST_GLOBAL_FIXTURE(GlobalProtobufTeardown); + BOOST_AUTO_TEST_SUITE(FrameTest) BOOST_AUTO_TEST_CASE(testing_Frame) { diff --git a/common/tests/unit/test_MessageFactory.cpp b/common/tests/unit/test_MessageFactory.cpp index 7f9a18200..3df758e7e 100644 --- a/common/tests/unit/test_MessageFactory.cpp +++ b/common/tests/unit/test_MessageFactory.cpp @@ -13,6 +13,16 @@ using namespace SDMS; +struct GlobalProtobufTeardown { + ~GlobalProtobufTeardown() { + // This is the teardown function that runs once at the end + google::protobuf::ShutdownProtobufLibrary(); + } +}; + +// Declare a global fixture instance +BOOST_GLOBAL_FIXTURE(GlobalProtobufTeardown); + BOOST_AUTO_TEST_SUITE(MessageFactoryTest) BOOST_AUTO_TEST_CASE(testing_MessageFactory) { diff --git a/common/tests/unit/test_OperatorFactory.cpp b/common/tests/unit/test_OperatorFactory.cpp index 30004adbd..f91bdcc2a 100644 --- a/common/tests/unit/test_OperatorFactory.cpp +++ b/common/tests/unit/test_OperatorFactory.cpp @@ -11,6 +11,9 @@ #include "common/OperatorFactory.hpp" #include "common/OperatorTypes.hpp" +// Third party includes +#include + // Standard includes #include #include @@ -18,6 +21,16 @@ using namespace SDMS; +struct GlobalProtobufTeardown { + ~GlobalProtobufTeardown() { + // This is the teardown function that runs once at the end + google::protobuf::ShutdownProtobufLibrary(); + } +}; + +// Declare a global fixture instance +BOOST_GLOBAL_FIXTURE(GlobalProtobufTeardown); + class DummyAuthManager : public IAuthenticationManager { private: std::unordered_map m_counters; diff --git a/common/tests/unit/test_ProtoBufFactory.cpp b/common/tests/unit/test_ProtoBufFactory.cpp index b901e18bd..a3d0c4910 100644 --- a/common/tests/unit/test_ProtoBufFactory.cpp +++ b/common/tests/unit/test_ProtoBufFactory.cpp @@ -19,6 +19,16 @@ using namespace SDMS; +struct GlobalProtobufTeardown { + ~GlobalProtobufTeardown() { + // This is the teardown function that runs once at the end + google::protobuf::ShutdownProtobufLibrary(); + } +}; + +// Declare a global fixture instance +BOOST_GLOBAL_FIXTURE(GlobalProtobufTeardown); + BOOST_AUTO_TEST_SUITE(ProtoBufFactoryTest) BOOST_AUTO_TEST_CASE(testing_ProtoBufFactory) { diff --git a/common/tests/unit/test_ProtoBufMap.cpp b/common/tests/unit/test_ProtoBufMap.cpp index b780d8b2c..21c12c2e0 100644 --- a/common/tests/unit/test_ProtoBufMap.cpp +++ b/common/tests/unit/test_ProtoBufMap.cpp @@ -15,6 +15,16 @@ using namespace SDMS; +struct GlobalProtobufTeardown { + ~GlobalProtobufTeardown() { + // This is the teardown function that runs once at the end + google::protobuf::ShutdownProtobufLibrary(); + } +}; + +// Declare a global fixture instance +BOOST_GLOBAL_FIXTURE(GlobalProtobufTeardown); + BOOST_AUTO_TEST_SUITE(ProtoBufFactoryTest) BOOST_AUTO_TEST_CASE(testing_ProtoBufFactory_ProtocolID) { diff --git a/common/tests/unit/test_Proxy.cpp b/common/tests/unit/test_Proxy.cpp index c0223fca4..5156756d6 100644 --- a/common/tests/unit/test_Proxy.cpp +++ b/common/tests/unit/test_Proxy.cpp @@ -59,6 +59,16 @@ const std::string secret_key = const std::string server_key = "Wce6y$B4vXjM$xnM^tRGJGP^ads5hxkDSULJWM&9"; // 40 chars +struct GlobalProtobufTeardown { + ~GlobalProtobufTeardown() { + // This is the teardown function that runs once at the end + google::protobuf::ShutdownProtobufLibrary(); + } +}; + +// Declare a global fixture instance +BOOST_GLOBAL_FIXTURE(GlobalProtobufTeardown); + BOOST_AUTO_TEST_SUITE(ProxyTest) BOOST_AUTO_TEST_CASE(testing_Proxy) { diff --git a/common/tests/unit/test_ProxyBasicZMQ.cpp b/common/tests/unit/test_ProxyBasicZMQ.cpp index ba9a7db41..03b2f3328 100644 --- a/common/tests/unit/test_ProxyBasicZMQ.cpp +++ b/common/tests/unit/test_ProxyBasicZMQ.cpp @@ -60,6 +60,16 @@ const std::string secret_key = const std::string server_key = "AX0D+@G+P$Wv.join(); } - // std::cout << "GET CONTEXT and exit" << std::endl; - // auto context = getContext(); - // zmq_ctx_destroy(context); } BOOST_AUTO_TEST_CASE(testing_ProxyBasicZMQ_Reply) { @@ -534,10 +541,6 @@ BOOST_AUTO_TEST_CASE(testing_ProxyBasicZMQ_Reply) { proxy_thread->join(); std::cout << __FILE__ << ":" << __LINE__ << std::endl; } - // std::cout << "GET CONTEXT and exit" << std::endl; - - // auto context = getContext(); - // zmq_ctx_destroy(context); } BOOST_AUTO_TEST_CASE(testing_ProxyBasicZMQ_TCPServer_Reply) { @@ -823,8 +826,5 @@ BOOST_AUTO_TEST_CASE(testing_ProxyBasicZMQ_TCPServer_Reply) { std::cout << __FILE__ << ":" << __LINE__ << std::endl; } std::cout << "GET CONTEXT and exit" << std::endl; - - auto context = getContext(); - zmq_ctx_destroy(context); } BOOST_AUTO_TEST_SUITE_END() diff --git a/compose/all/compose.yml b/compose/all/compose.yml index 162b79308..64d1195fd 100644 --- a/compose/all/compose.yml +++ b/compose/all/compose.yml @@ -48,6 +48,7 @@ services: DATAFED_DATABASE_PASSWORD: "${DATAFED_DATABASE_PASSWORD}" DATAFED_DATABASE_IP_ADDRESS: "${DATAFED_DATABASE_IP_ADDRESS}" DATAFED_DATABASE_IP_ADDRESS_PORT: "${DATAFED_DATABASE_IP_ADDRESS}:${DATAFED_DATABASE_PORT}" + DATAFED_CORE_LOG_LEVEL: "${DATAFED_CORE_LOG_LEVEL}" ports: - 7513 # Communication web server - 7512:7512 # Secure core server communication must be exposed outside of the container @@ -68,6 +69,9 @@ services: DATAFED_DATABASE_PASSWORD: "${DATAFED_DATABASE_PASSWORD}" DATAFED_DATABASE_IP_ADDRESS: "${DATAFED_DATABASE_IP_ADDRESS}" DATAFED_DATABASE_HOST: "arango" + # NOTE enabling foxx tests will cause state changes in the database + # do not run this unless you are ok with the database being wiped. + ENABLE_FOXX_TESTS: "${DATAFED_ENABLE_FOXX_TESTS}" healthcheck: test: ["CMD", "/bin/bash", "-c", "[ -f /tmp/.foxx_is_installed ]"] interval: 10s @@ -79,7 +83,7 @@ services: - datafed-internal arango: - image: arangodb:3.12.0.2 + image: arangodb/arangodb:3.12.4 environment: ARANGO_ROOT_PASSWORD: "${DATAFED_DATABASE_PASSWORD}" volumes: @@ -113,6 +117,8 @@ services: - ${DATAFED_HOST_COLLECTION_MOUNT}:${DATAFED_GCS_COLLECTION_ROOT_PATH}/${DATAFED_REPO_ID_AND_DIR} ports: - 9000:9000 # Communication core server + networks: + - datafed-internal # Needs host port 80 for apache # Needs ports 50000 - 51000 for GridFTP diff --git a/compose/all/generate_env.sh b/compose/all/generate_env.sh index 87b51b4af..47be24538 100755 --- a/compose/all/generate_env.sh +++ b/compose/all/generate_env.sh @@ -3,5 +3,8 @@ SCRIPT=$(realpath "$0") SOURCE=$(dirname "$SCRIPT") PROJECT_ROOT=$(realpath "${SOURCE}/../../") +# Variables specific to running the compose instance +export DATAFED_COMPOSE_REPO_DOMAIN="datafed-repo" + "${PROJECT_ROOT}/scripts/compose_generate_env.sh" -d "$(pwd)" diff --git a/compose/metadata/build_metadata_images_for_compose.sh b/compose/metadata/build_metadata_images_for_compose.sh index 2490e969e..28f8f4de4 100755 --- a/compose/metadata/build_metadata_images_for_compose.sh +++ b/compose/metadata/build_metadata_images_for_compose.sh @@ -25,6 +25,4 @@ fi # Load the variables from the build_args . "$BUILD_ARG_FILE" -echo "BASE_IMAGE is $BASE_IMAGE" - "${PROJECT_ROOT}/scripts/compose_build_images.sh" -m -b "$BASE_IMAGE" diff --git a/compose/metadata/compose.yml b/compose/metadata/compose.yml index d443f3606..a3fa4f41d 100644 --- a/compose/metadata/compose.yml +++ b/compose/metadata/compose.yml @@ -45,6 +45,7 @@ services: DATAFED_DATABASE_PASSWORD: "${DATAFED_DATABASE_PASSWORD}" DATAFED_DATABASE_IP_ADDRESS: "${DATAFED_DATABASE_IP_ADDRESS}" DATAFED_DATABASE_IP_ADDRESS_PORT: "${DATAFED_DATABASE_IP_ADDRESS}:${DATAFED_DATABASE_PORT}" + DATAFED_CORE_LOG_LEVEL: "${DATAFED_CORE_LOG_LEVEL}" ports: - 7513 # Communication web server - 7512:7512 # Secure core server communication must be exposed outside of the container @@ -65,6 +66,9 @@ services: DATAFED_DATABASE_PASSWORD: "${DATAFED_DATABASE_PASSWORD}" DATAFED_DATABASE_IP_ADDRESS: "${DATAFED_DATABASE_IP_ADDRESS}" DATAFED_DATABASE_HOST: "arango" + # NOTE enabling foxx tests will cause state changes in the database + # do not run this unless you are ok with the database being wiped. + ENABLE_FOXX_TESTS: "${DATAFED_ENABLE_FOXX_TESTS}" healthcheck: test: ["CMD", "/bin/bash", "-c", "[ -f /tmp/.foxx_is_installed ]"] interval: 10s @@ -76,7 +80,7 @@ services: - datafed-internal arango: - image: arangodb:3.12.0.2 + image: arangodb/arangodb:3.12.4 environment: ARANGO_ROOT_PASSWORD: "${DATAFED_DATABASE_PASSWORD}" volumes: diff --git a/core/database/CMakeLists.txt b/core/database/CMakeLists.txt index 34527dabd..17bdd6da1 100644 --- a/core/database/CMakeLists.txt +++ b/core/database/CMakeLists.txt @@ -13,11 +13,33 @@ configure_file( if( ENABLE_FOXX_TESTS ) add_test(NAME foxx_setup COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_setup.sh") add_test(NAME foxx_teardown COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_teardown.sh") - add_test(NAME foxx_version COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_foxx.sh" -t "version") - add_test(NAME foxx_support COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_foxx.sh" -t "support") + add_test(NAME foxx_authz COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_foxx.sh" -t "unit_authz") + add_test(NAME foxx_record COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_foxx.sh" -t "unit_record") + add_test(NAME foxx_repo COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_foxx.sh" -t "unit_repo") + add_test(NAME foxx_path COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_foxx.sh" -t "unit_path") + add_test(NAME foxx_db_fixtures COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_fixture_setup.sh") + add_test(NAME foxx_version COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_foxx.sh" -t "unit_version") + add_test(NAME foxx_support COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_foxx.sh" -t "unit_support") + add_test(NAME foxx_user_router COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_foxx.sh" -t "unit_user_router") + add_test(NAME foxx_authz_router COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_foxx.sh" -t "unit_authz_router") + add_test(NAME foxx_unit_user_token COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_foxx.sh" -t "unit_user_token") + add_test(NAME foxx_unit_user_model COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_foxx.sh" -t "unit_user_model") + add_test(NAME foxx_unit_globus_collection_model COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_foxx.sh" -t "unit_globus_collection_model") + add_test(NAME foxx_unit_globus_token_model COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_foxx.sh" -t "unit_globus_token_model") set_tests_properties(foxx_setup PROPERTIES FIXTURES_SETUP Foxx) set_tests_properties(foxx_teardown PROPERTIES FIXTURES_CLEANUP Foxx) + set_tests_properties(foxx_db_fixtures PROPERTIES FIXTURES_SETUP FoxxDBFixtures FIXTURES_REQUIRED Foxx) set_tests_properties(foxx_version PROPERTIES FIXTURES_REQUIRED Foxx) set_tests_properties(foxx_support PROPERTIES FIXTURES_REQUIRED Foxx) + set_tests_properties(foxx_authz PROPERTIES FIXTURES_REQUIRED Foxx) + set_tests_properties(foxx_authz_router PROPERTIES FIXTURES_REQUIRED Foxx) + set_tests_properties(foxx_record PROPERTIES FIXTURES_REQUIRED Foxx) + set_tests_properties(foxx_repo PROPERTIES FIXTURES_REQUIRED Foxx) + set_tests_properties(foxx_path PROPERTIES FIXTURES_REQUIRED Foxx) + set_tests_properties(foxx_user_router PROPERTIES FIXTURES_REQUIRED "Foxx;FoxxDBFixtures") + set_tests_properties(foxx_unit_user_token PROPERTIES FIXTURES_REQUIRED Foxx) + set_tests_properties(foxx_unit_user_model PROPERTIES FIXTURES_REQUIRED "Foxx;FoxxDBFixtures") + set_tests_properties(foxx_unit_globus_collection_model PROPERTIES FIXTURES_REQUIRED "Foxx;FoxxDBFixtures") + set_tests_properties(foxx_unit_globus_token_model PROPERTIES FIXTURES_REQUIRED "Foxx;FoxxDBFixtures") endif() diff --git a/core/database/README.md b/core/database/README.md new file mode 100644 index 000000000..3e2a5beec --- /dev/null +++ b/core/database/README.md @@ -0,0 +1,44 @@ +# WARNING - Adding Tests + +Note The granularity of CMake is dependent on how they are defined in the CMakeLists.txt file. The tests are specified in +CMake by passing a string that is matched against the chai test cases in the +"it()" sections of the chai unit tests. Any test cases that match the pattern will run when that test is triggered. + +i.e. + +CMakeLists.txt line + +``` +add_test(NAME foxx_record COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_foxx.sh" -t "unit_record") +``` + +This will pass "unit_record" as the pattern to be matched to the test_foxx.sh +script. In turn, the test_foxx.sh script will call foxx test with +"unit_record". Tests are not matched based on the name of the test file they +are matched based on the test cases. + +i.e. + +Below is part of a test case that would be matched against the "unit_record" pattern. + +``` + +describe('Record Class', () => { + it('unit_record: isPathConsistent should return false paths are inconsistent in new and old alloc.', () => { + : + : + }); + + + it('unit_record: isPathConsistent a different test case.', () => { + : + : + }); +}); +``` + +Notice that 'unit_record' is explicitly mentioned in the test cases. In the above exerpt, both tests will run. If ctest were to be explicitly called we could run all unit_record tests with the following. + +``` +ctest -R foxx_record +``` diff --git a/core/database/foxx/api/acl_router.js b/core/database/foxx/api/acl_router.js index 77aaef339..9f66b643c 100644 --- a/core/database/foxx/api/acl_router.js +++ b/core/database/foxx/api/acl_router.js @@ -1,30 +1,30 @@ -'use strict'; +"use strict"; -const createRouter = require('@arangodb/foxx/router'); +const createRouter = require("@arangodb/foxx/router"); const router = createRouter(); -const joi = require('joi'); -const g_db = require('@arangodb').db; -const g_lib = require('./support'); +const joi = require("joi"); +const g_db = require("@arangodb").db; +const g_lib = require("./support"); module.exports = router; - //==================== ACL API FUNCTIONS -router.get('/update', function(req, res) { +router + .get("/update", function (req, res) { try { var result = []; g_db._executeTransaction({ collections: { read: ["u", "p", "uuid", "accn", "d", "c", "a", "admin", "alias"], - write: ["c", "d", "acl"] + write: ["c", "d", "acl"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var object = g_lib.getObject(req.queryParams.id, client); var owner_id = g_db.owner.firstExample({ - _from: object._id + _from: object._id, })._to; //var owner = g_db._document( owner_id ); //owner_id = owner_id.substr(2); @@ -33,10 +33,8 @@ router.get('/update', function(req, res) { var is_coll; - if (object._id[0] == "c") - is_coll = true; - else - is_coll = false; + if (object._id[0] == "c") is_coll = true; + else is_coll = false; if (!is_coll && object._id[0] != "d") throw [g_lib.ERR_INVALID_PARAM, "Invalid object type, " + object._id]; @@ -53,9 +51,14 @@ router.get('/update', function(req, res) { if (!is_admin) { client_perm = g_lib.getPermissions(client, object, g_lib.PERM_ALL); - cur_rules = g_db._query("for v, e in 1..1 outbound @object acl return { id: v._id, gid: v.gid, grant: e.grant, inhgrant: e.inhgrant }", { - object: object._id - }).toArray(); + cur_rules = g_db + ._query( + "for v, e in 1..1 outbound @object acl return { id: v._id, gid: v.gid, grant: e.grant, inhgrant: e.inhgrant }", + { + object: object._id, + }, + ) + .toArray(); } var acl_mode = 0; @@ -64,7 +67,7 @@ router.get('/update', function(req, res) { if (req.queryParams.rules) { // Delete existing ACL rules for this object g_db.acl.removeByExample({ - _from: object._id + _from: object._id, }); var rule, obj, old_rule, chg; @@ -73,13 +76,16 @@ router.get('/update', function(req, res) { rule = req.queryParams.rules[i]; if (!is_coll && rule.inhgrant) - throw [g_lib.ERR_INVALID_PARAM, "Inherited permissions cannot be applied to data records"]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Inherited permissions cannot be applied to data records", + ]; if (rule.id.startsWith("g/")) { acl_mode |= 2; var group = g_db.g.firstExample({ uid: owner_id, - gid: rule.id.substr(2) + gid: rule.id.substr(2), }); if (!group) @@ -94,7 +100,7 @@ router.get('/update', function(req, res) { if (!is_admin) { // TODO I believe the code below is obsolete - granting sharing permission is (should be) unrestricted now - old_rule = cur_rules.findIndex(function(r) { + old_rule = cur_rules.findIndex(function (r) { return r.id == rule.id; }); @@ -103,26 +109,49 @@ router.get('/update', function(req, res) { if (old_rule.grant != rule.grant) { chg = old_rule.grant ^ rule.grant; if ((chg & client_perm) != (chg & ~g_lib.PERM_SHARE)) { - console.log("bad alter", rule.id, old_rule, rule, client_perm); - throw [g_lib.ERR_PERM_DENIED, "Attempt to alter protected permissions on " + rule.id + " ACL."]; + console.log( + "bad alter", + rule.id, + old_rule, + rule, + client_perm, + ); + throw [ + g_lib.ERR_PERM_DENIED, + "Attempt to alter protected permissions on " + + rule.id + + " ACL.", + ]; } } } else { - if ((rule.grant & g_lib.PERM_SHARE) || (rule.grant & client_perm) != rule.grant) { - console.log("exceeding", rule.id, old_rule.grant, rule.grant, client_perm); - throw [g_lib.ERR_PERM_DENIED, "Attempt to exceed controlled permissions on " + rule.id + " ACL."]; + if ( + rule.grant & g_lib.PERM_SHARE || + (rule.grant & client_perm) != rule.grant + ) { + console.log( + "exceeding", + rule.id, + old_rule.grant, + rule.grant, + client_perm, + ); + throw [ + g_lib.ERR_PERM_DENIED, + "Attempt to exceed controlled permissions on " + + rule.id + + " ACL.", + ]; } } } obj = { _from: object._id, - _to: rule.id + _to: rule.id, }; - if (rule.grant) - obj.grant = rule.grant; - if (rule.inhgrant) - obj.inhgrant = rule.inhgrant; + if (rule.grant) obj.grant = rule.grant; + if (rule.inhgrant) obj.inhgrant = rule.inhgrant; g_db.acl.save(obj); } @@ -131,14 +160,19 @@ router.get('/update', function(req, res) { new_obj.acls = acl_mode; g_db._update(object._id, new_obj, { - keepNull: false + keepNull: false, }); - result = g_db._query("for v, e in 1..1 outbound @object acl return { id: v._id, gid: v.gid, grant: e.grant, inhgrant: e.inhgrant }", { - object: object._id - }).toArray(); + result = g_db + ._query( + "for v, e in 1..1 outbound @object acl return { id: v._id, gid: v.gid, grant: e.grant, inhgrant: e.inhgrant }", + { + object: object._id, + }, + ) + .toArray(); postProcACLRules(result, object); - } + }, }); res.send(result); @@ -146,13 +180,20 @@ router.get('/update', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().required(), "ID or alias of data record or collection") - .queryParam('rules', joi.array().items(g_lib.acl_schema).optional(), "User and/or group ACL rules to create") - .summary('Update ACL(s) on a data record or collection') - .description('Update access control list(s) (ACLs) on a data record or collection. Inherited permissions can only be set on collections.'); - -router.get('/view', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().required(), "ID or alias of data record or collection") + .queryParam( + "rules", + joi.array().items(g_lib.acl_schema).optional(), + "User and/or group ACL rules to create", + ) + .summary("Update ACL(s) on a data record or collection") + .description( + "Update access control list(s) (ACLs) on a data record or collection. Inherited permissions can only be set on collections.", + ); + +router + .get("/view", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var object = g_lib.getObject(req.queryParams.id, client); @@ -165,9 +206,14 @@ router.get('/view', function(req, res) { throw g_lib.ERR_PERM_DENIED; } - var rules = g_db._query("for v, e in 1..1 outbound @object acl return { id: v._id, gid: v.gid, grant: e.grant, inhgrant: e.inhgrant }", { - object: object._id - }).toArray(); + var rules = g_db + ._query( + "for v, e in 1..1 outbound @object acl return { id: v._id, gid: v.gid, grant: e.grant, inhgrant: e.inhgrant }", + { + object: object._id, + }, + ) + .toArray(); postProcACLRules(rules, object); res.send(rules); @@ -175,34 +221,40 @@ router.get('/view', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().required(), "ID or alias of data record or collection") - .summary('View current ACL on an object') - .description('View current ACL on an object (data record or collection)'); - + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().required(), "ID or alias of data record or collection") + .summary("View current ACL on an object") + .description("View current ACL on an object (data record or collection)"); -router.get('/shared/list', function(req, res) { +router + .get("/shared/list", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); - res.send(g_lib.getACLOwnersBySubject(client._id, req.queryParams.inc_users, req.queryParams.inc_projects)); + res.send( + g_lib.getACLOwnersBySubject( + client._id, + req.queryParams.inc_users, + req.queryParams.inc_projects, + ), + ); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('inc_users', joi.boolean().optional(), "Include users") - .queryParam('inc_projects', joi.boolean().optional(), "Include projects") - .summary('List users/projects that have shared data or collections with client/subject.') - .description('List users/projects that have shared data or collections with client/subject.'); - - -router.get('/shared/list/items', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("inc_users", joi.boolean().optional(), "Include users") + .queryParam("inc_projects", joi.boolean().optional(), "Include projects") + .summary("List users/projects that have shared data or collections with client/subject.") + .description("List users/projects that have shared data or collections with client/subject."); + +router + .get("/shared/list/items", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var owner_id; - if (req.queryParams.owner.charAt(0) == 'p') { + if (req.queryParams.owner.charAt(0) == "p") { owner_id = req.queryParams.owner; // Verify project exists @@ -212,10 +264,17 @@ router.get('/shared/list/items', function(req, res) { owner_id = g_lib.getUserFromClientID(req.queryParams.owner)._id; } - var i, share, shares = g_db._query("for v in 1..2 inbound @client member, acl filter v.owner == @owner return {id:v._id,title:v.title,alias:v.alias,owner:v.owner,creator:v.creator,md_err:v.md_err,external:v.external,locked:v.locked}", { - client: client._id, - owner: owner_id - }).toArray(); + var i, + share, + shares = g_db + ._query( + "for v in 1..2 inbound @client member, acl filter v.owner == @owner return {id:v._id,title:v.title,alias:v.alias,owner:v.owner,creator:v.creator,md_err:v.md_err,external:v.external,locked:v.locked}", + { + client: client._id, + owner: owner_id, + }, + ) + .toArray(); for (i in shares) { share = shares[i]; @@ -227,16 +286,14 @@ router.get('/shared/list/items', function(req, res) { } else { res.send(dedupShares(client, shares)); } - } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('owner', joi.string().required(), "Owner ID") - .summary('Lists data and collections shared with client/subject by owner') - .description('Lists data and collections shared with client/subject by owner'); - + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("owner", joi.string().required(), "Owner ID") + .summary("Lists data and collections shared with client/subject by owner") + .description("Lists data and collections shared with client/subject by owner"); /* router.get('/by_user', function (req, res) { @@ -256,30 +313,33 @@ router.get('/by_user', function (req, res) { function dedupShares(client, shares) { var i, j, k, id; var items = {}, - item, parent; + item, + parent; for (i in shares) { id = shares[i].id; item = { paths: [], - data: shares[i] + data: shares[i], }; - parent = g_db.item.byExample({ - _to: item.data.id - }).toArray(); + parent = g_db.item + .byExample({ + _to: item.data.id, + }) + .toArray(); if (parent.length) { for (j in parent) { item.paths.push({ path: [id, parent[j]._from], par: null, - done: false + done: false, }); } } else { item.paths.push({ path: [id], par: null, - done: true + done: true, }); } items[id] = item; @@ -309,7 +369,7 @@ function dedupShares(client, shares) { } parent = g_db.item.firstExample({ - _to: id + _to: id, }); if (parent) { path.path.push(parent._from); @@ -365,8 +425,7 @@ function dedupShares(client, shares) { k = 0; break; } - if ((perm.grant & g_lib.PERM_LIST) == 0) - break; + if ((perm.grant & g_lib.PERM_LIST) == 0) break; } if (k == 0) { @@ -381,14 +440,11 @@ function dedupShares(client, shares) { } } - shares.sort(function(a, b) { + shares.sort(function (a, b) { if (a.id.charAt(0) != b.id.charAt(0)) { - if (a.id.charAt(0) == 'c') - return -1; - else - return 1; - } else - return a.title.localeCompare(b.title); + if (a.id.charAt(0) == "c") return -1; + else return 1; + } else return a.title.localeCompare(b.title); }); return shares; @@ -467,13 +523,10 @@ function postProcACLRules(rules, object) { if (rule.gid != null) { rule.id = "g/" + rule.gid; - } else - delete rule.gid; + } else delete rule.gid; - if (rule.grant == null) - delete rule.grant; + if (rule.grant == null) delete rule.grant; - if (rule.inhgrant == null) - delete rule.inhgrant; + if (rule.inhgrant == null) delete rule.inhgrant; } -} \ No newline at end of file +} diff --git a/core/database/foxx/api/admin_router.js b/core/database/foxx/api/admin_router.js index beef0a8f7..977a6ad70 100644 --- a/core/database/foxx/api/admin_router.js +++ b/core/database/foxx/api/admin_router.js @@ -1,29 +1,30 @@ -'use strict'; +"use strict"; -const createRouter = require('@arangodb/foxx/router'); +const createRouter = require("@arangodb/foxx/router"); const router = createRouter(); -const joi = require('joi'); +const joi = require("joi"); -const g_db = require('@arangodb').db; -const g_lib = require('./support'); +const g_db = require("@arangodb").db; +const g_lib = require("./support"); //const perf = require('@arangodb/foxx'); module.exports = router; -router.get('/ping', function(req, res) { +router + .get("/ping", function (req, res) { try { res.send({ - status: 1 + status: 1, }); } catch (e) { g_lib.handleException(e, res); } }) - .summary('Ping DB server') - .description('Ping DB server'); + .summary("Ping DB server") + .description("Ping DB server"); - -router.get('/test', function(req, res) { +router + .get("/test", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); //var perms = req.queryParams.perms?req.queryParams.perms:g_lib.PERM_ALL; @@ -41,30 +42,41 @@ router.get('/test', function(req, res) { res.send({ perm: result, - time: (t2 - t1) / 1000 + time: (t2 - t1) / 1000, }); } catch (e) { g_lib.handleException(e, res); } - }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('item', joi.string().required(), "Data/collection ID or alias") - .summary('Do perf test') - .description('Do perf test'); + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("item", joi.string().required(), "Data/collection ID or alias") + .summary("Do perf test") + .description("Do perf test"); - -router.get('/check', function(req, res) { +router + .get("/check", function (req, res) { try { var result = {}; g_db._executeTransaction({ collections: { read: ["u", "p"], - write: [] + write: [], }, - action: function() { - var edges = ["owner", "member", "item", "acl", "ident", "admin", "alias", "alloc", "loc", "top", "dep"]; + action: function () { + var edges = [ + "owner", + "member", + "item", + "acl", + "ident", + "admin", + "alias", + "alloc", + "loc", + "top", + "dep", + ]; var ecoll; var subres; var count = 0; @@ -72,9 +84,14 @@ router.get('/check', function(req, res) { // Check for dangling edges for (var e in edges) { ecoll = edges[e]; - subres = g_db._query("for i in @@coll let a = document(i._from)._id let b = document(i._to)._id filter a == null or b == null return {edge:i._id,fr:a,to:b}", { - "@coll": ecoll - }).toArray(); + subres = g_db + ._query( + "for i in @@coll let a = document(i._from)._id let b = document(i._to)._id filter a == null or b == null return {edge:i._id,fr:a,to:b}", + { + "@coll": ecoll, + }, + ) + .toArray(); count += subres.length; result[ecoll] = subres; } @@ -84,96 +101,184 @@ router.get('/check', function(req, res) { // Check for correct structure per vertex type count = 0; - subres = g_db._query("for i in d let x = (for v in 1..1 outbound i._id owner return v) filter length(x) == 0 return i._id").toArray(); + subres = g_db + ._query( + "for i in d let x = (for v in 1..1 outbound i._id owner return v) filter length(x) == 0 return i._id", + ) + .toArray(); count += subres.length; result.data_no_owner = subres; - subres = g_db._query("for i in d let x = (for v in 1..1 outbound i._id owner return v) filter length(x) > 1 return i._id").toArray(); + subres = g_db + ._query( + "for i in d let x = (for v in 1..1 outbound i._id owner return v) filter length(x) > 1 return i._id", + ) + .toArray(); count += subres.length; result.data_multi_owner = subres; - subres = g_db._query("for i in d filter i.external != true let x = (for v in 1..1 outbound i._id loc return v) filter length(x) == 0 return i._id").toArray(); + subres = g_db + ._query( + "for i in d filter i.external != true let x = (for v in 1..1 outbound i._id loc return v) filter length(x) == 0 return i._id", + ) + .toArray(); count += subres.length; result.data_no_loc = subres; - subres = g_db._query("for i in d let x = (for v in 1..1 outbound i._id loc return v) filter length(x) > 1 return i._id").toArray(); + subres = g_db + ._query( + "for i in d let x = (for v in 1..1 outbound i._id loc return v) filter length(x) > 1 return i._id", + ) + .toArray(); count += subres.length; result.data_multi_loc = subres; - subres = g_db._query("for i in d let x = (for v in 1..1 inbound i._id item return v) filter length(x) == 0 return i._id").toArray(); + subres = g_db + ._query( + "for i in d let x = (for v in 1..1 inbound i._id item return v) filter length(x) == 0 return i._id", + ) + .toArray(); count += subres.length; result.data_no_parent = subres; - subres = g_db._query("for i in c let x = (for v in 1..1 outbound i._id owner return v) filter length(x) == 0 return i._id").toArray(); + subres = g_db + ._query( + "for i in c let x = (for v in 1..1 outbound i._id owner return v) filter length(x) == 0 return i._id", + ) + .toArray(); count += subres.length; result.coll_no_owner = subres; - subres = g_db._query("for i in c let x = (for v in 1..1 outbound i._id owner return v) filter length(x) > 1 return i._id").toArray(); + subres = g_db + ._query( + "for i in c let x = (for v in 1..1 outbound i._id owner return v) filter length(x) > 1 return i._id", + ) + .toArray(); count += subres.length; result.coll_multi_owner = subres; - subres = g_db._query("for i in c let x = (for v in 1..1 inbound i._id item return v) filter i.is_root != true and length(x) == 0 return i._id").toArray(); + subres = g_db + ._query( + "for i in c let x = (for v in 1..1 inbound i._id item return v) filter i.is_root != true and length(x) == 0 return i._id", + ) + .toArray(); count += subres.length; result.coll_no_parent = subres; - subres = g_db._query("for i in c let x = (for v in 1..1 inbound i._id item return v) filter length(x) > 1 return i._id").toArray(); + subres = g_db + ._query( + "for i in c let x = (for v in 1..1 inbound i._id item return v) filter length(x) > 1 return i._id", + ) + .toArray(); count += subres.length; result.coll_multi_parent = subres; - subres = g_db._query("for i in g let x = (for v in 1..1 outbound i._id owner return v) filter length(x) == 0 return i._id").toArray(); + subres = g_db + ._query( + "for i in g let x = (for v in 1..1 outbound i._id owner return v) filter length(x) == 0 return i._id", + ) + .toArray(); count += subres.length; result.group_no_owner = subres; - subres = g_db._query("for i in g let x = (for v in 1..1 outbound i._id owner return v) filter length(x) > 1 return i._id").toArray(); + subres = g_db + ._query( + "for i in g let x = (for v in 1..1 outbound i._id owner return v) filter length(x) > 1 return i._id", + ) + .toArray(); count += subres.length; result.group_multi_owner = subres; - subres = g_db._query("for i in a let x = (for v in 1..1 outbound i._id owner return v) filter length(x) == 0 return i._id").toArray(); + subres = g_db + ._query( + "for i in a let x = (for v in 1..1 outbound i._id owner return v) filter length(x) == 0 return i._id", + ) + .toArray(); count += subres.length; result.alias_no_owner = subres; - subres = g_db._query("for i in a let x = (for v in 1..1 outbound i._id owner return v) filter length(x) > 1 return i._id").toArray(); + subres = g_db + ._query( + "for i in a let x = (for v in 1..1 outbound i._id owner return v) filter length(x) > 1 return i._id", + ) + .toArray(); count += subres.length; result.alias_multi_owner = subres; - subres = g_db._query("for i in a let x = (for v in 1..1 inbound i._id alias return v) filter length(x) == 0 return i._id").toArray(); + subres = g_db + ._query( + "for i in a let x = (for v in 1..1 inbound i._id alias return v) filter length(x) == 0 return i._id", + ) + .toArray(); count += subres.length; result.alias_no_alias = subres; - subres = g_db._query("for i in a let x = (for v in 1..1 inbound i._id alias return v) filter length(x) > 1 return i._id").toArray(); + subres = g_db + ._query( + "for i in a let x = (for v in 1..1 inbound i._id alias return v) filter length(x) > 1 return i._id", + ) + .toArray(); count += subres.length; result.alias_multi_alias = subres; - subres = g_db._query("for i in p let x = (for v in 1..1 outbound i._id owner return v) filter length(x) == 0 return i._id").toArray(); + subres = g_db + ._query( + "for i in p let x = (for v in 1..1 outbound i._id owner return v) filter length(x) == 0 return i._id", + ) + .toArray(); count += subres.length; result.proj_no_owner = subres; - subres = g_db._query("for i in p let x = (for v in 1..1 outbound i._id owner return v) filter length(x) > 1 return i._id").toArray(); + subres = g_db + ._query( + "for i in p let x = (for v in 1..1 outbound i._id owner return v) filter length(x) > 1 return i._id", + ) + .toArray(); count += subres.length; result.proj_multi_owner = subres; - subres = g_db._query("for i in q let x = (for v in 1..1 outbound i._id owner return v) filter length(x) == 0 return i._id").toArray(); + subres = g_db + ._query( + "for i in q let x = (for v in 1..1 outbound i._id owner return v) filter length(x) == 0 return i._id", + ) + .toArray(); count += subres.length; result.query_no_owner = subres; - subres = g_db._query("for i in q let x = (for v in 1..1 outbound i._id owner return v) filter length(x) > 1 return i._id").toArray(); + subres = g_db + ._query( + "for i in q let x = (for v in 1..1 outbound i._id owner return v) filter length(x) > 1 return i._id", + ) + .toArray(); count += subres.length; result.query_multi_owner = subres; - subres = g_db._query("for i in t let x = (for v in 1..1 outbound i._id top return v) filter i.top != true && length(x) == 0 return i._id").toArray(); + subres = g_db + ._query( + "for i in t let x = (for v in 1..1 outbound i._id top return v) filter i.top != true && length(x) == 0 return i._id", + ) + .toArray(); count += subres.length; result.topic_no_parent = subres; - subres = g_db._query("for i in t let x = (for v in 1..1 outbound i._id top return v) filter length(x) > 1 return i._id").toArray(); + subres = g_db + ._query( + "for i in t let x = (for v in 1..1 outbound i._id top return v) filter length(x) > 1 return i._id", + ) + .toArray(); count += subres.length; result.topic_multi_parent = subres; - subres = g_db._query("for i in repo let x = (for v in 1..1 outbound i._id admin return v) filter length(x) == 0 return i._id").toArray(); + subres = g_db + ._query( + "for i in repo let x = (for v in 1..1 outbound i._id admin return v) filter length(x) == 0 return i._id", + ) + .toArray(); count += subres.length; result.repo_no_admin = subres; result.vertex_bad_count = count; - } + }, }); res.send(result); @@ -181,6 +286,6 @@ router.get('/check', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('fix', joi.bool().optional(), "Automatically fix dangling edges.") - .summary('Database integrity check') - .description('Database integrity check.'); \ No newline at end of file + .queryParam("fix", joi.bool().optional(), "Automatically fix dangling edges.") + .summary("Database integrity check") + .description("Database integrity check."); diff --git a/core/database/foxx/api/authz.js b/core/database/foxx/api/authz.js new file mode 100644 index 000000000..94950d541 --- /dev/null +++ b/core/database/foxx/api/authz.js @@ -0,0 +1,191 @@ +"use strict"; + +const g_db = require("@arangodb").db; +const path = require("path"); +const Record = require("./record"); +const pathModule = require("./posix_path"); +const g_lib = require("./support"); +const { Repo, PathType } = require("./repo"); + +module.exports = (function () { + let obj = {}; + + /** + * Checks if a client has the required permissions on a record. + * + * @param {object} a_client - A user document representing the client being verified. + * @param {string} a_data_key - A DataFed key associated with a record (not prepended with 'd/'). + * The client object should have the following structure: + * + * "_key": "bob", + * "_id": "u/bob", + * "name": "bob junior", + * "name_first": "bob", + * "name_last": "jones", + * "is_admin": true, + * "max_coll": 50, + * "max_proj": 10, + * "max_sav_qry": 20, + * "email": "bobjones@gmail.com" + * + * @param {string} a_perm - The permission type to check (e.g., `PERM_CREATE`, `PERM_WR_DATA`, `PERM_RD_DATA`). + * + * @returns {boolean} True if the client has the required permissions, otherwise false. + */ + obj.isRecordActionAuthorized = function (a_client, a_data_key, a_perm) { + const data_id = "d/" + a_data_key; + // If the user is not an admin of the object we will need + // to check if the user has the write authorization + if (g_lib.hasAdminPermObject(a_client, data_id)) { + return true; + } + let data = g_db.d.document(data_id); + // Grab the data item + if (g_lib.hasPermissions(a_client, data, a_perm)) { + return true; + } + return false; + }; + + obj.readRecord = function (client, path) { + const permission = g_lib.PERM_RD_DATA; + const path_components = pathModule.splitPOSIXPath(path); + const data_key = path_components.at(-1); + let record = new Record(data_key); + if (!record.exists()) { + // Return not found error for non-existent records + console.log("AUTHZ act: read client: " + client._id + " path " + path + " NOT_FOUND"); + throw [g_lib.ERR_NOT_FOUND, "Record not found: " + path]; + } + + // Special case - allow unknown client to read a publicly accessible record + // if record exists and if it is a public record + if (!client) { + if (!g_lib.hasPublicRead(record.id())) { + console.log("AUTHZ act: read" + " unknown client " + " path " + path + " FAILED"); + throw [ + g_lib.ERR_PERM_DENIED, + "Unknown client does not have read permissions on " + path, + ]; + } + } else if (!obj.isRecordActionAuthorized(client, data_key, permission)) { + console.log("AUTHZ act: read" + " client: " + client._id + " path " + path + " FAILED"); + throw [ + g_lib.ERR_PERM_DENIED, + "Client " + client._id + " does not have read permissions on " + path, + ]; + } + + if (!record.isPathConsistent(path)) { + console.log("AUTHZ act: read client: " + client._id + " path " + path + " FAILED"); + throw [record.error(), record.errorMessage()]; + } + }; + + obj.none = function (client, path) { + const permission = g_lib.PERM_NONE; + }; + + obj.denied = function (client, path) { + throw g_lib.ERR_PERM_DENIED; + }; + + obj.createRecord = function (client, path) { + const permission = g_lib.PERM_WR_DATA; + const path_components = pathModule.splitPOSIXPath(path); + const data_key = path_components.at(-1); + + if (!client) { + console.log( + "AUTHZ act: create" + " client: " + client._id + " path " + path + " FAILED", + ); + throw [ + g_lib.ERR_PERM_DENIED, + "Unknown client does not have create permissions on " + path, + ]; + } else if (!obj.isRecordActionAuthorized(client, data_key, permission)) { + console.log( + "AUTHZ act: create" + " client: " + client._id + " path " + path + " FAILED", + ); + throw [ + g_lib.ERR_PERM_DENIED, + "Client " + client._id + " does not have create permissions on " + path, + ]; + } + + let record = new Record(data_key); + // This does not mean the record exsts in the repo it checks if an entry + // exists in the database. + if (!record.exists()) { + // If the record does not exist then the path would not be consistent. + console.log("AUTHZ act: create client: " + client._id + " path " + path + " FAILED"); + throw [g_lib.ERR_PERM_DENIED, "Invalid record specified: " + path]; + } + + // This will tell us if the proposed path is consistent with what we expect + // GridFTP will fail if the posix file path does not exist. + if (!record.isPathConsistent(path)) { + console.log("AUTHZ act: create client: " + client._id + " path " + path + " FAILED"); + throw [record.error(), record.errorMessage()]; + } + }; + + obj.authz_strategy = { + read: { + [PathType.USER_PATH]: obj.none, + [PathType.USER_RECORD_PATH]: obj.readRecord, + [PathType.PROJECT_PATH]: obj.none, + [PathType.PROJECT_RECORD_PATH]: obj.readRecord, + [PathType.REPO_BASE_PATH]: obj.none, + [PathType.REPO_ROOT_PATH]: obj.none, + [PathType.REPO_PATH]: obj.none, + }, + write: { + [PathType.USER_PATH]: obj.none, + [PathType.USER_RECORD_PATH]: obj.none, + [PathType.PROJECT_PATH]: obj.none, + [PathType.PROJECT_RECORD_PATH]: obj.none, + [PathType.REPO_BASE_PATH]: obj.none, + [PathType.REPO_ROOT_PATH]: obj.none, + [PathType.REPO_PATH]: obj.none, + }, + create: { + [PathType.USER_PATH]: obj.none, + [PathType.USER_RECORD_PATH]: obj.createRecord, + [PathType.PROJECT_PATH]: obj.none, + [PathType.PROJECT_RECORD_PATH]: obj.createRecord, + [PathType.REPO_BASE_PATH]: obj.none, + [PathType.REPO_ROOT_PATH]: obj.none, + [PathType.REPO_PATH]: obj.none, + }, + delete: { + [PathType.USER_PATH]: obj.denied, + [PathType.USER_RECORD_PATH]: obj.denied, + [PathType.PROJECT_PATH]: obj.denied, + [PathType.PROJECT_RECORD_PATH]: obj.denied, + [PathType.REPO_BASE_PATH]: obj.denied, + [PathType.REPO_ROOT_PATH]: obj.denied, + [PathType.REPO_PATH]: obj.denied, + }, + chdir: { + [PathType.USER_PATH]: obj.none, + [PathType.USER_RECORD_PATH]: obj.none, + [PathType.PROJECT_PATH]: obj.none, + [PathType.PROJECT_RECORD_PATH]: obj.none, + [PathType.REPO_BASE_PATH]: obj.none, + [PathType.REPO_ROOT_PATH]: obj.none, + [PathType.REPO_PATH]: obj.none, + }, + lookup: { + [PathType.USER_PATH]: obj.none, + [PathType.USER_RECORD_PATH]: obj.none, + [PathType.PROJECT_PATH]: obj.none, + [PathType.PROJECT_RECORD_PATH]: obj.none, + [PathType.REPO_BASE_PATH]: obj.none, + [PathType.REPO_ROOT_PATH]: obj.none, + [PathType.REPO_PATH]: obj.none, + }, + }; + + return obj; +})(); diff --git a/core/database/foxx/api/authz_router.js b/core/database/foxx/api/authz_router.js index 3988703e5..ff160e764 100644 --- a/core/database/foxx/api/authz_router.js +++ b/core/database/foxx/api/authz_router.js @@ -1,142 +1,121 @@ -'use strict'; +"use strict"; -const createRouter = require('@arangodb/foxx/router'); +const createRouter = require("@arangodb/foxx/router"); const router = createRouter(); -const joi = require('joi'); -const g_db = require('@arangodb').db; -const g_lib = require('./support'); +const joi = require("joi"); +const g_db = require("@arangodb").db; +const g_lib = require("./support"); +const authzModule = require("./authz"); +const { Repo, PathType } = require("./repo"); module.exports = router; - -router.get('/gridftp', function(req, res) { +router + .get("/gridftp", function (req, res) { try { - console.log("/gridftp start authz client", req.queryParams.client, "repo", req.queryParams.repo, "file", req.queryParams.file, "act", req.queryParams.act); - + console.log( + "/gridftp start authz client", + req.queryParams.client, + "repo", + req.queryParams.repo, + "file", + req.queryParams.file, + "act", + req.queryParams.act, + ); + + // Client will contain the following information + // + // "_key" : "bob", + // "_id" : "u/bob", + // "name" : "bob junior ", + // "name_first" : "bob", + // "name_last" : "jones", + // "is_admin" : true, + // "max_coll" : 50, + // "max_proj" : 10, + // "max_sav_qry" : 20, + // : + // "email" : "bobjones@gmail.com" const client = g_lib.getUserFromClientID_noexcept(req.queryParams.client); - - var idx = req.queryParams.file.lastIndexOf("/"); - var data_key = req.queryParams.file.substr(idx + 1); - var data_id = "d/" + data_key; - - // Special case - allow unknown client to read a publicly accessible record if (!client) { - if (req.queryParams.act != "read" || !g_lib.hasPublicRead(data_id)) { - console.log("Permission to read denied!"); - throw g_lib.ERR_PERM_DENIED; - } - console.log("allow anon read of public record"); - } else { - console.log("client:", client); - - // Actions: read, write, create, delete, chdir, lookup - var req_perm = 0; - switch (req.queryParams.act) { - case "read": - console.log("Client: ", client, " read permissions?"); - req_perm = g_lib.PERM_RD_DATA; - break; - case "write": - console.log("Client: ", client, " write permissions?"); - break; - case "create": - console.log("Client: ", client, " create permissions?"); - req_perm = g_lib.PERM_WR_DATA; - break; - case "delete": - console.log("Client: ", client, " delete permissions?"); - throw g_lib.ERR_PERM_DENIED; - case "chdir": - console.log("Client: ", client, " chdir permissions?"); - break; - case "lookup": - console.log("Client: ", client, " lookup permissions?"); - // For TESTING, allow these actions - return; - default: - throw [g_lib.ERR_INVALID_PARAM, "Invalid gridFTP action: ", req.queryParams.act]; - } - - console.log("client: ", client, " data_id: ", data_id); - if (!g_lib.hasAdminPermObject(client, data_id)) { - var data = g_db.d.document(data_id); - if (!g_lib.hasPermissions(client, data, req_perm)) { - console.log("Client: ", client, " does not have permission!"); - throw g_lib.ERR_PERM_DENIED; - } - } - } - - // Verify repo and path are correct for record - // Note: only managed records have an allocations and this gridftp auth call is only made for managed records - //var path = req.queryParams.file.substr( req.queryParams.file.indexOf("/",8)); - var path = req.queryParams.file; - console.log("data_id is, ", data_id); - var loc = g_db.loc.firstExample({ - _from: data_id - }); - console.log("Loc is:") - console.log(loc) - if (!loc) { - console.log("Permission denied data is not managed by DataFed. This can happen if you try to do a transfer directly from Globus.") - throw g_lib.ERR_PERM_DENIED; - } - var alloc = g_db.alloc.firstExample({ - _from: loc.uid, - _to: loc._to - }); - console.log("path:", path, " alloc path:", alloc.path + data_key, " loc: ", loc); - if (!alloc) { - throw g_lib.ERR_PERM_DENIED; + console.log( + "AUTHZ act: " + + req.queryParams.act + + " client: " + + +req.queryParams.client + + " path " + + req.queryParams.file + + " FAILED", + ); + throw [g_lib.ERR_PERM_DENIED, "Unknown client: " + req.queryParams.client]; } - - // If path is missing the starting "/" add it back in - if (!path.startsWith("/") && alloc.path.startsWith("/") ) { - path = "/" + path; + let repo = new Repo(req.queryParams.repo); + let path_type = repo.pathType(req.queryParams.file); + + // If the provided path is not within the repo throw an error + if (path_type === PathType.UNKNOWN) { + console.log( + "AUTHZ act: " + + req.queryParams.act + + " client: " + + client._id + + " path " + + req.queryParams.file + + " FAILED", + ); + throw [ + g_lib.ERR_PERM_DENIED, + "Unknown path, or path is not consistent with supported repository folder hierarchy: " + + req.queryParams.file, + ]; } - console.log("path:", path, " alloc path:", alloc.path + data_key, " loc: ", loc); - if (alloc.path + data_key != path) { - // This may be due to an alloc/owner change - // Allow If new path matches - console.log("authz loc info:", loc); - - if (!loc.new_repo) { - console.log("Throw a permission denied error"); - throw g_lib.ERR_PERM_DENIED; - } - - console.log("Creating alloc"); - alloc = g_db.alloc.firstExample({ - _from: loc.new_owner ? loc.new_owner : loc.uid, - _to: loc.new_repo - }); - - - console.log("alloc is "); - console.log(alloc); - if (!alloc || (alloc.path + data_key != path)) { - throw [obj.ERR_PERM_DENIED, "Permission denied, DataFed registered path is '" + alloc.path + data_key + "' Globus path is '" + path + "'"] - } + // Determine permissions associated with path provided + // Actions: read, write, create, delete, chdir, lookup + if (Object.keys(authzModule.authz_strategy).includes(req.queryParams.act)) { + authzModule.authz_strategy[req.queryParams.act][path_type]( + client, + req.queryParams.file, + ); + } else { + throw [g_lib.ERR_INVALID_PARAM, "Invalid gridFTP action: ", req.queryParams.act]; } - + console.log( + "AUTHZ act: " + + req.queryParams.act + + " client: " + + client._id + + " path " + + req.queryParams.file + + " SUCCESS", + ); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('repo', joi.string().required(), "Originating repo ID") - .queryParam('file', joi.string().required(), "Data file name") - .queryParam('act', joi.string().required(), "Action") - .summary('Checks authorization') - .description('Checks authorization'); - - -router.get('/perm/check', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam( + "repo", + joi.string().required(), + "Originating repo ID, where the DataFed managed GridFTP server is running.", + ) + .queryParam("file", joi.string().required(), "Data file name") + .queryParam( + "act", + joi.string().required(), + "GridFTP action: 'lookup', 'chdir', 'read', 'write', 'create', 'delete'", + ) + .summary("Checks authorization") + .description("Checks authorization"); + +router + .get("/perm/check", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var perms = req.queryParams.perms ? req.queryParams.perms : g_lib.PERM_ALL; - var obj, result = true, + var obj, + result = true, id = g_lib.resolveID(req.queryParams.id, client), ty = id[0]; @@ -146,34 +125,37 @@ router.get('/perm/check', function(req, res) { if (ty == "p") { var role = g_lib.getProjectRole(client._id, id); - if (role == g_lib.PROJ_NO_ROLE) { // Non members have only VIEW permissions - if (perms != g_lib.PERM_RD_REC) - result = false; - } else if (role == g_lib.PROJ_MEMBER) { // Non members have only VIEW permissions - if ((perms & ~g_lib.PERM_MEMBER) != 0) - result = false; - } else if (role == g_lib.PROJ_MANAGER) { // Managers have all but UPDATE - if ((perms & ~g_lib.PERM_MANAGER) != 0) - result = false; + if (role == g_lib.PROJ_NO_ROLE) { + // Non members have only VIEW permissions + if (perms != g_lib.PERM_RD_REC) result = false; + } else if (role == g_lib.PROJ_MEMBER) { + // Non members have only VIEW permissions + if ((perms & ~g_lib.PERM_MEMBER) != 0) result = false; + } else if (role == g_lib.PROJ_MANAGER) { + // Managers have all but UPDATE + if ((perms & ~g_lib.PERM_MANAGER) != 0) result = false; } } else if (ty == "d") { if (!g_lib.hasAdminPermObject(client, id)) { obj = g_db.d.document(id); - if (obj.locked) - result = false; - else - result = g_lib.hasPermissions(client, obj, perms); + if (obj.locked) result = false; + else result = g_lib.hasPermissions(client, obj, perms); } } else if (ty == "c") { // If create perm is requested, ensure owner of collection has at least one allocation if (perms & g_lib.PERM_CREATE) { var owner = g_db.owner.firstExample({ - _from: id + _from: id, }); - if (!g_db.alloc.firstExample({ - _from: owner._to - })) { - throw [g_lib.ERR_NO_ALLOCATION, "An allocation is required to create a collection."]; + if ( + !g_db.alloc.firstExample({ + _from: owner._to, + }) + ) { + throw [ + g_lib.ERR_NO_ALLOCATION, + "An allocation is required to create a collection.", + ]; } } @@ -186,62 +168,64 @@ router.get('/perm/check', function(req, res) { } res.send({ - granted: result + granted: result, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().required(), "Object ID or alias") - .queryParam('perms', joi.number().required(), "Permission bit mask to check") - .summary('Checks client permissions for object') - .description('Checks client permissions for object (projects, data, collections'); - -router.get('/perm/get', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().required(), "Object ID or alias") + .queryParam("perms", joi.number().required(), "Permission bit mask to check") + .summary("Checks client permissions for object") + .description("Checks client permissions for object (projects, data, collections"); + +router + .get("/perm/get", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var result = req.queryParams.perms ? req.queryParams.perms : g_lib.PERM_ALL; - var obj, id = g_lib.resolveID(req.queryParams.id, client), + var obj, + id = g_lib.resolveID(req.queryParams.id, client), ty = id[0]; - if (id[1] != "/") - throw [g_lib.ERR_INVALID_PARAM, "Invalid ID, " + req.queryParams.id]; + if (id[1] != "/") throw [g_lib.ERR_INVALID_PARAM, "Invalid ID, " + req.queryParams.id]; if (ty == "p") { var role = g_lib.getProjectRole(client._id, id); - if (role == g_lib.PROJ_NO_ROLE) { // Non members have only VIEW permissions + if (role == g_lib.PROJ_NO_ROLE) { + // Non members have only VIEW permissions result &= g_lib.PERM_RD_REC; } else if (role == g_lib.PROJ_MEMBER) { result &= g_lib.PERM_MEMBER; - } else if (role == g_lib.PROJ_MANAGER) { // Managers have all but UPDATE + } else if (role == g_lib.PROJ_MANAGER) { + // Managers have all but UPDATE result &= g_lib.PERM_MANAGER; } } else if (ty == "d") { if (!g_lib.hasAdminPermObject(client, id)) { obj = g_db.d.document(id); - if (obj.locked) - result = 0; - else - result = g_lib.getPermissions(client, obj, result); + if (obj.locked) result = 0; + else result = g_lib.getPermissions(client, obj, result); } } else if (ty == "c") { if (!g_lib.hasAdminPermObject(client, id)) { obj = g_db.c.document(id); result = g_lib.getPermissions(client, obj, result); } - } else - throw [g_lib.ERR_INVALID_PARAM, "Invalid ID, " + req.queryParams.id]; + } else throw [g_lib.ERR_INVALID_PARAM, "Invalid ID, " + req.queryParams.id]; res.send({ - granted: result + granted: result, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().required(), "Object ID or alias") - .queryParam('perms', joi.number().optional(), "Permission bit mask to get (default = all)") - .summary('Gets client permissions for object') - .description('Gets client permissions for object (projects, data, collections. Note this is potentially slower than using "check" method.'); + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().required(), "Object ID or alias") + .queryParam("perms", joi.number().optional(), "Permission bit mask to get (default = all)") + .summary("Gets client permissions for object") + .description( + 'Gets client permissions for object (projects, data, collections. Note this is potentially slower than using "check" method.', + ); diff --git a/core/database/foxx/api/coll_router.js b/core/database/foxx/api/coll_router.js index 9743be425..98383210f 100644 --- a/core/database/foxx/api/coll_router.js +++ b/core/database/foxx/api/coll_router.js @@ -1,32 +1,31 @@ -'use strict'; +"use strict"; -const createRouter = require('@arangodb/foxx/router'); +const createRouter = require("@arangodb/foxx/router"); const router = createRouter(); -const joi = require('joi'); +const joi = require("joi"); -const g_db = require('@arangodb').db; -const g_graph = require('@arangodb/general-graph')._graph('sdmsg'); -const g_lib = require('./support'); +const g_db = require("@arangodb").db; +const g_graph = require("@arangodb/general-graph")._graph("sdmsg"); +const g_lib = require("./support"); module.exports = router; - //===== COLLECTION API FUNCTIONS ===== -router.post('/create', function(req, res) { +router + .post("/create", function (req, res) { var retry = 10; for (;;) { - try { var result = []; g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn", "alloc"], - write: ["c", "a", "alias", "owner", "item", "t", "top", "tag"] + write: ["c", "a", "alias", "owner", "item", "t", "top", "tag"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var owner = client, parent_id; @@ -35,13 +34,19 @@ router.post('/create', function(req, res) { parent_id = g_lib.resolveCollID(req.body.parent, client); var owner_id = g_db.owner.firstExample({ - _from: parent_id + _from: parent_id, })._to; if (owner_id != client._id) { if (!g_lib.hasManagerPermProj(client, owner_id)) { var parent_coll = g_db.c.document(parent_id); - if (!g_lib.hasPermissions(client, parent_coll, g_lib.PERM_CREATE)) + if ( + !g_lib.hasPermissions( + client, + parent_coll, + g_lib.PERM_CREATE, + ) + ) throw g_lib.ERR_PERM_DENIED; } owner = g_db._document(owner_id); @@ -51,19 +56,34 @@ router.post('/create', function(req, res) { } // Ensure owner of collection has at least one allocation - if (!g_db.alloc.firstExample({ - _from: owner_id - })) { - throw [g_lib.ERR_NO_ALLOCATION, "An allocation is required to create a collection."]; + if ( + !g_db.alloc.firstExample({ + _from: owner_id, + }) + ) { + throw [ + g_lib.ERR_NO_ALLOCATION, + "An allocation is required to create a collection.", + ]; } // Enforce collection limit if set if (owner.max_coll >= 0) { - var count = g_db._query("return length(FOR i IN owner FILTER i._to == @id and is_same_collection('c',i._from) RETURN 1)", { - id: owner_id - }).next(); + var count = g_db + ._query( + "return length(FOR i IN owner FILTER i._to == @id and is_same_collection('c',i._from) RETURN 1)", + { + id: owner_id, + }, + ) + .next(); if (count >= owner.max_coll) - throw [g_lib.ERR_ALLOCATION_EXCEEDED, "Collection limit reached (" + owner.max_coll + "). Contact system administrator to increase limit."]; + throw [ + g_lib.ERR_ALLOCATION_EXCEEDED, + "Collection limit reached (" + + owner.max_coll + + "). Contact system administrator to increase limit.", + ]; } var time = Math.floor(Date.now() / 1000); @@ -71,7 +91,7 @@ router.post('/create', function(req, res) { owner: owner._id, creator: client._id, ct: time, - ut: time + ut: time, }; g_lib.procInputParam(req.body, "title", false, obj); @@ -84,11 +104,11 @@ router.post('/create', function(req, res) { obj.public = true; obj.cat_tags = []; - var tag, tags = req.body.topic.split("."); + var tag, + tags = req.body.topic.split("."); for (var i in tags) { tag = tags[i]; - if (tag) - obj.cat_tags.push(tag); + if (tag) obj.cat_tags.push(tag); } //g_lib.addTags( obj.cat_tags ); @@ -100,33 +120,34 @@ router.post('/create', function(req, res) { } var coll = g_db.c.save(obj, { - returnNew: true + returnNew: true, }); g_db.owner.save({ _from: coll._id, - _to: owner._id + _to: owner._id, }); g_lib.makeTitleUnique(parent_id, coll.new); g_graph.item.save({ _from: parent_id, - _to: coll._id + _to: coll._id, }); if (obj.alias) { - var alias_key = owner._id[0] + ":" + owner._id.substr(2) + ":" + obj.alias; + var alias_key = + owner._id[0] + ":" + owner._id.substr(2) + ":" + obj.alias; g_db.a.save({ - _key: alias_key + _key: alias_key, }); g_db.alias.save({ _from: coll._id, - _to: "a/" + alias_key + _to: "a/" + alias_key, }); g_db.owner.save({ _from: "a/" + alias_key, - _to: owner._id + _to: owner._id, }); } @@ -142,11 +163,11 @@ router.post('/create', function(req, res) { delete coll._rev; result.push(coll); - } + }, }); res.send({ - results: result + results: result, }); break; } catch (e) { @@ -154,38 +175,42 @@ router.post('/create', function(req, res) { g_lib.handleException(e, res); } } - } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.object({ - title: joi.string().allow('').optional(), - desc: joi.string().allow('').optional(), - alias: joi.string().allow('').optional(), - topic: joi.string().allow('').optional(), - parent: joi.string().allow('').optional(), - tags: joi.array().items(joi.string()).optional() - }).required(), 'Collection fields') - .summary('Create a new data collection') - .description('Create a new data collection from JSON body'); - -router.post('/update', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .object({ + title: joi.string().allow("").optional(), + desc: joi.string().allow("").optional(), + alias: joi.string().allow("").optional(), + topic: joi.string().allow("").optional(), + parent: joi.string().allow("").optional(), + tags: joi.array().items(joi.string()).optional(), + }) + .required(), + "Collection fields", + ) + .summary("Create a new data collection") + .description("Create a new data collection from JSON body"); + +router + .post("/update", function (req, res) { var retry = 10; for (;;) { - try { var result = { results: [], - updates: [] + updates: [], }; g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn"], - write: ["c", "a", "d", "owner", "alias", "t", "top", "tag"] + write: ["c", "a", "d", "owner", "alias", "t", "top", "tag"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var coll_id = g_lib.resolveCollID(req.body.id, client); var coll = g_db.c.document(coll_id); @@ -194,9 +219,11 @@ router.post('/update', function(req, res) { var time = Math.floor(Date.now() / 1000), obj = { - ut: time + ut: time, }, - i, tags, tag; //, idx; + i, + tags, + tag; //, idx; g_lib.procInputParam(req.body, "title", true, obj); g_lib.procInputParam(req.body, "desc", true, obj); @@ -208,11 +235,14 @@ router.post('/update', function(req, res) { if (!g_lib.hasAdminPermObject(client, coll_id)) { var perms = 0; - if (obj.title !== undefined || obj.alias !== undefined || obj.desc !== undefined) + if ( + obj.title !== undefined || + obj.alias !== undefined || + obj.desc !== undefined + ) perms |= g_lib.PERM_WR_REC; - if (obj.topic !== undefined) - perms |= g_lib.PERM_SHARE; + if (obj.topic !== undefined) perms |= g_lib.PERM_SHARE; if (!g_lib.hasPermissions(client, coll, perms)) throw g_lib.ERR_PERM_DENIED; @@ -306,7 +336,7 @@ router.post('/update', function(req, res) { coll = g_db._update(coll_id, obj, { keepNull: false, - returnNew: true + returnNew: true, }); coll = coll.new; @@ -317,29 +347,30 @@ router.post('/update', function(req, res) { if (obj.alias !== undefined) { var old_alias = g_db.alias.firstExample({ - _from: coll_id + _from: coll_id, }); if (old_alias) { - const graph = require('@arangodb/general-graph')._graph('sdmsg'); + const graph = require("@arangodb/general-graph")._graph("sdmsg"); graph.a.remove(old_alias._to); } if (obj.alias) { var owner_id = g_db.owner.firstExample({ - _from: coll_id + _from: coll_id, })._to; - var alias_key = owner_id[0] + ":" + owner_id.substr(2) + ":" + obj.alias; + var alias_key = + owner_id[0] + ":" + owner_id.substr(2) + ":" + obj.alias; g_db.a.save({ - _key: alias_key + _key: alias_key, }); g_db.alias.save({ _from: coll_id, - _to: "a/" + alias_key + _to: "a/" + alias_key, }); g_db.owner.save({ _from: "a/" + alias_key, - _to: owner_id + _to: owner_id, }); } } @@ -351,7 +382,7 @@ router.post('/update', function(req, res) { result.results.push(coll); result.updates.push(coll); - } + }, }); res.send(result); @@ -361,24 +392,28 @@ router.post('/update', function(req, res) { g_lib.handleException(e, res); } } - } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.object({ - id: joi.string().required(), - title: joi.string().allow('').optional(), - desc: joi.string().allow('').optional(), - alias: joi.string().allow('').optional(), - topic: joi.string().allow('').optional(), - tags: joi.array().items(joi.string()).optional(), - tags_clear: joi.boolean().optional() - }).required(), 'Collection fields') - .summary('Update an existing collection') - .description('Update an existing collection from JSON body'); - - -router.get('/view', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .object({ + id: joi.string().required(), + title: joi.string().allow("").optional(), + desc: joi.string().allow("").optional(), + alias: joi.string().allow("").optional(), + topic: joi.string().allow("").optional(), + tags: joi.array().items(joi.string()).optional(), + tags_clear: joi.boolean().optional(), + }) + .required(), + "Collection fields", + ) + .summary("Update an existing collection") + .description("Update an existing collection from JSON body"); + +router + .get("/view", function (req, res) { try { const client = g_lib.getUserFromClientID_noexcept(req.queryParams.client); @@ -407,19 +442,19 @@ router.get('/view', function(req, res) { delete coll._rev; res.send({ - results: [coll] + results: [coll], }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().required(), "Collection ID or alias") - .summary('View collection information by ID or alias') - .description('View collection information by ID or alias'); - + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().required(), "Collection ID or alias") + .summary("View collection information by ID or alias") + .description("View collection information by ID or alias"); -router.get('/read', function(req, res) { +router + .get("/read", function (req, res) { try { const client = g_lib.getUserFromClientID_noexcept(req.queryParams.client); @@ -438,29 +473,38 @@ router.get('/read', function(req, res) { throw g_lib.ERR_PERM_DENIED; } - var qry = "for v in 1..1 outbound @coll item sort is_same_collection('c',v) DESC, v.title", - result, params = { - coll: coll_id + var qry = + "for v in 1..1 outbound @coll item sort is_same_collection('c',v) DESC, v.title", + result, + params = { + coll: coll_id, }, item; if (req.queryParams.offset != undefined && req.queryParams.count != undefined) { qry += " limit " + req.queryParams.offset + ", " + req.queryParams.count; - qry += " return { id: v._id, title: v.title, alias: v.alias, owner: v.owner, creator: v.creator, size: v.size, external: v.external, md_err: v.md_err, locked: v.locked }"; - result = g_db._query(qry, params, {}, { - fullCount: true - }); + qry += + " return { id: v._id, title: v.title, alias: v.alias, owner: v.owner, creator: v.creator, size: v.size, external: v.external, md_err: v.md_err, locked: v.locked }"; + result = g_db._query( + qry, + params, + {}, + { + fullCount: true, + }, + ); var tot = result.getExtra().stats.fullCount; result = result.toArray(); result.push({ paging: { off: req.queryParams.offset, cnt: req.queryParams.count, - tot: tot - } + tot: tot, + }, }); } else { - qry += " return { id: v._id, title: v.title, alias: v.alias, owner: v.owner, creator: v.creator, size: v.size, external: v.external, md_err: v.md_err, locked: v.locked }"; + qry += + " return { id: v._id, title: v.title, alias: v.alias, owner: v.owner, creator: v.creator, size: v.size, external: v.external, md_err: v.md_err, locked: v.locked }"; result = g_db._query(qry, params).toArray(); } @@ -476,32 +520,35 @@ router.get('/read', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().required(), "Collection ID or alias to list") - .queryParam('offset', joi.number().integer().min(0).optional(), "Offset") - .queryParam('count', joi.number().integer().min(1).optional(), "Count") - .summary('Read contents of a collection by ID or alias') - .description('Read contents of a collection by ID or alias'); - - -router.get('/write', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().required(), "Collection ID or alias to list") + .queryParam("offset", joi.number().integer().min(0).optional(), "Offset") + .queryParam("count", joi.number().integer().min(1).optional(), "Count") + .summary("Read contents of a collection by ID or alias") + .description("Read contents of a collection by ID or alias"); + +router + .get("/write", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "c", "uuid", "accn"], - write: ["item", "d"] + write: ["item", "d"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); if (req.queryParams.add && req.queryParams.remove) { - throw [g_lib.ERR_INVALID_PARAM, "Cannot add and remove collection items at the same time."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Cannot add and remove collection items at the same time.", + ]; } var coll_id = g_lib.resolveCollID(req.queryParams.id, client); var coll = g_db.c.document(coll_id); var owner_id = g_db.owner.firstExample({ - _from: coll_id + _from: coll_id, })._to; var chk_perm = false; @@ -510,13 +557,19 @@ router.get('/write', function(req, res) { //if ( req.queryParams.remove && req.queryParams.remove.length ) // req_perm |= g_lib.PERM_SHARE; if (!g_lib.hasPermissions(client, coll, req_perm, true)) - throw [g_lib.ERR_PERM_DENIED, "Permission denied - requires LINK on collection."]; + throw [ + g_lib.ERR_PERM_DENIED, + "Permission denied - requires LINK on collection.", + ]; chk_perm = true; } - var i, obj, cres, - loose, have_loose = false, + var i, + obj, + cres, + loose, + have_loose = false, visited = {}, coll_ctx = g_lib.catalogCalcParCtxt(coll, visited); @@ -535,31 +588,41 @@ router.get('/write', function(req, res) { for (i in req.queryParams.remove) { obj = g_lib.getObject(req.queryParams.remove[i], client); - if (!g_db.item.firstExample({ + if ( + !g_db.item.firstExample({ _from: coll_id, - _to: obj._id - })) - throw [g_lib.ERR_UNLINK, obj._id + " is not in collection " + coll_id]; + _to: obj._id, + }) + ) + throw [ + g_lib.ERR_UNLINK, + obj._id + " is not in collection " + coll_id, + ]; if (chk_perm && obj.creator != client._id) { // Check if another instance exists in same scope, if not deny permission if (!g_lib.hasAnyCommonAccessScope(obj._id, coll_id)) { - throw [g_lib.ERR_PERM_DENIED, "Cannot unlink items owned by other users."]; + throw [ + g_lib.ERR_PERM_DENIED, + "Cannot unlink items owned by other users.", + ]; } } g_db.item.removeByExample({ _from: coll_id, - _to: obj._id + _to: obj._id, }); - if (!g_db.item.firstExample({ - _to: obj._id - })) { + if ( + !g_db.item.firstExample({ + _to: obj._id, + }) + ) { loose[obj._id] = obj; have_loose = true; } else if (coll_ctx.pub) { - if (obj._id.charAt(0) == 'c') { + if (obj._id.charAt(0) == "c") { // Must update all records in this collection g_lib.catalogUpdateColl(obj, null, visited); } else { @@ -573,54 +636,73 @@ router.get('/write', function(req, res) { if (req.queryParams.add) { // Limit number of items in collection cres = g_db._query("for v in 1..1 outbound @coll item return v._id", { - coll: coll_id + coll: coll_id, }); //console.log("coll item count:",cres.count()); if (cres.count() + req.queryParams.add.length > g_lib.MAX_COLL_ITEMS) - throw [g_lib.ERR_INPUT_TOO_LONG, "Collection item limit exceeded (" + g_lib.MAX_COLL_ITEMS + " items)"]; + throw [ + g_lib.ERR_INPUT_TOO_LONG, + "Collection item limit exceeded (" + + g_lib.MAX_COLL_ITEMS + + " items)", + ]; cres.dispose(); for (i in req.queryParams.add) { - obj = g_lib.getObject(req.queryParams.add[i], client); // Check if item is already in this collection - if (g_db.item.firstExample({ + if ( + g_db.item.firstExample({ _from: coll_id, - _to: obj._id - })) + _to: obj._id, + }) + ) throw [g_lib.ERR_LINK, obj._id + " already linked to " + coll_id]; // Check if item is a root collection - if (obj.is_root) - throw [g_lib.ERR_LINK, "Cannot link root collection"]; + if (obj.is_root) throw [g_lib.ERR_LINK, "Cannot link root collection"]; // Check if item has same owner as this collection - if (g_db.owner.firstExample({ - _from: obj._id - })._to != owner_id) - throw [g_lib.ERR_LINK, obj._id + " and " + coll_id + " have different owners"]; + if ( + g_db.owner.firstExample({ + _from: obj._id, + })._to != owner_id + ) + throw [ + g_lib.ERR_LINK, + obj._id + " and " + coll_id + " have different owners", + ]; if (chk_perm && obj.creator != client._id) { // TODO check if another instance exists in same scope, if not deny if (!g_lib.hasAnyCommonAccessScope(obj._id, coll_id)) { - throw [g_lib.ERR_PERM_DENIED, "Cannot link items from other access-control scopes."]; + throw [ + g_lib.ERR_PERM_DENIED, + "Cannot link items from other access-control scopes.", + ]; } } if (obj._id.charAt(0) == "c") { // Check for circular dependency if (obj._id == coll_id || g_lib.isSrcParentOfDest(obj._id, coll_id)) - throw [g_lib.ERR_LINK, "Cannot link ancestor, " + obj._id + ", to descendant, " + coll_id]; + throw [ + g_lib.ERR_LINK, + "Cannot link ancestor, " + + obj._id + + ", to descendant, " + + coll_id, + ]; // Collections can only be linked to one parent g_db.item.removeByExample({ - _to: obj._id + _to: obj._id, }); g_db.item.save({ _from: coll_id, - _to: obj._id + _to: obj._id, }); if (coll_ctx.pub) { @@ -632,7 +714,7 @@ router.get('/write', function(req, res) { } else { g_db.item.save({ _from: coll_id, - _to: obj._id + _to: obj._id, }); if (coll_ctx.pub) { @@ -652,18 +734,26 @@ router.get('/write', function(req, res) { loose_res = []; cres = g_db._query("for v in 1..1 outbound @coll item return v._id", { - coll: root_id + coll: root_id, }); - if (cres.count() + (req.queryParams.add ? req.queryParams.add.length : 0) > g_lib.MAX_COLL_ITEMS) - throw [g_lib.ERR_INPUT_TOO_LONG, "Root collection item limit exceeded (" + g_lib.MAX_COLL_ITEMS + " items)"]; + if ( + cres.count() + (req.queryParams.add ? req.queryParams.add.length : 0) > + g_lib.MAX_COLL_ITEMS + ) + throw [ + g_lib.ERR_INPUT_TOO_LONG, + "Root collection item limit exceeded (" + + g_lib.MAX_COLL_ITEMS + + " items)", + ]; cres.dispose(); if (coll_ctx.pub) { rctxt = { pub: false, - tag: new Set() + tag: new Set(), }; } @@ -671,26 +761,30 @@ router.get('/write', function(req, res) { obj = loose[i]; g_db.item.save({ _from: root_id, - _to: obj._id + _to: obj._id, }); loose_res.push({ id: obj._id, - title: obj.title + title: obj.title, }); if (coll_ctx.pub) { - if (obj._id.charAt(0) == 'c') { + if (obj._id.charAt(0) == "c") { // Must update all records in this collection g_lib.catalogUpdateColl(obj, rctxt, visited); } else { // Update this record - g_db._update(obj._id, { - public: false, - cat_tags: null - }, { - keepNull: false - }); + g_db._update( + obj._id, + { + public: false, + cat_tags: null, + }, + { + keepNull: false, + }, + ); } } @@ -699,27 +793,28 @@ router.get('/write', function(req, res) { } else { res.send([]); } - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().required(), "Collection ID or alias to modify") - .queryParam('add', joi.array().items(joi.string()).optional(), "Array of item IDs to add") - .queryParam('remove', joi.array().items(joi.string()).optional(), "Array of item IDs to remove") - .summary('Add/remove items in a collection') - .description('Add/remove items in a collection'); - -router.get('/move', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().required(), "Collection ID or alias to modify") + .queryParam("add", joi.array().items(joi.string()).optional(), "Array of item IDs to add") + .queryParam("remove", joi.array().items(joi.string()).optional(), "Array of item IDs to remove") + .summary("Add/remove items in a collection") + .description("Add/remove items in a collection"); + +router + .get("/move", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "c", "uuid", "accn"], - write: ["item", "d"] + write: ["item", "d"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var src_id = g_lib.resolveCollID(req.queryParams.source, client), src = g_db.c.document(src_id), @@ -731,7 +826,13 @@ router.get('/move', function(req, res) { is_pub = src_ctx.pub | dst_ctx.pub; if (src.owner != dst.owner) - throw [g_lib.ERR_LINK, req.queryParams.source + " and " + req.queryParams.dest + " have different owners"]; + throw [ + g_lib.ERR_LINK, + req.queryParams.source + + " and " + + req.queryParams.dest + + " have different owners", + ]; var chk_perm = false, src_perms = 0, @@ -740,15 +841,26 @@ router.get('/move', function(req, res) { if (!g_lib.hasAdminPermObject(client, src_id)) { src_perms = g_lib.getPermissions(client, src, g_lib.PERM_LINK, true); if ((src_perms & g_lib.PERM_LINK) == 0) - throw [g_lib.ERR_PERM_DENIED, "Permission denied - requires LINK on source collection."]; + throw [ + g_lib.ERR_PERM_DENIED, + "Permission denied - requires LINK on source collection.", + ]; chk_perm = true; } if (!g_lib.hasAdminPermObject(client, dst_id)) { - dst_perms = g_lib.getPermissions(client, dst, g_lib.PERM_LINK /*| g_lib.PERM_SHARE*/ , true); + dst_perms = g_lib.getPermissions( + client, + dst, + g_lib.PERM_LINK /*| g_lib.PERM_SHARE*/, + true, + ); if ((dst_perms & g_lib.PERM_LINK) == 0) - throw [g_lib.ERR_PERM_DENIED, "Permission denied - requires LINK on destination collection."]; + throw [ + g_lib.ERR_PERM_DENIED, + "Permission denied - requires LINK on destination collection.", + ]; chk_perm = true; } @@ -759,45 +871,60 @@ router.get('/move', function(req, res) { // TODO - should aliases be resolved with client or owner ID? item = g_lib.getObject(req.queryParams.items[i], client); - if (item.is_root) - throw [g_lib.ERR_LINK, "Cannot link root collection"]; + if (item.is_root) throw [g_lib.ERR_LINK, "Cannot link root collection"]; - if (chk_perm && item.creator != client._id /*&& !has_share*/ ) { + if (chk_perm && item.creator != client._id /*&& !has_share*/) { if (!g_lib.hasCommonAccessScope(src_id, dst_id)) { - throw [g_lib.ERR_PERM_DENIED, "Cannot move items across access-control scopes."]; + throw [ + g_lib.ERR_PERM_DENIED, + "Cannot move items across access-control scopes.", + ]; } } - if (!g_db.item.firstExample({ + if ( + !g_db.item.firstExample({ _from: src_id, - _to: item._id - })) + _to: item._id, + }) + ) throw [g_lib.ERR_UNLINK, item._id + " is not in collection " + src_id]; - if (g_db.item.firstExample({ + if ( + g_db.item.firstExample({ _from: dst_id, - _to: item._id - })) - throw [g_lib.ERR_LINK, item._id + " is already in collection " + dst_id]; + _to: item._id, + }) + ) + throw [ + g_lib.ERR_LINK, + item._id + " is already in collection " + dst_id, + ]; if (item._id[0] == "c") { // Check for circular dependency if (item._id == dst_id || g_lib.isSrcParentOfDest(item._id, dst_id)) - throw [g_lib.ERR_LINK, "Cannot link ancestor, " + item._id + ", to descendant, " + dst_id]; + throw [ + g_lib.ERR_LINK, + "Cannot link ancestor, " + + item._id + + ", to descendant, " + + dst_id, + ]; } g_db.item.removeByExample({ _from: src_id, - _to: item._id + _to: item._id, }); g_db.item.save({ _from: dst_id, - _to: item._id + _to: item._id, }); // Update public flag & cat tags for published items if (is_pub) { - if (item._id.charAt(0) == 'c') { + if (item._id.charAt(0) == "c") { // Must update all records in this collection g_lib.catalogUpdateColl(item, dst_ctx, visited); } else { @@ -808,29 +935,33 @@ router.get('/move', function(req, res) { } var cres = g_db._query("for v in 1..1 outbound @coll item return v._id", { - coll: dst_id + coll: dst_id, }); if (cres.count() > g_lib.MAX_COLL_ITEMS) - throw [g_lib.ERR_INPUT_TOO_LONG, "Collection item limit exceeded (" + g_lib.MAX_COLL_ITEMS + " items)"]; + throw [ + g_lib.ERR_INPUT_TOO_LONG, + "Collection item limit exceeded (" + g_lib.MAX_COLL_ITEMS + " items)", + ]; cres.dispose(); res.send({}); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('items', joi.array().items(joi.string()).optional(), "Items IDs/aliases to move") - .queryParam('source', joi.string().required(), "Source collection ID/alias") - .queryParam('dest', joi.string().required(), "Destination collection ID/alias") - .summary('Move items from source collection to destination collection') - .description('Move items from source collection to destination collection'); - -router.get('/get_parents', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("items", joi.array().items(joi.string()).optional(), "Items IDs/aliases to move") + .queryParam("source", joi.string().required(), "Source collection ID/alias") + .queryParam("dest", joi.string().required(), "Destination collection ID/alias") + .summary("Move items from source collection to destination collection") + .description("Move items from source collection to destination collection"); + +router + .get("/get_parents", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var item_id = g_lib.resolveID(req.queryParams.id, client); @@ -841,15 +972,13 @@ router.get('/get_parents', function(req, res) { var results = g_lib.getParents(item_id); if (req.queryParams.inclusive) { var item; - if (item_id[0] == 'c') - item = g_db.c.document(item_id); - else - item = g_db.d.document(item_id); + if (item_id[0] == "c") item = g_db.c.document(item_id); + else item = g_db.d.document(item_id); item = { id: item._id, title: item.title, - alias: item.alias + alias: item.alias, }; for (var i in results) { results[i].unshift(item); @@ -860,19 +989,20 @@ router.get('/get_parents', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().required(), "ID or alias of child item") - .queryParam('inclusive', joi.boolean().optional(), "Include child item in result") - .summary('Get parent collection(s) (path) of item') - .description('Get parent collection(s) (path) of item'); - -router.get('/get_offset', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().required(), "ID or alias of child item") + .queryParam("inclusive", joi.boolean().optional(), "Include child item in result") + .summary("Get parent collection(s) (path) of item") + .description("Get parent collection(s) (path) of item"); + +router + .get("/get_offset", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var coll_id = g_lib.resolveID(req.queryParams.id, client); var item_id = g_lib.resolveID(req.queryParams.item, client); - if (coll_id.charAt(0) != 'c') + if (coll_id.charAt(0) != "c") throw [g_lib.ERR_INVALID_PARAM, "ID is not a collection."]; /*if ( !g_lib.hasAdminPermObject( client, coll_id )) { @@ -882,39 +1012,49 @@ router.get('/get_offset', function(req, res) { }*/ var qry = "for v in 1..1 outbound @coll item "; - if (item_id.charAt(0) == 'c') + if (item_id.charAt(0) == "c") qry += "filter is_same_collection('c',v) sort v.title return v._id"; - else - qry += "sort is_same_collection('c',v) DESC, v.title return v._id"; + else qry += "sort is_same_collection('c',v) DESC, v.title return v._id"; - var ids = g_db._query(qry, { - coll: coll_id - }).toArray(); + var ids = g_db + ._query(qry, { + coll: coll_id, + }) + .toArray(); if (ids.length < req.queryParams.page_sz) res.send({ - offset: 0 + offset: 0, }); else { var idx = ids.indexOf(item_id); if (idx < 0) - throw [g_lib.ERR_NOT_FOUND, "Item " + req.queryParams.item + " was not found in collection " + req.queryParams.id]; + throw [ + g_lib.ERR_NOT_FOUND, + "Item " + + req.queryParams.item + + " was not found in collection " + + req.queryParams.id, + ]; res.send({ - offset: req.queryParams.page_sz * Math.floor(idx / req.queryParams.page_sz) + offset: req.queryParams.page_sz * Math.floor(idx / req.queryParams.page_sz), }); } } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().required(), "ID or alias of collection") - .queryParam('item', joi.string().required(), "ID or alias of child item") - .queryParam('page_sz', joi.number().required(), "Page size") - .summary('Get offset to item in collection') - .description('Get offset to item in collection. Offset will be aligned to specified page size.'); - -router.get('/published/list', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().required(), "ID or alias of collection") + .queryParam("item", joi.string().required(), "ID or alias of child item") + .queryParam("page_sz", joi.number().required(), "Page size") + .summary("Get offset to item in collection") + .description( + "Get offset to item in collection. Offset will be aligned to specified page size.", + ); + +router + .get("/published/list", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var owner_id; @@ -925,30 +1065,36 @@ router.get('/published/list', function(req, res) { owner_id = client._id; } - var qry = "for v in 1..1 inbound @user owner filter is_same_collection('c',v) && v.public sort v.title"; + var qry = + "for v in 1..1 inbound @user owner filter is_same_collection('c',v) && v.public sort v.title"; var result; if (req.queryParams.offset != undefined && req.queryParams.count != undefined) { qry += " limit " + req.queryParams.offset + ", " + req.queryParams.count; qry += " return { id: v._id, title: v.title, alias: v.alias }"; - result = g_db._query(qry, { - user: owner_id - }, {}, { - fullCount: true - }); + result = g_db._query( + qry, + { + user: owner_id, + }, + {}, + { + fullCount: true, + }, + ); var tot = result.getExtra().stats.fullCount; result = result.toArray(); result.push({ paging: { off: req.queryParams.offset, cnt: req.queryParams.count, - tot: tot - } + tot: tot, + }, }); } else { qry += " return { id: v._id, title: v.title, alias: v.alias }"; result = g_db._query(qry, { - user: owner_id + user: owner_id, }); } @@ -957,9 +1103,9 @@ router.get('/published/list', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().optional(), "UID of subject user (optional)") - .queryParam('offset', joi.number().optional(), "Offset") - .queryParam('count', joi.number().optional(), "Count") - .summary('Get list of clients published collections.') - .description('Get list of clients published collections.'); \ No newline at end of file + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().optional(), "UID of subject user (optional)") + .queryParam("offset", joi.number().optional(), "Offset") + .queryParam("count", joi.number().optional(), "Count") + .summary("Get list of clients published collections.") + .description("Get list of clients published collections."); diff --git a/core/database/foxx/api/config_router.js b/core/database/foxx/api/config_router.js index c0c24d863..2531a1167 100644 --- a/core/database/foxx/api/config_router.js +++ b/core/database/foxx/api/config_router.js @@ -1,32 +1,32 @@ -'use strict'; - -const createRouter = require('@arangodb/foxx/router'); -const router = createRouter(); -const g_db = require('@arangodb').db; -const g_lib = require('./support'); - -module.exports = router; - - -router.get('/msg/daily', function(req, res) { - try { - var msg = {}, - key = { - _key: "msg_daily" - }; - - if (g_db.config.exists(key)) { - msg = g_db.config.document(key); - - delete msg._id; - delete msg._key; - delete msg._rev; - } - - res.send(msg); - } catch (e) { - g_lib.handleException(e, res); - } - }) - .summary('Get message of the day.') - .description('Get message of the day. If not set, an empty document will be returned.'); \ No newline at end of file +"use strict"; + +const createRouter = require("@arangodb/foxx/router"); +const router = createRouter(); +const g_db = require("@arangodb").db; +const g_lib = require("./support"); + +module.exports = router; + +router + .get("/msg/daily", function (req, res) { + try { + var msg = {}, + key = { + _key: "msg_daily", + }; + + if (g_db.config.exists(key)) { + msg = g_db.config.document(key); + + delete msg._id; + delete msg._key; + delete msg._rev; + } + + res.send(msg); + } catch (e) { + g_lib.handleException(e, res); + } + }) + .summary("Get message of the day.") + .description("Get message of the day. If not set, an empty document will be returned."); diff --git a/core/database/foxx/api/data_router.js b/core/database/foxx/api/data_router.js index 079f1b444..0b2f74d98 100644 --- a/core/database/foxx/api/data_router.js +++ b/core/database/foxx/api/data_router.js @@ -1,12 +1,13 @@ -'use strict'; +"use strict"; -const createRouter = require('@arangodb/foxx/router'); +const createRouter = require("@arangodb/foxx/router"); const router = createRouter(); -const joi = require('joi'); -const g_db = require('@arangodb').db; -const g_lib = require('./support'); -const g_proc = require('./process'); -const g_tasks = require('./tasks'); +const joi = require("joi"); +const g_db = require("@arangodb").db; +const g_lib = require("./support"); +const g_proc = require("./process"); +const g_tasks = require("./tasks"); +const { UserToken } = require("./lib/user_token"); module.exports = router; @@ -22,7 +23,7 @@ function recordCreate(client, record, result) { if (record.parent) { parent_id = g_lib.resolveCollID(record.parent, client); owner_id = g_db.owner.firstExample({ - _from: parent_id + _from: parent_id, })._to; if (owner_id != client._id) { if (!g_lib.hasManagerPermProj(client, owner_id)) { @@ -40,11 +41,17 @@ function recordCreate(client, record, result) { // TODO This need to be updated when allocations can be assigned to collections // Enforce collection item limit - var cnt_res = g_db._query("for v in 1..1 outbound @coll item collect with count into n return n", { - coll: parent_id - }); + var cnt_res = g_db._query( + "for v in 1..1 outbound @coll item collect with count into n return n", + { + coll: parent_id, + }, + ); if (cnt_res.next() >= g_lib.MAX_COLL_ITEMS) - throw [g_lib.ERR_INPUT_TOO_LONG, "Parent collection item limit exceeded (" + g_lib.MAX_COLL_ITEMS + " items)"]; + throw [ + g_lib.ERR_INPUT_TOO_LONG, + "Parent collection item limit exceeded (" + g_lib.MAX_COLL_ITEMS + " items)", + ]; var time = Math.floor(Date.now() / 1000), obj = { @@ -52,9 +59,10 @@ function recordCreate(client, record, result) { ct: time, ut: time, owner: owner_id, - creator: client._id + creator: client._id, }, - sch_id, sch_ver; + sch_id, + sch_ver; g_lib.procInputParam(record, "title", false, obj); g_lib.procInputParam(record, "desc", false, obj); @@ -80,24 +88,21 @@ function recordCreate(client, record, result) { repo_alloc = g_lib.assignRepo(owner_id); } - if (!repo_alloc) - throw [g_lib.ERR_NO_ALLOCATION, "No allocation available"]; + if (!repo_alloc) throw [g_lib.ERR_NO_ALLOCATION, "No allocation available"]; // Extension setting only apply to managed data if (record.ext) { obj.ext_auto = false; obj.ext = record.ext; - if (obj.ext.length && obj.ext.charAt(0) != ".") - obj.ext = "." + obj.ext; + if (obj.ext.length && obj.ext.charAt(0) != ".") obj.ext = "." + obj.ext; } else { obj.ext_auto = true; } } if (record.md) { - obj.md = record.md; - if (Array.isArray(obj.md)) - throw [g_lib.ERR_INVALID_PARAM, "Metadata cannot be an array"]; + obj.md = JSON.parse(record.md); // parse escaped JSON string TODO: this could be dangerous + if (Array.isArray(obj.md)) throw [g_lib.ERR_INVALID_PARAM, "Metadata cannot be an array"]; } if (obj.alias) { @@ -124,29 +129,27 @@ function recordCreate(client, record, result) { if (idx < 0) { throw [g_lib.ERR_INVALID_PARAM, "Schema ID missing version number suffix."]; } - sch_id = obj.sch_id.substr(0, idx), - sch_ver = parseInt(obj.sch_id.substr(idx + 1)); + (sch_id = obj.sch_id.substr(0, idx)), (sch_ver = parseInt(obj.sch_id.substr(idx + 1))); var sch = g_db.sch.firstExample({ id: sch_id, - ver: sch_ver + ver: sch_ver, }); - if (!sch) - throw [g_lib.ERR_INVALID_PARAM, "Schema '" + obj.sch_id + "' does not exist"]; + if (!sch) throw [g_lib.ERR_INVALID_PARAM, "Schema '" + obj.sch_id + "' does not exist"]; obj.sch_id = sch._id; g_db._update(sch._id, { - cnt: sch.cnt + 1 + cnt: sch.cnt + 1, }); } var data = g_db.d.save(obj, { - returnNew: true + returnNew: true, }).new; g_db.owner.save({ _from: data._id, - _to: owner_id + _to: owner_id, }); g_lib.makeTitleUnique(parent_id, data); @@ -156,74 +159,81 @@ function recordCreate(client, record, result) { var loc = { _from: data._id, _to: repo_alloc._to, - uid: owner_id + uid: owner_id, }; g_db.loc.save(loc); g_db.alloc.update(repo_alloc._id, { - rec_count: repo_alloc.rec_count + 1 + rec_count: repo_alloc.rec_count + 1, }); data.repo_id = repo_alloc._to; } if (alias_key) { - if (g_db.a.exists({ - _key: alias_key - })) + if ( + g_db.a.exists({ + _key: alias_key, + }) + ) throw [g_lib.ERR_INVALID_PARAM, "Alias, " + alias_key + ", already in use"]; g_db.a.save({ - _key: alias_key + _key: alias_key, }); g_db.alias.save({ _from: data._id, - _to: "a/" + alias_key + _to: "a/" + alias_key, }); g_db.owner.save({ _from: "a/" + alias_key, - _to: owner_id + _to: owner_id, }); } - var updates = new Set(); // Handle specified dependencies if (record.deps != undefined) { - var dep, id, dep_data, dep_ids = new Set(); + var dep, + id, + dep_data, + dep_ids = new Set(); data.deps = []; for (var i in record.deps) { dep = record.deps[i]; id = g_lib.resolveDataID(dep.id, client); dep_data = g_db.d.document(id); - if (g_db.dep.firstExample({ + if ( + g_db.dep.firstExample({ _from: data._id, - _to: id - })) - throw [g_lib.ERR_INVALID_PARAM, "Only one dependency can be defined between any two data records."]; + _to: id, + }) + ) + throw [ + g_lib.ERR_INVALID_PARAM, + "Only one dependency can be defined between any two data records.", + ]; g_db.dep.save({ _from: data._id, _to: id, - type: dep.type + type: dep.type, }); data.deps.push({ id: id, alias: dep_data.alias, type: dep.type, - dir: g_lib.DEP_OUT + dir: g_lib.DEP_OUT, }); - if (dep.type < g_lib.DEP_IS_NEW_VERSION_OF) - dep_ids.add(id); + if (dep.type < g_lib.DEP_IS_NEW_VERSION_OF) dep_ids.add(id); } - if (dep_ids.size) - g_lib.annotationDependenciesUpdated(data, dep_ids, null, updates); + if (dep_ids.size) g_lib.annotationDependenciesUpdated(data, dep_ids, null, updates); } g_db.item.save({ _from: parent_id, - _to: data._id + _to: data._id, }); // Replace internal sch_id with user-facing sch_id + sch_ver @@ -241,24 +251,38 @@ function recordCreate(client, record, result) { result.results.push(data); } -router.post('/create', function(req, res) { +router + .post("/create", function (req, res) { var retry = 10; for (;;) { try { var result = { - results: [] + results: [], }; g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn", "repo"], - write: ["d", "a", "alloc", "loc", "owner", "alias", "item", "dep", "n", "note", "tag", "sch"] + write: [ + "d", + "a", + "alloc", + "loc", + "owner", + "alias", + "item", + "dep", + "n", + "note", + "tag", + "sch", + ], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); recordCreate(client, req.body, result); - } + }, }); res.send(result); @@ -270,36 +294,46 @@ router.post('/create', function(req, res) { } } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.object({ - title: joi.string().allow('').optional(), - desc: joi.string().allow('').optional(), - alias: joi.string().allow('').optional(), - parent: joi.string().allow('').optional(), - external: joi.boolean().optional(), - source: joi.string().allow('').optional(), - repo: joi.string().allow('').optional(), - md: joi.any().optional(), - sch_id: joi.string().allow('').optional(), - ext: joi.string().allow('').optional(), - ext_auto: joi.boolean().optional(), - deps: joi.array().items(joi.object({ - id: joi.string().required(), - type: joi.number().integer().required() - })).optional(), - tags: joi.array().items(joi.string()).optional() - }).required(), 'Record fields') - .summary('Create a new data record') - .description('Create a new data record from JSON body'); - - -router.post('/create/batch', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .object({ + title: joi.string().allow("").optional(), + desc: joi.string().allow("").optional(), + alias: joi.string().allow("").optional(), + parent: joi.string().allow("").optional(), + external: joi.boolean().optional(), + source: joi.string().allow("").optional(), + repo: joi.string().allow("").optional(), + md: joi.any().optional(), + sch_id: joi.string().allow("").optional(), + ext: joi.string().allow("").optional(), + ext_auto: joi.boolean().optional(), + deps: joi + .array() + .items( + joi.object({ + id: joi.string().required(), + type: joi.number().integer().required(), + }), + ) + .optional(), + tags: joi.array().items(joi.string()).optional(), + }) + .required(), + "Record fields", + ) + .summary("Create a new data record") + .description("Create a new data record from JSON body"); + +router + .post("/create/batch", function (req, res) { var retry = 10; for (;;) { try { var result = { - results: [] + results: [], }; //console.log( "create data" ); @@ -307,14 +341,27 @@ router.post('/create/batch', function(req, res) { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn", "repo"], - write: ["d", "a", "alloc", "loc", "owner", "alias", "item", "dep", "n", "note", "tag", "sch"] + write: [ + "d", + "a", + "alloc", + "loc", + "owner", + "alias", + "item", + "dep", + "n", + "note", + "tag", + "sch", + ], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); for (var i in req.body) { recordCreate(client, req.body[i], result); } - } + }, }); res.send(result); @@ -326,38 +373,48 @@ router.post('/create/batch', function(req, res) { } } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.array().items( - joi.object({ - title: joi.string().allow('').optional(), - desc: joi.string().allow('').optional(), - alias: joi.string().allow('').optional(), - parent: joi.string().allow('').optional(), - external: joi.boolean().optional(), - source: joi.string().allow('').optional(), - repo: joi.string().allow('').optional(), - md: joi.any().optional(), - sch_id: joi.string().allow('').optional(), - ext: joi.string().allow('').optional(), - ext_auto: joi.boolean().optional(), - deps: joi.array().items(joi.object({ - id: joi.string().required(), - type: joi.number().integer().required() - })).optional(), - tags: joi.array().items(joi.string()).optional(), - id: joi.string().allow('').optional(), // Ignored - locked: joi.boolean().optional(), // Ignore - size: joi.number().optional(), // Ignored - owner: joi.string().allow('').optional(), // Ignored - creator: joi.string().allow('').optional(), // Ignored - dt: joi.number().optional(), // Ignored - ut: joi.number().optional(), // Ignored - ct: joi.number().optional() // Ignored - }) - ).required(), 'Array of record with attributes') - .summary('Create a batch of new data records') - .description('Create a batch of new data records from JSON body'); - + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .array() + .items( + joi.object({ + title: joi.string().allow("").optional(), + desc: joi.string().allow("").optional(), + alias: joi.string().allow("").optional(), + parent: joi.string().allow("").optional(), + external: joi.boolean().optional(), + source: joi.string().allow("").optional(), + repo: joi.string().allow("").optional(), + md: joi.any().optional(), + sch_id: joi.string().allow("").optional(), + ext: joi.string().allow("").optional(), + ext_auto: joi.boolean().optional(), + deps: joi + .array() + .items( + joi.object({ + id: joi.string().required(), + type: joi.number().integer().required(), + }), + ) + .optional(), + tags: joi.array().items(joi.string()).optional(), + id: joi.string().allow("").optional(), // Ignored + locked: joi.boolean().optional(), // Ignore + size: joi.number().optional(), // Ignored + owner: joi.string().allow("").optional(), // Ignored + creator: joi.string().allow("").optional(), // Ignored + dt: joi.number().optional(), // Ignored + ut: joi.number().optional(), // Ignored + ct: joi.number().optional(), // Ignored + }), + ) + .required(), + "Array of record with attributes", + ) + .summary("Create a batch of new data records") + .description("Create a batch of new data records from JSON body"); function recordUpdate(client, record, result) { // /console.log("recordUpdate:",record); @@ -369,26 +426,31 @@ function recordUpdate(client, record, result) { // Required permissions depend on which fields are being modified: // Metadata = PERM_WR_META, file_size = PERM_WR_DATA, all else = ADMIN var perms = 0; - if (record.md !== undefined) - perms |= g_lib.PERM_WR_META; - - if (record.title !== undefined || record.alias !== undefined || record.desc !== undefined || - record.tags !== undefined || record.source !== undefined || - (record.dep_add && record.dep_add.length) || (record.dep_rem && record.dep_rem.length)) { + if (record.md !== undefined) perms |= g_lib.PERM_WR_META; + + if ( + record.title !== undefined || + record.alias !== undefined || + record.desc !== undefined || + record.tags !== undefined || + record.source !== undefined || + (record.dep_add && record.dep_add.length) || + (record.dep_rem && record.dep_rem.length) + ) { perms |= g_lib.PERM_WR_REC; } - if (data.locked || !g_lib.hasPermissions(client, data, perms)) - throw g_lib.ERR_PERM_DENIED; + if (data.locked || !g_lib.hasPermissions(client, data, perms)) throw g_lib.ERR_PERM_DENIED; } var owner_id = g_db.owner.firstExample({ - _from: data_id + _from: data_id, })._to, obj = { - ut: Math.floor(Date.now() / 1000) + ut: Math.floor(Date.now() / 1000), }, - sch, i; + sch, + i; g_lib.procInputParam(record, "title", true, obj); g_lib.procInputParam(record, "desc", true, obj); @@ -401,7 +463,7 @@ function recordUpdate(client, record, result) { obj.md_err_msg = null; obj.md_err = false; } else if (record.md) { - obj.md = record.md; + obj.md = JSON.parse(record.md); if (Array.isArray(obj.md)) { throw [g_lib.ERR_INVALID_PARAM, "Metadata cannot be an array"]; } @@ -417,7 +479,7 @@ function recordUpdate(client, record, result) { if (data.sch_id) { sch = g_db.sch.document(data.sch_id); g_db._update(sch._id, { - cnt: sch.cnt - 1 + cnt: sch.cnt - 1, }); obj.md_err_msg = null; obj.md_err = false; @@ -436,7 +498,7 @@ function recordUpdate(client, record, result) { sch = g_db.sch.firstExample({ id: sch_id, - ver: sch_ver + ver: sch_ver, }); if (!sch) { @@ -445,13 +507,13 @@ function recordUpdate(client, record, result) { obj.sch_id = sch._id; g_db._update(sch._id, { - cnt: sch.cnt + 1 + cnt: sch.cnt + 1, }); if (data.sch_id) { sch = g_db.sch.document(data.sch_id); g_db._update(sch._id, { - cnt: sch.cnt - 1 + cnt: sch.cnt - 1, }); } } @@ -466,11 +528,13 @@ function recordUpdate(client, record, result) { } } else { if (obj.source) { - throw [g_lib.ERR_INVALID_PARAM, "Raw data source cannot be specified for managed data records."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Raw data source cannot be specified for managed data records.", + ]; } - if (record.ext_auto !== undefined) - obj.ext_auto = record.ext_auto; + if (record.ext_auto !== undefined) obj.ext_auto = record.ext_auto; if (obj.ext_auto == true || (obj.ext_auto == undefined && data.ext_auto == true)) { if (data.source !== undefined) { @@ -490,8 +554,7 @@ function recordUpdate(client, record, result) { } } else { g_lib.procInputParam(record, "ext", true, obj); - if (obj.ext && obj.ext.charAt(0) != ".") - obj.ext = "." + obj.ext; + if (obj.ext && obj.ext.charAt(0) != ".") obj.ext = "." + obj.ext; } } @@ -534,35 +597,37 @@ function recordUpdate(client, record, result) { data = g_db._update(data_id, obj, { keepNull: false, returnNew: true, - mergeObjects: record.mdset ? false : true + mergeObjects: record.mdset ? false : true, }).new; if (obj.alias !== undefined) { var old_alias = g_db.alias.firstExample({ - _from: data_id + _from: data_id, }); if (old_alias) { - const graph = require('@arangodb/general-graph')._graph('sdmsg'); + const graph = require("@arangodb/general-graph")._graph("sdmsg"); graph.a.remove(old_alias._to); } if (obj.alias) { var alias_key = owner_id[0] + ":" + owner_id.substr(2) + ":" + obj.alias; - if (g_db.a.exists({ - _key: alias_key - })) + if ( + g_db.a.exists({ + _key: alias_key, + }) + ) throw [g_lib.ERR_INVALID_PARAM, "Alias, " + obj.alias + ", already in use"]; g_db.a.save({ - _key: alias_key + _key: alias_key, }); g_db.alias.save({ _from: data_id, - _to: "a/" + alias_key + _to: "a/" + alias_key, }); g_db.owner.save({ _from: "a/" + alias_key, - _to: owner_id + _to: owner_id, }); } } @@ -570,7 +635,9 @@ function recordUpdate(client, record, result) { if (record.deps != undefined && (record.deps_add != undefined || record.deps_rem != undefined)) throw [g_lib.ERR_INVALID_PARAM, "Cannot use both dependency set and add/remove."]; - var dep, id, deps_add = new Set(), + var dep, + id, + deps_add = new Set(), deps_rem = new Set(); if (record.dep_rem != undefined) { @@ -583,10 +650,13 @@ function recordUpdate(client, record, result) { dep = g_db.dep.firstExample({ _from: data._id, _to: id, - type: dep.type + type: dep.type, }); if (!dep) - throw [g_lib.ERR_INVALID_PARAM, "Specified dependency on " + id + " does not exist."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Specified dependency on " + id + " does not exist.", + ]; if (dep.type <= g_lib.DEP_IS_COMPONENT_OF) { //console.log("will remove:", id ); @@ -596,7 +666,7 @@ function recordUpdate(client, record, result) { g_db.dep.removeByExample({ _from: data._id, _to: id, - type: dep.type + type: dep.type, }); } } @@ -608,28 +678,37 @@ function recordUpdate(client, record, result) { if (!id.startsWith("d/")) throw [g_lib.ERR_INVALID_PARAM, "Dependencies can only be set on data records."]; - if (g_db.dep.firstExample({ + if ( + g_db.dep.firstExample({ _from: data._id, _to: id, - type: dep.type - })) - throw [g_lib.ERR_INVALID_PARAM, "Only one dependency of each type may be defined between any two data records."]; + type: dep.type, + }) + ) + throw [ + g_lib.ERR_INVALID_PARAM, + "Only one dependency of each type may be defined between any two data records.", + ]; g_db.dep.save({ _from: data_id, _to: id, - type: dep.type + type: dep.type, }); - if (dep.type <= g_lib.DEP_IS_COMPONENT_OF) - deps_add.add(id); + if (dep.type <= g_lib.DEP_IS_COMPONENT_OF) deps_add.add(id); } g_lib.checkDependencies(data_id); } if (deps_add.size || deps_rem.size) { - g_lib.annotationDependenciesUpdated(data, deps_add.size ? deps_add : null, deps_rem.size ? deps_rem : null, result.updates); + g_lib.annotationDependenciesUpdated( + data, + deps_add.size ? deps_add : null, + deps_rem.size ? deps_rem : null, + result.updates, + ); } // Convert DB schema _id to user-facing id + ver @@ -640,15 +719,18 @@ function recordUpdate(client, record, result) { data.notes = g_lib.getNoteMask(client, data); - data.deps = g_db._query("for v,e in 1..1 any @data dep return {id:v._id,alias:v.alias,type:e.type,from:e._from}", { - data: data_id - }).toArray(); + data.deps = g_db + ._query( + "for v,e in 1..1 any @data dep return {id:v._id,alias:v.alias,type:e.type,from:e._from}", + { + data: data_id, + }, + ) + .toArray(); for (i in data.deps) { dep = data.deps[i]; - if (dep.from == data_id) - dep.dir = g_lib.DEP_OUT; - else - dep.dir = g_lib.DEP_IN; + if (dep.from == data_id) dep.dir = g_lib.DEP_OUT; + else dep.dir = g_lib.DEP_IN; delete dep.from; } @@ -658,11 +740,11 @@ function recordUpdate(client, record, result) { if (!data.external) { var loc = g_db.loc.firstExample({ - _from: data_id + _from: data_id, }), alloc = g_db.alloc.firstExample({ _from: owner_id, - _to: loc._to + _to: loc._to, }); data.repo_id = alloc._to; @@ -675,27 +757,41 @@ function recordUpdate(client, record, result) { result.results.push(data); } -router.post('/update', function(req, res) { +router + .post("/update", function (req, res) { try { var result = { results: [], - updates: new Set() + updates: new Set(), }; const client = g_lib.getUserFromClientID(req.queryParams.client); g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn", "loc"], - write: ["d", "a", "p", "owner", "alias", "alloc", "dep", "n", "note", "tag", "sch"], - exclusive: ["task", "lock", "block"] + write: [ + "d", + "a", + "p", + "owner", + "alias", + "alloc", + "dep", + "n", + "note", + "tag", + "sch", + ], + exclusive: ["task", "lock", "block"], }, - action: function() { + action: function () { recordUpdate(client, req.body, result); - } + }, }); - var doc, updates = []; - result.updates.forEach(function(id) { + var doc, + updates = []; + result.updates.forEach(function (id) { if (id == req.body.id) { // Updated record is already in results - just copy it doc = Object.assign(result.results[0]); @@ -714,50 +810,77 @@ router.post('/update', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.object({ - id: joi.string().required(), - title: joi.string().allow('').optional(), - desc: joi.string().allow('').optional(), - alias: joi.string().allow('').optional(), - tags: joi.array().items(joi.string()).optional(), - tags_clear: joi.boolean().optional(), - md: joi.any().optional(), - mdset: joi.boolean().optional().default(false), - sch_id: joi.string().allow('').optional(), - //size: joi.number().optional(), - source: joi.string().allow('').optional(), - ext: joi.string().allow('').optional(), - ext_auto: joi.boolean().optional(), - //dt: joi.number().optional(), - dep_add: joi.array().items(joi.object({ - id: joi.string().required(), - type: joi.number().integer().required() - })).optional(), - dep_rem: joi.array().items(joi.object({ - id: joi.string().required(), - type: joi.number().integer().required() - })).optional() - }).required(), 'Record fields') - .summary('Update an existing data record') - .description('Update an existing data record from JSON body'); - - -router.post('/update/batch', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .object({ + id: joi.string().required(), + title: joi.string().allow("").optional(), + desc: joi.string().allow("").optional(), + alias: joi.string().allow("").optional(), + tags: joi.array().items(joi.string()).optional(), + tags_clear: joi.boolean().optional(), + md: joi.any().optional(), + mdset: joi.boolean().optional().default(false), + sch_id: joi.string().allow("").optional(), + //size: joi.number().optional(), + source: joi.string().allow("").optional(), + ext: joi.string().allow("").optional(), + ext_auto: joi.boolean().optional(), + //dt: joi.number().optional(), + dep_add: joi + .array() + .items( + joi.object({ + id: joi.string().required(), + type: joi.number().integer().required(), + }), + ) + .optional(), + dep_rem: joi + .array() + .items( + joi.object({ + id: joi.string().required(), + type: joi.number().integer().required(), + }), + ) + .optional(), + }) + .required(), + "Record fields", + ) + .summary("Update an existing data record") + .description("Update an existing data record from JSON body"); + +router + .post("/update/batch", function (req, res) { try { var result = { results: [], - updates: new Set() + updates: new Set(), }; const client = g_lib.getUserFromClientID(req.queryParams.client); g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn", "loc"], - write: ["d", "a", "p", "owner", "alias", "alloc", "dep", "n", "note", "tag", "sch"], - exclusive: ["task", "lock", "block"] + write: [ + "d", + "a", + "p", + "owner", + "alias", + "alloc", + "dep", + "n", + "note", + "tag", + "sch", + ], + exclusive: ["task", "lock", "block"], }, - action: function() { + action: function () { var rec; for (var i in req.body) { @@ -770,11 +893,12 @@ router.post('/update/batch', function(req, res) { recordUpdate(client, rec, result); } - } + }, }); - var doc, updates = []; - result.updates.forEach(function(id) { + var doc, + updates = []; + result.updates.forEach(function (id) { doc = g_db._document(id); doc.notes = g_lib.getNoteMask(client, doc); @@ -789,78 +913,102 @@ router.post('/update/batch', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.array().items( - joi.object({ - id: joi.string().required(), - title: joi.string().allow('').optional(), - desc: joi.string().allow('').optional(), - alias: joi.string().allow('').optional(), - tags: joi.array().items(joi.string()).optional(), - tags_clear: joi.boolean().optional(), - md: joi.any().optional(), - mdset: joi.boolean().optional().default(false), - sch_id: joi.string().allow('').optional(), - source: joi.string().allow('').optional(), - ext: joi.string().allow('').optional(), - ext_auto: joi.boolean().optional(), - dep_add: joi.array().items(joi.object({ - id: joi.string().required(), - type: joi.number().integer().required() - })).optional(), - dep_rem: joi.array().items(joi.object({ - id: joi.string().required(), - type: joi.number().integer().required() - })).optional(), - dt: joi.number().optional(), // Ignore - locked: joi.boolean().optional(), // Ignore - size: joi.number().optional(), // Ignore - owner: joi.string().allow('').optional(), // Ignored - creator: joi.string().allow('').optional(), // Ignored - ut: joi.number().optional(), // Ignored - ct: joi.number().optional() // Ignored - }) - ).required(), 'Array of records and field updates') - .summary('Update a batch of existing data record') - .description('Update a batch of existing data record from JSON body'); - -router.post('/update/md_err_msg', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .array() + .items( + joi.object({ + id: joi.string().required(), + title: joi.string().allow("").optional(), + desc: joi.string().allow("").optional(), + alias: joi.string().allow("").optional(), + tags: joi.array().items(joi.string()).optional(), + tags_clear: joi.boolean().optional(), + md: joi.any().optional(), + mdset: joi.boolean().optional().default(false), + sch_id: joi.string().allow("").optional(), + source: joi.string().allow("").optional(), + ext: joi.string().allow("").optional(), + ext_auto: joi.boolean().optional(), + dep_add: joi + .array() + .items( + joi.object({ + id: joi.string().required(), + type: joi.number().integer().required(), + }), + ) + .optional(), + dep_rem: joi + .array() + .items( + joi.object({ + id: joi.string().required(), + type: joi.number().integer().required(), + }), + ) + .optional(), + dt: joi.number().optional(), // Ignore + locked: joi.boolean().optional(), // Ignore + size: joi.number().optional(), // Ignore + owner: joi.string().allow("").optional(), // Ignored + creator: joi.string().allow("").optional(), // Ignored + ut: joi.number().optional(), // Ignored + ct: joi.number().optional(), // Ignored + }), + ) + .required(), + "Array of records and field updates", + ) + .summary("Update a batch of existing data record") + .description("Update a batch of existing data record from JSON body"); + +router + .post("/update/md_err_msg", function (req, res) { try { g_db._executeTransaction({ collections: { - write: ["d"] + write: ["d"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var data_id = g_lib.resolveDataID(req.queryParams.id, client); - if (!g_db.d.exists({ - _id: data_id - })) + if ( + !g_db.d.exists({ + _id: data_id, + }) + ) throw [g_lib.ERR_INVALID_PARAM, "Record, " + data_id + ", does not exist."]; // TODO Update schema validation error flag - g_db._update(data_id, { - md_err_msg: req.body, - md_err: true - }, { - keepNull: false - }); - } + g_db._update( + data_id, + { + md_err_msg: req.body, + md_err: true, + }, + { + keepNull: false, + }, + ); + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().optional(), "Client ID") - .queryParam('id', joi.string().required(), "Record ID") + .queryParam("client", joi.string().optional(), "Client ID") + .queryParam("id", joi.string().required(), "Record ID") //.body( joi.string().required(), 'Error message') - .body(['text/plain'], 'Error message') - .summary('Update data record schema validation error message') - .description('Update data record schema validation error message'); + .body(["text/plain"], "Error message") + .summary("Update data record schema validation error message") + .description("Update data record schema validation error message"); // Only called after upload of raw data for managed records -router.post('/update/size', function(req, res) { +router + .post("/update/size", function (req, res) { var retry = 10; // Must do this in a retry loop in case of concurrent (non-put) updates @@ -871,10 +1019,16 @@ router.post('/update/size', function(req, res) { g_db._executeTransaction({ collections: { read: ["owner", "loc"], - write: ["d", "alloc"] + write: ["d", "alloc"], }, - action: function() { - var owner_id, data, loc, alloc, rec, obj, t = Math.floor(Date.now() / 1000); + action: function () { + var owner_id, + data, + loc, + alloc, + rec, + obj, + t = Math.floor(Date.now() / 1000); for (var i in req.body.records) { rec = req.body.records[i]; @@ -883,29 +1037,29 @@ router.post('/update/size', function(req, res) { if (rec.size != data.size) { owner_id = g_db.owner.firstExample({ - _from: rec.id + _from: rec.id, })._to; loc = g_db.loc.firstExample({ - _from: rec.id + _from: rec.id, }); alloc = g_db.alloc.firstExample({ _from: owner_id, - _to: loc._to + _to: loc._to, }); obj = { ut: t, size: rec.size, - dt: t + dt: t, }; g_db._update(alloc._id, { - data_size: Math.max(0, alloc.data_size - data.size + obj.size) + data_size: Math.max(0, alloc.data_size - data.size + obj.size), }); g_db._update(rec.id, obj); } } - } + }, }); res.send(result); @@ -917,36 +1071,51 @@ router.post('/update/size', function(req, res) { } } }) - .queryParam('client', joi.string().allow('').optional(), "Client ID") - .body(joi.object({ - records: joi.array().items(joi.object({ - id: joi.string().required(), - size: joi.number().required() - })).required() - }).required(), 'Record fields') - .summary('Update existing data record size') - .description('Update existing data record raw data size'); - - -router.get('/view', function(req, res) { + .queryParam("client", joi.string().allow("").optional(), "Client ID") + .body( + joi + .object({ + records: joi + .array() + .items( + joi.object({ + id: joi.string().required(), + size: joi.number().required(), + }), + ) + .required(), + }) + .required(), + "Record fields", + ) + .summary("Update existing data record size") + .description("Update existing data record raw data size"); + +router + .get("/view", function (req, res) { try { const client = g_lib.getUserFromClientID_noexcept(req.queryParams.client); var data_id = g_lib.resolveDataID(req.queryParams.id, client); var data = g_db.d.document(data_id), - i, dep, rem_md = false, + i, + dep, + rem_md = false, admin = false; if (client) { admin = g_lib.hasAdminPermObject(client, data_id); if (!admin) { - var perms = g_lib.getPermissions(client, data, g_lib.PERM_RD_REC | g_lib.PERM_RD_META); + var perms = g_lib.getPermissions( + client, + data, + g_lib.PERM_RD_REC | g_lib.PERM_RD_META, + ); if (data.locked || (perms & (g_lib.PERM_RD_REC | g_lib.PERM_RD_META)) == 0) throw g_lib.ERR_PERM_DENIED; - if ((perms & g_lib.PERM_RD_META) == 0) - rem_md = true; + if ((perms & g_lib.PERM_RD_META) == 0) rem_md = true; } } else if (!g_lib.hasPublicRead(data_id)) { throw g_lib.ERR_PERM_DENIED; @@ -959,9 +1128,14 @@ router.get('/view', function(req, res) { data.sch_id = sch.id + ":" + sch.ver; } - data.deps = g_db._query("for v,e in 1..1 any @data dep let dir=e._from == @data?1:0 sort dir desc, e.type asc return {id:v._id,alias:v.alias,owner:v.owner,md_err:v.md_err,type:e.type,dir:dir}", { - data: data_id - }).toArray(); + data.deps = g_db + ._query( + "for v,e in 1..1 any @data dep let dir=e._from == @data?1:0 sort dir desc, e.type asc return {id:v._id,alias:v.alias,owner:v.owner,md_err:v.md_err,type:e.type,dir:dir}", + { + data: data_id, + }, + ) + .toArray(); for (i in data.deps) { dep = data.deps[i]; if (dep.alias && (!client || client._id != dep.owner)) @@ -970,12 +1144,11 @@ router.get('/view', function(req, res) { dep.notes = g_lib.getNoteMask(client, dep); } - if (rem_md && data.md) - delete data.md; + if (rem_md && data.md) delete data.md; if (!data.external) { data.repo_id = g_db.loc.firstExample({ - _from: data_id + _from: data_id, })._to; } @@ -985,27 +1158,29 @@ router.get('/view', function(req, res) { delete data._id; res.send({ - results: [data] + results: [data], }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().required(), "Data ID or alias") - .summary('Get data by ID or alias') - .description('Get data by ID or alias'); + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().required(), "Data ID or alias") + .summary("Get data by ID or alias") + .description("Get data by ID or alias"); - -router.post('/export', function(req, res) { +router + .post("/export", function (req, res) { try { g_db._executeTransaction({ collections: { - read: ["uuid", "accn", "d", "c", "item"] + read: ["uuid", "accn", "d", "c", "item"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); - var i, id, res_ids = []; + var i, + id, + res_ids = []; for (i in req.body.id) { id = g_lib.resolveDataCollID(req.body.id[i], client); @@ -1013,20 +1188,24 @@ router.post('/export', function(req, res) { } var ctxt = g_proc.preprocessItems(client, null, res_ids, g_lib.TT_DATA_EXPORT); - var data, ids = [], + var data, + ids = [], results = []; - for (i in ctxt.glob_data) - ids.push(ctxt.glob_data[i].id); - for (i in ctxt.http_data) - ids.push(ctxt.http_data[i].id); + for (i in ctxt.glob_data) ids.push(ctxt.glob_data[i].id); + for (i in ctxt.http_data) ids.push(ctxt.http_data[i].id); for (i in ids) { data = g_db.d.document(ids[i]); - data.deps = g_db._query("for v,e in 1..1 outbound @data dep return {id:v._id,type:e.type}", { - data: data._id - }).toArray(); + data.deps = g_db + ._query( + "for v,e in 1..1 outbound @data dep return {id:v._id,type:e.type}", + { + data: data._id, + }, + ) + .toArray(); delete data._rev; delete data._key; @@ -1037,32 +1216,42 @@ router.post('/export', function(req, res) { } res.send(results); - } + }, }); - } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.object({ - id: joi.array().items(joi.string()).required() - }).required(), 'Parameters') - .summary('Export record metadata') - .description('Export record metadata'); - - -router.get('/dep/graph/get', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .object({ + id: joi.array().items(joi.string()).required(), + }) + .required(), + "Parameters", + ) + .summary("Export record metadata") + .description("Export record metadata"); + +router + .get("/dep/graph/get", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var data_id = g_lib.resolveDataID(req.queryParams.id, client); - var i, j, entry, rec, deps, dep, node, visited = [data_id], - cur = [ - [data_id, true] - ], + var i, + j, + entry, + rec, + deps, + dep, + node, + visited = [data_id], + cur = [[data_id, true]], next = [], result = [], - notes, gen = 0; + notes, + gen = 0; // Get Ancestors @@ -1075,16 +1264,22 @@ router.get('/dep/graph/get', function(req, res) { rec = g_db.d.document(entry[0]); if (rec.alias && client._id != rec.owner) { - rec.alias = rec.owner.charAt(0) + ":" + rec.owner.substr(2) + ":" + rec.alias; + rec.alias = + rec.owner.charAt(0) + ":" + rec.owner.substr(2) + ":" + rec.alias; } //console.log("calc notes for", rec._id ); notes = g_lib.getNoteMask(client, rec); if (entry[1]) { - deps = g_db._query("for v,e in 1..1 outbound @data dep return {id:v._id,type:e.type,dir:1}", { - data: entry[0] - }).toArray(); + deps = g_db + ._query( + "for v,e in 1..1 outbound @data dep return {id:v._id,type:e.type,dir:1}", + { + data: entry[0], + }, + ) + .toArray(); for (j in deps) { dep = deps[j]; @@ -1105,7 +1300,7 @@ router.get('/dep/graph/get', function(req, res) { notes: notes, locked: rec.locked, gen: gen, - deps: deps + deps: deps, }); } else { result.push({ @@ -1116,7 +1311,7 @@ router.get('/dep/graph/get', function(req, res) { creator: rec.creator, size: rec.size, notes: notes, - locked: rec.locked + locked: rec.locked, }); } } @@ -1132,9 +1327,7 @@ router.get('/dep/graph/get', function(req, res) { //console.log("get descendants"); - cur = [ - [data_id, true] - ]; + cur = [[data_id, true]]; next = []; gen = 1; @@ -1145,9 +1338,14 @@ router.get('/dep/graph/get', function(req, res) { entry = cur[i]; //rec = g_db.d.document( cur[i] ); - deps = g_db._query("for v,e in 1..1 inbound @data dep return {id:v._id,alias:v.alias,title:v.title,owner:v.owner,creator:v.creator,size:v.size,md_err:v.md_err,locked:v.locked,type:e.type}", { - data: entry[0] - }).toArray(); + deps = g_db + ._query( + "for v,e in 1..1 inbound @data dep return {id:v._id,alias:v.alias,title:v.title,owner:v.owner,creator:v.creator,size:v.size,md_err:v.md_err,locked:v.locked,type:e.type}", + { + data: entry[0], + }, + ) + .toArray(); if (entry[1]) { for (j in deps) { @@ -1156,7 +1354,6 @@ router.get('/dep/graph/get', function(req, res) { //console.log("dep:",dep.id,"ty:",dep.type); if (visited.indexOf(dep.id) < 0) { - // TODO Why are we not just copying the dep object? node = { id: dep.id, @@ -1167,23 +1364,28 @@ router.get('/dep/graph/get', function(req, res) { size: dep.size, md_err: dep.md_err, locked: dep.locked, - deps: [{ - id: entry[0], - type: dep.type, - dir: 0 - }] + deps: [ + { + id: entry[0], + type: dep.type, + dir: 0, + }, + ], }; if (node.alias && client._id != node.owner) - node.alias = node.owner.charAt(0) + ":" + node.owner.substr(2) + ":" + node.alias; + node.alias = + node.owner.charAt(0) + + ":" + + node.owner.substr(2) + + ":" + + node.alias; node.notes = g_lib.getNoteMask(client, node); - if (dep.type < 2) - node.gen = gen; + if (dep.type < 2) node.gen = gen; result.push(node); visited.push(dep.id); - if (dep.type < 2) - next.push([dep.id, true]); + if (dep.type < 2) next.push([dep.id, true]); } } } @@ -1193,15 +1395,13 @@ router.get('/dep/graph/get', function(req, res) { next = []; } - //console.log("adjust gen:",gen_min); // Adjust gen values to start at 0 if (gen_min < 0) { for (i in result) { node = result[i]; - if (node.gen != undefined) - node.gen -= gen_min; + if (node.gen != undefined) node.gen -= gen_min; } } @@ -1210,22 +1410,24 @@ router.get('/dep/graph/get', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().required(), "Data ID or alias") - .summary('Get data dependency graph') - .description('Get data dependency graph'); - + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().required(), "Data ID or alias") + .summary("Get data dependency graph") + .description("Get data dependency graph"); -router.get('/lock', function(req, res) { +router + .get("/lock", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn", "a", "alias"], - write: ["d"] + write: ["d"], }, - action: function() { - var obj, i, result = []; + action: function () { + var obj, + i, + result = []; for (i in req.queryParams.ids) { obj = g_lib.getObject(req.queryParams.ids[i], client); @@ -1233,38 +1435,55 @@ router.get('/lock', function(req, res) { if (!g_lib.hasPermissions(client, obj, g_lib.PERM_LOCK)) throw g_lib.ERR_PERM_DENIED; } - g_db._update(obj._id, { - locked: req.queryParams.lock - }, { - returnNew: true - }); + g_db._update( + obj._id, + { + locked: req.queryParams.lock, + }, + { + returnNew: true, + }, + ); result.push({ id: obj._id, alias: obj.alias, title: obj.title, owner: obj.owner, - locked: req.queryParams.lock + locked: req.queryParams.lock, }); } res.send(result); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().optional(), "Client ID") - .queryParam('ids', joi.array().items(joi.string()).required(), "Array of data IDs or aliases") - .queryParam('lock', joi.bool().required(), "Lock (true) or unlock (false) flag") - .summary('Toggle data record lock') - .description('Toggle data record lock'); - - - -/** @brief Get raw data path for local direct access, if possible from specified domain + .queryParam("client", joi.string().optional(), "Client ID") + .queryParam("ids", joi.array().items(joi.string()).required(), "Array of data IDs or aliases") + .queryParam("lock", joi.bool().required(), "Lock (true) or unlock (false) flag") + .summary("Toggle data record lock") + .description("Toggle data record lock"); + +/** + * @function + * @description Gets the raw data path for local direct access from the specified domain, + * if available, for a given data ID and client. + * + * The method checks the client's permissions for the data ID and returns the path to the data + * if the client has the required permissions and the data exists in the specified domain. + * + * @param {object} req - The request object, containing the query parameters. + * @param {object} res - The response object, used to send the raw data path or error. + * + * @throws {Error} g_lib.ERR_PERM_DENIED - If the client does not have permission to read the data. + * @throws {Error} g_lib.ERR_NO_RAW_DATA - If the raw data is not found. + * @throws {Error} g_lib.ERR_INVALID_PARAM - If the data belongs to a different domain than specified. * + * @returns {void} - Returns the raw data path in the response if the request is successful. */ -router.get('/path', function(req, res) { +router + .get("/path", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var data_id = g_lib.resolveDataID(req.queryParams.id, client); @@ -1272,37 +1491,38 @@ router.get('/path', function(req, res) { if (!g_lib.hasAdminPermObject(client, data_id)) { var data = g_db.d.document(data_id); var perms = g_lib.getPermissions(client, data, g_lib.PERM_RD_DATA); - if ((perms & g_lib.PERM_RD_DATA) == 0) - throw g_lib.ERR_PERM_DENIED; + if ((perms & g_lib.PERM_RD_DATA) == 0) throw g_lib.ERR_PERM_DENIED; } var loc = g_db.loc.firstExample({ - _from: data_id + _from: data_id, }); - if (!loc) - throw g_lib.ERR_NO_RAW_DATA; + if (!loc) throw g_lib.ERR_NO_RAW_DATA; var repo = g_db.repo.document(loc._to); if (repo.domain != req.queryParams.domain) - throw [g_lib.ERR_INVALID_PARAM, "Can only access data from '" + repo.domain + "' domain"]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Can only access data from '" + repo.domain + "' domain", + ]; var path = g_lib.computeDataPath(loc, true); res.send({ - path: path + path: path, }); //res.send({ path: repo.exp_path + loc.path.substr( repo.path.length ) }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().optional(), "Client ID") - .queryParam('id', joi.string().required(), "Data ID (not alias)") - .queryParam('domain', joi.string().required(), "Client domain") - .summary('Get raw data local path') - .description('Get raw data local path'); - - -router.get('/list/by_alloc', function(req, res) { + .queryParam("client", joi.string().optional(), "Client ID") + .queryParam("id", joi.string().required(), "Data ID (not alias)") + .queryParam("domain", joi.string().required(), "Client domain") + .summary("Get raw data local path") + .description("Get raw data local path"); + +router + .get("/list/by_alloc", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var owner_id; @@ -1319,31 +1539,39 @@ router.get('/list/by_alloc', function(req, res) { } var qry = "for v,e in 1..1 inbound @repo loc filter e.uid == @uid sort v.title", - result, doc; + result, + doc; if (req.queryParams.offset != undefined && req.queryParams.count != undefined) { qry += " limit " + req.queryParams.offset + ", " + req.queryParams.count; - qry += " return { id: v._id, title: v.title, alias: v.alias, owner: v.owner, creator: v.creator, size: v.size, md_err: v.md_err, external: v.external, locked: v.locked }"; - result = g_db._query(qry, { - repo: req.queryParams.repo, - uid: owner_id - }, {}, { - fullCount: true - }); + qry += + " return { id: v._id, title: v.title, alias: v.alias, owner: v.owner, creator: v.creator, size: v.size, md_err: v.md_err, external: v.external, locked: v.locked }"; + result = g_db._query( + qry, + { + repo: req.queryParams.repo, + uid: owner_id, + }, + {}, + { + fullCount: true, + }, + ); var tot = result.getExtra().stats.fullCount; result = result.toArray(); result.push({ paging: { off: req.queryParams.offset, cnt: req.queryParams.count, - tot: tot - } + tot: tot, + }, }); } else { - qry += " return { id: v._id, title: v.title, alias: v.alias, owner: v.owner, creator: v.creator, size: v.size, md_err: v.md_err, external: v.external, locked: v.locked }"; + qry += + " return { id: v._id, title: v.title, alias: v.alias, owner: v.owner, creator: v.creator, size: v.size, md_err: v.md_err, external: v.external, locked: v.locked }"; result = g_db._query(qry, { repo: req.queryParams.repo, - uid: owner_id + uid: owner_id, }); } @@ -1359,183 +1587,284 @@ router.get('/list/by_alloc', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().optional(), "UID of subject user (optional)") - .queryParam('repo', joi.string().required(), "Repo ID") - .queryParam('offset', joi.number().optional(), "Offset") - .queryParam('count', joi.number().optional(), "Count") - .summary('List data records by allocation') - .description('List data records by allocation'); - - -router.post('/get', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().optional(), "UID of subject user (optional)") + .queryParam("repo", joi.string().required(), "Repo ID") + .queryParam("offset", joi.number().optional(), "Offset") + .queryParam("count", joi.number().optional(), "Count") + .summary("List data records by allocation") + .description("List data records by allocation"); + +router + .post("/get", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["uuid", "accn", "d", "c", "item"], write: ["u"], - exclusive: ["task", "lock", "block"] + exclusive: ["task", "lock", "block"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); - var id, res_ids = []; + var id, + res_ids = []; if (!req.body.check && !req.body.path) - throw [g_lib.ERR_INVALID_PARAM, "Must provide path parameter if not running check."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Must provide path parameter if not running check.", + ]; + + const { collection_id, collection_type } = req.body; + const is_collection = UserToken.validateRequestParams(req.body); + const token_exists = new UserToken({ + user_id: client._id, + globus_collection_id: req.body.collection_id, + }).exists(); + if (is_collection && !token_exists) { + throw [ + g_lib.ERR_NOT_FOUND, + "Globus token for mapped collection " + + collection_id + + " for user " + + client._id + + " does not exist.", + ]; + } for (var i in req.body.id) { id = g_lib.resolveDataCollID(req.body.id[i], client); res_ids.push(id); } - var result = g_tasks.taskInitDataGet(client, req.body.path, req.body.encrypt, res_ids, req.body.orig_fname, req.body.check); + var result = g_tasks.taskInitDataGet( + client, + req.body.path, + req.body.encrypt, + res_ids, + req.body.orig_fname, + req.body.check, + is_collection, + { collection_id: collection_id, collection_type: collection_type }, + ); if (!req.body.check) g_lib.saveRecentGlobusPath(client, req.body.path, g_lib.TT_DATA_GET); res.send(result); - } + }, }); - } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.object({ - id: joi.array().items(joi.string()).required(), - path: joi.string().optional(), - encrypt: joi.number().optional(), - orig_fname: joi.boolean().optional(), - check: joi.boolean().optional() - }).required(), 'Parameters') - .summary('Get (download) data to Globus destination path') - .description('Get (download) data to Globus destination path. IDs may be data/collection IDs or aliases.'); - - -router.post('/put', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .object({ + id: joi.array().items(joi.string()).required(), + path: joi.string().optional(), + encrypt: joi.number().optional(), + orig_fname: joi.boolean().optional(), + check: joi.boolean().optional(), + collection_id: joi.string().optional().guid(), + collection_type: joi.string().optional().valid("mapped"), + }) + .required(), + "Parameters", + ) + .summary("Get (download) data to Globus destination path") + .description( + "Get (download) data to Globus destination path. IDs may be data/collection IDs or aliases.", + ); + +router + .post("/put", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["uuid", "accn", "d", "c", "item"], write: ["u"], - exclusive: ["task", "lock", "block"] + exclusive: ["task", "lock", "block"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var res_ids = []; if (!req.body.check && !req.body.path) - throw [g_lib.ERR_INVALID_PARAM, "Must provide path parameter if not running check."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Must provide path parameter if not running check.", + ]; if (req.body.id.length > 1) - throw [g_lib.ERR_INVALID_PARAM, "Concurrent put of multiple records no supported."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Concurrent put of multiple records no supported.", + ]; + + const { collection_id, collection_type } = req.body; + const is_collection = UserToken.validateRequestParams(req.body); + const token_exists = new UserToken({ + user_id: client._id, + globus_collection_id: req.body.collection_id, + }).exists(); + if (is_collection && !token_exists) { + throw [ + g_lib.ERR_NOT_FOUND, + "Globus token for mapped collection " + + collection_id + + " for user " + + client._id + + " does not exist.", + ]; + } for (var i in req.body.id) { res_ids.push(g_lib.resolveDataID(req.body.id[i], client)); } - var result = g_tasks.taskInitDataPut(client, req.body.path, req.body.encrypt, req.body.ext, res_ids, req.body.check); + var result = g_tasks.taskInitDataPut( + client, + req.body.path, + req.body.encrypt, + req.body.ext, + res_ids, + req.body.check, + is_collection, + { collection_id: collection_id, collection_type: collection_type }, + ); if (!req.body.check) g_lib.saveRecentGlobusPath(client, req.body.path, g_lib.TT_DATA_PUT); res.send(result); - } + }, }); - } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.object({ - id: joi.array().items(joi.string()).required(), - path: joi.string().optional(), - encrypt: joi.number().optional(), - ext: joi.string().optional(), - check: joi.boolean().optional() - }).required(), 'Parameters') - .summary('Put (upload) raw data to record') - .description('Put (upload) raw data to record from Globus source path. ID must be a data ID or alias.'); - - -router.post('/alloc_chg', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .object({ + id: joi.array().items(joi.string()).required(), + path: joi.string().optional(), + encrypt: joi.number().optional(), + ext: joi.string().optional(), + check: joi.boolean().optional(), + collection_id: joi.string().optional().guid(), + collection_type: joi.string().optional().valid("mapped"), + }) + .required(), + "Parameters", + ) + .summary("Put (upload) raw data to record") + .description( + "Put (upload) raw data to record from Globus source path. ID must be a data ID or alias.", + ); + +router + .post("/alloc_chg", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn", "d", "c", "item"], - exclusive: ["task", "lock", "block"] + exclusive: ["task", "lock", "block"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); - var id, res_ids = []; + var id, + res_ids = []; for (var i in req.body.ids) { id = g_lib.resolveDataCollID(req.body.ids[i], client); res_ids.push(id); } - var result = g_tasks.taskInitRecAllocChg(client, req.body.proj_id, res_ids, req.body.repo_id, req.body.check); + var result = g_tasks.taskInitRecAllocChg( + client, + req.body.proj_id, + res_ids, + req.body.repo_id, + req.body.check, + ); res.send(result); - } + }, }); - } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.object({ - ids: joi.array().items(joi.string()).required(), - proj_id: joi.string().optional(), - repo_id: joi.string().required(), - check: joi.boolean().optional() - }).required(), 'Parameters') - .summary('Move raw data to a new allocation') - .description('Move data to a new allocation. IDs may be data/collection IDs or aliases.'); - - -router.post('/owner_chg', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .object({ + ids: joi.array().items(joi.string()).required(), + proj_id: joi.string().optional(), + repo_id: joi.string().required(), + check: joi.boolean().optional(), + }) + .required(), + "Parameters", + ) + .summary("Move raw data to a new allocation") + .description("Move data to a new allocation. IDs may be data/collection IDs or aliases."); + +router + .post("/owner_chg", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn", "d", "c", "item", "admin"], - exclusive: ["task", "lock", "block"] + exclusive: ["task", "lock", "block"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); - var id, res_ids = []; + var id, + res_ids = []; for (var i in req.body.ids) { id = g_lib.resolveDataCollID(req.body.ids[i], client); res_ids.push(id); } var coll_id = g_lib.resolveDataCollID(req.body.coll_id, client); - var result = g_tasks.taskInitRecOwnerChg(client, res_ids, coll_id, req.body.repo_id, req.body.check); + var result = g_tasks.taskInitRecOwnerChg( + client, + res_ids, + coll_id, + req.body.repo_id, + req.body.check, + ); res.send(result); - } + }, }); - } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.object({ - ids: joi.array().items(joi.string()).required(), - coll_id: joi.string().required(), - repo_id: joi.string().optional(), - check: joi.boolean().optional() - }).required(), 'Parameters') - .summary('Move data records and raw data to a new owner/allocation') - .description('Move data records and raw data to a new owner/allocation. IDs may be data/collection IDs or aliases.'); - - - -router.post('/delete', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .object({ + ids: joi.array().items(joi.string()).required(), + coll_id: joi.string().required(), + repo_id: joi.string().optional(), + check: joi.boolean().optional(), + }) + .required(), + "Parameters", + ) + .summary("Move data records and raw data to a new owner/allocation") + .description( + "Move data records and raw data to a new owner/allocation. IDs may be data/collection IDs or aliases.", + ); + +router + .post("/delete", function (req, res) { var retry = 10; for (;;) { @@ -1543,12 +1872,30 @@ router.post('/delete', function(req, res) { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn"], - write: ["d", "c", "a", "alias", "owner", "item", "acl", "loc", "alloc", "p", "t", "top", "dep", "n", "note"], + write: [ + "d", + "c", + "a", + "alias", + "owner", + "item", + "acl", + "loc", + "alloc", + "p", + "t", + "top", + "dep", + "n", + "note", + ], exclusive: ["lock", "task", "block"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); - var i, id, ids = []; + var i, + id, + ids = []; for (i in req.body.ids) { id = g_lib.resolveDataCollID(req.body.ids[i], client); @@ -1558,7 +1905,7 @@ router.post('/delete', function(req, res) { var result = g_tasks.taskInitRecCollDelete(client, ids); res.send(result); - } + }, }); break; } catch (e) { @@ -1568,9 +1915,16 @@ router.post('/delete', function(req, res) { } } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.object({ - ids: joi.array().items(joi.string()).required(), - }).required(), 'Parameters') - .summary('Delete collections, data records and raw data') - .description('Delete collections, data records and associated raw data. IDs may be data IDs or aliases.'); \ No newline at end of file + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .object({ + ids: joi.array().items(joi.string()).required(), + }) + .required(), + "Parameters", + ) + .summary("Delete collections, data records and raw data") + .description( + "Delete collections, data records and associated raw data. IDs may be data IDs or aliases.", + ); diff --git a/core/database/foxx/api/group_router.js b/core/database/foxx/api/group_router.js index 4d2e2b1cf..4d4f53416 100644 --- a/core/database/foxx/api/group_router.js +++ b/core/database/foxx/api/group_router.js @@ -1,28 +1,28 @@ -'use strict'; +"use strict"; -const createRouter = require('@arangodb/foxx/router'); +const createRouter = require("@arangodb/foxx/router"); const router = createRouter(); -const joi = require('joi'); +const joi = require("joi"); -const g_db = require('@arangodb').db; -const g_graph = require('@arangodb/general-graph')._graph('sdmsg'); -const g_lib = require('./support'); +const g_db = require("@arangodb").db; +const g_graph = require("@arangodb/general-graph")._graph("sdmsg"); +const g_lib = require("./support"); module.exports = router; - //========== GROUP API FUNCTIONS ========== -router.get('/create', function(req, res) { +router + .get("/create", function (req, res) { try { var result = []; g_db._executeTransaction({ collections: { read: ["u", "p", "uuid", "accn", "admin"], - write: ["g", "owner", "member"] + write: ["g", "owner", "member"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var uid; @@ -37,26 +37,28 @@ router.get('/create', function(req, res) { throw [g_lib.ERR_PERM_DENIED, "Group ID 'members' is reserved"]; var obj = { - uid: uid + uid: uid, }; g_lib.procInputParam(req.queryParams, "gid", false, obj); g_lib.procInputParam(req.queryParams, "title", false, obj); g_lib.procInputParam(req.queryParams, "summary", false, obj); - if (g_db.g.firstExample({ + if ( + g_db.g.firstExample({ uid: uid, - gid: obj.gid - })) + gid: obj.gid, + }) + ) throw [g_lib.ERR_IN_USE, "Group ID '" + obj.gid + "' already exists."]; var group = g_db.g.save(obj, { - returnNew: true + returnNew: true, }); g_db.owner.save({ _from: group._id, - _to: uid + _to: uid, }); if (req.queryParams.members) { @@ -69,7 +71,7 @@ router.get('/create', function(req, res) { g_db.member.save({ _from: group._id, - _to: mem + _to: mem, }); } } else { @@ -81,7 +83,7 @@ router.get('/create', function(req, res) { delete group._rev; result.push(group.new); - } + }, }); res.send(result); @@ -89,26 +91,26 @@ router.get('/create', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('proj', joi.string().optional(), "Project ID (optional)") - .queryParam('gid', joi.string().required(), "Group ID") - .queryParam('title', joi.string().optional().allow(""), "Title") - .queryParam('desc', joi.string().optional().allow(""), "Description") - .queryParam('members', joi.array().items(joi.string()).optional(), "Array of member UIDs") - .summary('Creates a new group') - .description('Creates a new group owned by client (or project), with optional members'); - - -router.get('/update', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("proj", joi.string().optional(), "Project ID (optional)") + .queryParam("gid", joi.string().required(), "Group ID") + .queryParam("title", joi.string().optional().allow(""), "Title") + .queryParam("desc", joi.string().optional().allow(""), "Description") + .queryParam("members", joi.array().items(joi.string()).optional(), "Array of member UIDs") + .summary("Creates a new group") + .description("Creates a new group owned by client (or project), with optional members"); + +router + .get("/update", function (req, res) { try { var result = []; g_db._executeTransaction({ collections: { read: ["u", "p", "uuid", "accn", "admin"], - write: ["g", "owner", "member"] + write: ["g", "owner", "member"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var group; @@ -116,20 +118,26 @@ router.get('/update', function(req, res) { var uid = req.queryParams.proj; group = g_db.g.firstExample({ uid: uid, - gid: req.queryParams.gid + gid: req.queryParams.gid, }); if (!group) - throw [g_lib.ERR_NOT_FOUND, "Group ID '" + req.queryParams.gid + "' not found"]; + throw [ + g_lib.ERR_NOT_FOUND, + "Group ID '" + req.queryParams.gid + "' not found", + ]; //g_lib.ensureAdminPermObject( client, group._id ); g_lib.ensureManagerPermProj(client, uid); } else { group = g_db.g.firstExample({ uid: client._id, - gid: req.queryParams.gid + gid: req.queryParams.gid, }); if (!group) - throw [g_lib.ERR_NOT_FOUND, "Group ID '" + req.queryParams.gid + "' not found"]; + throw [ + g_lib.ERR_NOT_FOUND, + "Group ID '" + req.queryParams.gid + "' not found", + ]; } var obj = {}; @@ -141,7 +149,7 @@ router.get('/update', function(req, res) { group = g_db._update(group._id, obj, { keepNull: false, - returnNew: true + returnNew: true, }); group = group.new; } @@ -155,13 +163,15 @@ router.get('/update', function(req, res) { if (!g_db._exists(mem)) throw [g_lib.ERR_NOT_FOUND, "User, " + mem + ", not found"]; - if (!g_db.member.firstExample({ + if ( + !g_db.member.firstExample({ _from: group._id, - _to: mem - })) + _to: mem, + }) + ) g_db.member.save({ _from: group._id, - _to: mem + _to: mem, }); } } @@ -174,23 +184,24 @@ router.get('/update', function(req, res) { edge = g_db.member.firstExample({ _from: group._id, - _to: mem + _to: mem, }); - if (edge) - g_db._remove(edge); + if (edge) g_db._remove(edge); } } - group.members = g_db._query("for v in 1..1 outbound @group member return v._key", { - group: group._id - }).toArray(); + group.members = g_db + ._query("for v in 1..1 outbound @group member return v._key", { + group: group._id, + }) + .toArray(); delete group._id; delete group._key; delete group._rev; result.push(group); - } + }, }); res.send(result); @@ -198,25 +209,33 @@ router.get('/update', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('proj', joi.string().optional(), "Project ID") - .queryParam('gid', joi.string().required(), "Group ID") - .queryParam('title', joi.string().allow('').optional(), "New title") - .queryParam('desc', joi.string().allow('').optional(), "New description") - .queryParam('add', joi.array().items(joi.string()).optional(), "Array of member UIDs to add to group") - .queryParam('rem', joi.array().items(joi.string()).optional(), "Array of member UIDs to remove from group") - .summary('Updates an existing group') - .description('Updates an existing group owned by client (or project).'); - - -router.get('/delete', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("proj", joi.string().optional(), "Project ID") + .queryParam("gid", joi.string().required(), "Group ID") + .queryParam("title", joi.string().allow("").optional(), "New title") + .queryParam("desc", joi.string().allow("").optional(), "New description") + .queryParam( + "add", + joi.array().items(joi.string()).optional(), + "Array of member UIDs to add to group", + ) + .queryParam( + "rem", + joi.array().items(joi.string()).optional(), + "Array of member UIDs to remove from group", + ) + .summary("Updates an existing group") + .description("Updates an existing group owned by client (or project)."); + +router + .get("/delete", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn", "owner", "admin"], - write: ["g", "owner", "member", "acl"] + write: ["g", "owner", "member", "acl"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var group; @@ -224,41 +243,46 @@ router.get('/delete', function(req, res) { var uid = req.queryParams.proj; group = g_db.g.firstExample({ uid: uid, - gid: req.queryParams.gid + gid: req.queryParams.gid, }); if (!group) - throw [g_lib.ERR_NOT_FOUND, "Group ID '" + req.queryParams.gid + "' not found"]; + throw [ + g_lib.ERR_NOT_FOUND, + "Group ID '" + req.queryParams.gid + "' not found", + ]; //g_lib.ensureAdminPermObject( client, group._id ); g_lib.ensureManagerPermProj(client, uid); // Make sure special members project is protected - if (group.gid == "members") - throw g_lib.ERR_PERM_DENIED; + if (group.gid == "members") throw g_lib.ERR_PERM_DENIED; } else { group = g_db.g.firstExample({ uid: client._id, - gid: req.queryParams.gid + gid: req.queryParams.gid, }); if (!group) - throw [g_lib.ERR_NOT_FOUND, "Group, " + req.queryParams.gid + ", not found"]; + throw [ + g_lib.ERR_NOT_FOUND, + "Group, " + req.queryParams.gid + ", not found", + ]; } g_graph.g.remove(group._id); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('proj', joi.string().optional(), "Project ID") - .queryParam('gid', joi.string().required(), "Group ID") - .summary('Deletes an existing group') - .description('Deletes an existing group owned by client or project'); - - -router.get('/list', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("proj", joi.string().optional(), "Project ID") + .queryParam("gid", joi.string().required(), "Group ID") + .summary("Deletes an existing group") + .description("Deletes an existing group owned by client or project"); + +router + .get("/list", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var owner_id; @@ -271,22 +295,27 @@ router.get('/list', function(req, res) { owner_id = client._id; } - var groups = g_db._query("for v in 1..1 inbound @client owner filter IS_SAME_COLLECTION('g', v) return { uid: v.uid, gid: v.gid, title: v.title }", { - client: owner_id - }).toArray(); + var groups = g_db + ._query( + "for v in 1..1 inbound @client owner filter IS_SAME_COLLECTION('g', v) return { uid: v.uid, gid: v.gid, title: v.title }", + { + client: owner_id, + }, + ) + .toArray(); res.send(groups); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('proj', joi.string().optional(), "Project ID") - .summary('List groups') - .description('List groups owned by client or project'); + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("proj", joi.string().optional(), "Project ID") + .summary("List groups") + .description("List groups owned by client or project"); - -router.get('/view', function(req, res) { +router + .get("/view", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var group; @@ -295,7 +324,7 @@ router.get('/view', function(req, res) { var uid = req.queryParams.proj; group = g_db.g.firstExample({ uid: uid, - gid: req.queryParams.gid + gid: req.queryParams.gid, }); if (!group) throw [g_lib.ERR_NOT_FOUND, "Group ID '" + req.queryParams.gid + "' not found"]; @@ -305,7 +334,7 @@ router.get('/view', function(req, res) { } else { group = g_db.g.firstExample({ uid: client._id, - gid: req.queryParams.gid + gid: req.queryParams.gid, }); if (!group) throw [g_lib.ERR_NOT_FOUND, "Group ID '" + req.queryParams.gid + "' not found"]; @@ -315,19 +344,20 @@ router.get('/view', function(req, res) { uid: group.uid, gid: group.gid, title: group.title, - desc: group.desc + desc: group.desc, }; - result.members = g_db._query("for v in 1..1 outbound @group member return v._id", { - group: group._id - }).toArray(); + result.members = g_db + ._query("for v in 1..1 outbound @group member return v._id", { + group: group._id, + }) + .toArray(); res.send([result]); - } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('proj', joi.string().optional(), "Project ID") - .queryParam('gid', joi.string().required(), "Group ID") - .summary('View group details') - .description('View group details'); \ No newline at end of file + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("proj", joi.string().optional(), "Project ID") + .queryParam("gid", joi.string().required(), "Group ID") + .summary("View group details") + .description("View group details"); diff --git a/core/database/foxx/api/lib/user_token.js b/core/database/foxx/api/lib/user_token.js new file mode 100644 index 000000000..a3f66bfda --- /dev/null +++ b/core/database/foxx/api/lib/user_token.js @@ -0,0 +1,164 @@ +"use strict"; + +const g_lib = require("../support.js"); +const { UserModel } = require("../models/user"); +const { GlobusCollectionModel } = require("../models/globus_collection"); +const { GlobusTokenModel } = require("../models/globus_token"); +const { DataFedOAuthToken } = require("../models/DataFedOAuthToken"); + +class UserToken { + /** @type {UserModel} */ + #user_model; + user; + /** @type {Readonly} */ + globus_collection; + /** @type {Readonly} */ + #working_token; + + /** Creates object for accessing user tokens. + * Validation is handled by individual models. + * + * @param {object} kwargs - Keyword arguments for building and accessing user tokens + * @param {string} [kwargs.user_key] - Key for determining user model + * @param {string} [kwargs.user_id] - ID for determining user model + * @param {string} [kwargs.globus_collection_id] - UUID for determining globus collection model + * @returns {UserToken} - Accessor object for user token information + */ + constructor(kwargs) { + const { user_key, user_id, globus_collection_id } = kwargs; + this.#user_model = new UserModel(user_id, user_key); + if (!this.#user_model.exists()) { + throw [g_lib.ERR_NOT_FOUND, "Specified user does not exist: " + kwargs]; + } + this.user = this.#user_model.get(); + if (typeof globus_collection_id !== "undefined") { + const globus_collection_model = new GlobusCollectionModel(globus_collection_id); + this.globus_collection = globus_collection_model.get(); + if (globus_collection_model.exists()) { + const globus_token_model = new GlobusTokenModel( + this.user.id, + this.globus_collection.id, + ); + this.#working_token = globus_token_model.get_oauth_token(); + } else { + // TODO: should this state throw an error or perhaps provide reason? + this.#working_token = new DataFedOAuthToken(); + } + } + } + + #fetch_token() { + if (!this.#working_token) { + this.#working_token = this.#user_model.get_token(); + } + } + + /** Gets correctly typed token for usage with OAuth APIs + * + * @returns {Readonly} Formatted read only OAuth token + */ + get_token() { + this.#fetch_token(); + return Object.freeze(this.#working_token); + } + + /** Validates minimum viable token attributes exist + * + * @returns {boolean} Whether the token has required attributes + */ + exists() { + this.#fetch_token(); + // check that required fields are not null + return ( + !!this.#working_token.access && + !!this.#working_token.refresh && + !!this.#working_token.expiration + ); + } + + /** + * Validates request parameter object has all necessary pieces and determines whether the requested token is a collection token + * @param {object} query_params - Raw query parameters passed to endpoint logic after JOI parse. + * @param {string} [query_params.collection_id] - Globus collection ID associated with token. + * @param {string} [query_params.collection_type] - Type of Globus collection from ["mapped", "ha"]. + * @returns {boolean} - True if the token should be related to a specific Globus collection. + * @throws {Array} - When an invalid combination of `collection_id` and `collection_type` are provided. + */ + static validateRequestParams(query_params) { + const { collection_id, collection_type } = query_params; + let collection_token = false; + if (collection_id || collection_type) { + if (collection_id && collection_type) { + collection_token = true; + } else { + throw [ + g_lib.ERR_INVALID_PARAM, + "/token/get Requires 'collection_id' and 'collection_type' both if one is present, received " + + "collection_id: " + + collection_id + + " collection_type: " + + collection_type, + ]; + } + } + return collection_token; + } + + /** + * @typedef userTokenResponse + * @property {boolean} needs_consent - True if consent flow needs to be triggered, in which case other fields will be undefined + * @property {string} access - Access token + * @property {string} refresh - Refresh token + * @property {number} expires_in - Time until token expiry + * @property {g_lib.AccessTokenType | number} token_type - Type of token retrieved, useful when refreshing tokens + * @property {string} scopes - Scope associated with token, useful when refreshing tokens + */ + /** + * Build response object + * @param {boolean} is_collection_token - Whether the token relates to a collection + * @param {DataFedOAuthToken} token_document - Database document holding relevant token info + * @param {boolean} needs_consent - Whether consent is required + * @returns {userTokenResponse} - Object containing token information, or whether consent flow should start + */ + static formatUserToken(is_collection_token, token_document, needs_consent) { + let result_token = { + needs_consent: needs_consent, + access: "", + refresh: "", + expires_in: 0, + token_type: g_lib.AccessTokenType.ACCESS_SENTINEL, + scopes: "", + }; + if (needs_consent) { + // short circuit when consent flow is required + return result_token; + } + result_token.access = token_document.access; + result_token.refresh = token_document.refresh; + if (token_document.expiration) { + const expires_in = token_document.expiration - Math.floor(Date.now() / 1000); + result_token.expires_in = expires_in > 0 ? expires_in : 0; + } + if (is_collection_token) { + // NOTE: this is only necessary in case of refresh + result_token.token_type = token_document.type; + result_token.scopes = token_document.dependent_scopes; + // NOTE: force consent flow if proper refresh variables are unavailable + result_token.needs_consent = !result_token.token_type || !result_token.scopes; + } else { + result_token.token_type = g_lib.AccessTokenType.GLOBUS_DEFAULT; + } + return result_token; + } + + static formatUserTokenForTransferTask(token_doc) { + const exp_in = token_doc.expiration - Math.floor(Date.now() / 1000); + return Object.freeze({ + acc_tok: token_doc.access, + ref_tok: token_doc.refresh, + acc_tok_exp_in: exp_in > 0 ? exp_in : 0, + }); + } +} + +module.exports = { UserToken }; diff --git a/core/database/foxx/api/metrics_router.js b/core/database/foxx/api/metrics_router.js index 37696e246..0345e1188 100644 --- a/core/database/foxx/api/metrics_router.js +++ b/core/database/foxx/api/metrics_router.js @@ -1,21 +1,23 @@ -'use strict'; +"use strict"; -const createRouter = require('@arangodb/foxx/router'); +const createRouter = require("@arangodb/foxx/router"); const router = createRouter(); -const g_db = require('@arangodb').db; -const g_lib = require('./support'); -const joi = require('joi'); +const g_db = require("@arangodb").db; +const g_lib = require("./support"); +const joi = require("joi"); module.exports = router; -router.post('/msg_count/update', function(req, res) { +router + .post("/msg_count/update", function (req, res) { try { - var i, u, + var i, + u, ts = req.body.timestamp, obj = { timestamp: ts, type: "msgcnt_total", - total: req.body.total + total: req.body.total, }; g_db.metrics.save(obj); @@ -27,7 +29,7 @@ router.post('/msg_count/update', function(req, res) { type: "msgcnt_user", uid: i, total: u.tot, - msg: u.msg + msg: u.msg, }; g_db.metrics.save(obj); } @@ -35,25 +37,26 @@ router.post('/msg_count/update', function(req, res) { g_lib.handleException(e, res); } }) - .body(joi.object().required(), 'Metrics') - .summary('Update message metrics.') - .description('Update message metrics.'); + .body(joi.object().required(), "Metrics") + .summary("Update message metrics.") + .description("Update message metrics."); -router.get('/msg_count', function(req, res) { +router + .get("/msg_count", function (req, res) { try { var par = { now: Date.now() / 1000, - since: 60 * (req.queryParams.since ? req.queryParams.since : 60) + since: 60 * (req.queryParams.since ? req.queryParams.since : 60), }, filter = "(( i.timestamp + @since ) >= @now )"; if (req.queryParams.type) { - filter += " && i.type == @type" + filter += " && i.type == @type"; par.type = req.queryParams.type; } if (req.queryParams.uid) { - filter += " && i.uid == @uid" + filter += " && i.uid == @uid"; par.uid = req.queryParams.uid; } @@ -72,20 +75,31 @@ router.get('/msg_count', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('type', joi.string().optional(), "Metric type (default all)") - .queryParam('since', joi.number().min(0).optional(), "Return since last specified minutes ago (default 60)") - .queryParam('uid', joi.string().optional(), "User ID (default none)") - .summary('Update message metrics.') - .description('Update message metrics.'); - -router.get('/users/active', function(req, res) { + .queryParam("type", joi.string().optional(), "Metric type (default all)") + .queryParam( + "since", + joi.number().min(0).optional(), + "Return since last specified minutes ago (default 60)", + ) + .queryParam("uid", joi.string().optional(), "User ID (default none)") + .summary("Update message metrics.") + .description("Update message metrics."); + +router + .get("/users/active", function (req, res) { try { var cnt = {}, - u, r, qryres = g_db._query( - "for i in metrics filter (( i.timestamp + @since ) >= @now ) && i.type == 'msgcnt_user' return {uid:i.uid,tot:i.total}", { - now: Math.floor(Date.now() / 1000), - since: 60 * (req.queryParams.since ? req.queryParams.since : 15) - }).toArray(); + u, + r, + qryres = g_db + ._query( + "for i in metrics filter (( i.timestamp + @since ) >= @now ) && i.type == 'msgcnt_user' return {uid:i.uid,tot:i.total}", + { + now: Math.floor(Date.now() / 1000), + since: 60 * (req.queryParams.since ? req.queryParams.since : 15), + }, + ) + .toArray(); for (r in qryres) { u = qryres[r]; @@ -101,25 +115,34 @@ router.get('/users/active', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('since', joi.number().min(0).optional(), "Users active since given minutes ago (default 15)") - .summary('Get recently active users from metrics.') - .description('Get recently active users from metrics.'); - -router.post('/purge', function(req, res) { + .queryParam( + "since", + joi.number().min(0).optional(), + "Users active since given minutes ago (default 15)", + ) + .summary("Get recently active users from metrics.") + .description("Get recently active users from metrics."); + +router + .post("/purge", function (req, res) { try { g_db.metrics.save({ timestamp: Math.floor(Date.now() / 1000), type: "purge", - ts: req.queryParams.timestamp + ts: req.queryParams.timestamp, }); g_db._query("for i in metrics filter i.timestamp < @ts remove i in metrics", { - ts: req.queryParams.timestamp + ts: req.queryParams.timestamp, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('timestamp', joi.number().min(0).required(), "Purge all metrics from before timestamp (Unix epoch)") - .summary('Purge older metrics.') - .description('Purge older metrics.'); \ No newline at end of file + .queryParam( + "timestamp", + joi.number().min(0).required(), + "Purge all metrics from before timestamp (Unix epoch)", + ) + .summary("Purge older metrics.") + .description("Purge older metrics."); diff --git a/core/database/foxx/api/models/DataFedOAuthToken.js b/core/database/foxx/api/models/DataFedOAuthToken.js new file mode 100644 index 000000000..4bc289fe2 --- /dev/null +++ b/core/database/foxx/api/models/DataFedOAuthToken.js @@ -0,0 +1,18 @@ +"use strict"; + +/** + * @property {string} [access] - Access token + * @property {string} [refresh] - Refresh token + * @property {number} [expiration] - Exact DataFed server time of expiration + * @property {g_lib.AccessTokenType | number} [type] - Access token type, present when retrieving a collection token + * @property {string} [dependent_scopes] - Access token scopes, present when retrieving a collection token + */ +class DataFedOAuthToken { + static access; + static refresh; + static expiration; + static type; + static dependent_scopes; +} + +module.exports = { DataFedOAuthToken }; diff --git a/core/database/foxx/api/models/globus_collection.js b/core/database/foxx/api/models/globus_collection.js new file mode 100644 index 000000000..2b3355132 --- /dev/null +++ b/core/database/foxx/api/models/globus_collection.js @@ -0,0 +1,103 @@ +"use strict"; + +const support = require("../support"); + +const database = require("@arangodb").db; +const globus_collection_collection = database.globus_coll; + +class GlobusCollection { + static id; + static key; + static name; + static description; + static required_scopes; + static owner; + static creation_time; + static update_time; + static type; + static ha_enabled; +} + +class GlobusCollectionModel { + #globus_collection_uuid; + #exists; + #database_entry; + #is_fetched = false; + /** @type {GlobusCollection} */ + #globus_collection; + + /** Builds model for operations on Globus Collections entity within DataFed Database + * + * @param {string} globus_collection_id - UUID of Globus Collection + */ + constructor(globus_collection_id) { + if (!globus_collection_id) { + throw [support.ERR_MISSING_REQ_PARAM, "A Globus Collection ID must be provided"]; + } + this.#globus_collection_uuid = globus_collection_id; + } + + /** + * @returns {boolean} - Whether database entry exists + */ + exists() { + if (typeof this.#exists === "undefined") { + const query = { _key: this.#globus_collection_uuid }; + this.#exists = !!globus_collection_collection.exists(query); + } + return this.#exists; + } + + /** Gets entry from database and stores in private member + */ + #get_database_entry() { + if (typeof this.#database_entry !== "undefined") { + return; + } + if (this.exists()) { + const query = { _key: this.#globus_collection_uuid }; + this.#database_entry = globus_collection_collection.document(query); + } else { + this.#database_entry = {}; + } + } + + /** Maps database entry to working model + */ + #map_entry_to_globus_collection() { + // TODO: abstract + let globus_collection = new GlobusCollection(); + globus_collection.id = this.#database_entry._id; + globus_collection.key = this.#database_entry._key; + globus_collection.name = this.#database_entry.name; + globus_collection.description = this.#database_entry.description; + globus_collection.required_scopes = this.#database_entry.required_scopes; + globus_collection.owner = this.#database_entry.owner; + globus_collection.creation_time = this.#database_entry.ct; + globus_collection.update_time = this.#database_entry.ut; + globus_collection.type = this.#database_entry.type; + globus_collection.ha_enabled = this.#database_entry.ha_enabled; + this.#globus_collection = globus_collection; + } + + /** Fetches database entry and maps to model(s) if not already present + */ + #fetch_from_db() { + if (!this.#is_fetched) { + this.#get_database_entry(); + this.#map_entry_to_globus_collection(); + this.#is_fetched = true; + } + } + + /** Gets Globus Collection information in read only state. + * Information is cached and will not reflect updates. + * @returns {Readonly} Globus Collection information + */ + get() { + this.#fetch_from_db(); + return Object.freeze(this.#globus_collection); + } +} + +module.exports = { GlobusCollectionModel, GlobusCollection }; diff --git a/core/database/foxx/api/models/globus_token.js b/core/database/foxx/api/models/globus_token.js new file mode 100644 index 000000000..b6286aada --- /dev/null +++ b/core/database/foxx/api/models/globus_token.js @@ -0,0 +1,142 @@ +"use strict"; + +const support = require("../support"); +const { DataFedOAuthToken } = require("./DataFedOAuthToken"); + +const database = require("@arangodb").db; +const globus_token_collection = database.globus_token; + +class GlobusToken { + static id; + static key; + static user_id; + static globus_collection_id; + static type; + static dependent_scopes; + static request_time; + static last_used_time; + static status; + static access; + static refresh; + static expiration; +} + +class GlobusTokenModel { + #user_id; + #collection_id; + #is_fetched = false; + #database_entry; + /** @type {GlobusToken} */ + #globus_token; + /** @type {DataFedOAuthToken} */ + #oauth_token; + + /** Validates necessary fields exist and creates GlobusTokenModel Object + * + * @param {string} user_id - _id field of user document + * @param {string} globus_collection_id - _id field of globus collection document + * @throws {Array} - When either any parameter is not provided + */ + constructor(user_id, globus_collection_id) { + if (!user_id || !globus_collection_id) { + throw [ + support.ERR_MISSING_REQ_PARAM, + "User ID and Collection ID are required for Globus Tokens", + ]; + } + this.#user_id = user_id; + this.#collection_id = globus_collection_id; + } + + /** Gets entry from database and stores in private member + * + * @throws {Array} - If there is more than one entry for user token on a collection + */ + #get_database_entry() { + if (typeof this.#database_entry !== "undefined") { + return; + } + const token_matches = globus_token_collection + .byExample({ + _from: this.#user_id, + _to: this.#collection_id, + }) + .toArray(); + + if (token_matches.length > 0) { + if (token_matches.length > 1) { + throw [ + support.ERR_INTERNAL_FAULT, + "Too many matching tokens for user: " + + this.#user_id + + " to collection: " + + this.#collection_id, + ]; + } + this.#database_entry = token_matches[0]; + } else { + this.#database_entry = {}; + } + } + + /** Maps database entry to working model + */ + #map_entry_to_globus_token() { + // TODO: abstract database objects + let globus_token = new GlobusToken(); + globus_token.id = this.#database_entry._id; + globus_token.key = this.#database_entry._key; + globus_token.user_id = this.#database_entry._from; + globus_token.globus_collection_id = this.#database_entry._to; + globus_token.type = this.#database_entry.type; + globus_token.dependent_scopes = this.#database_entry.dependent_scopes; + globus_token.request_time = this.#database_entry.request_time; + globus_token.last_used_time = this.#database_entry.last_used; + globus_token.status = this.#database_entry.status; + globus_token.access = this.#database_entry.access; + globus_token.refresh = this.#database_entry.refresh; + globus_token.expiration = this.#database_entry.expiration; + this.#globus_token = globus_token; + } + + /** Maps database entry to working OAuth token model + */ + #map_entry_to_oauth_token() { + let oauth_token = new DataFedOAuthToken(); + Object.keys(DataFedOAuthToken).map((key) => { + oauth_token[key] = this.#database_entry[key]; // mapping is currently 1:1 + }); + this.#oauth_token = oauth_token; + } + + /** Fetches database entry and maps to model(s) if not already present + */ + #fetch_from_db() { + if (!this.#is_fetched) { + this.#get_database_entry(); + this.#map_entry_to_globus_token(); + this.#map_entry_to_oauth_token(); + this.#is_fetched = true; + } + } + + /** Gets Globus Token information in read only state. + * + * @returns {Readonly} Globus Token information + */ + get() { + this.#fetch_from_db(); + return Object.freeze(this.#globus_token); + } + + /** Gets correctly typed token for usage with OAuth APIs + * + * @returns {Readonly} Formatted read only OAuth token + */ + get_oauth_token() { + this.#fetch_from_db(); + return Object.freeze(this.#oauth_token); + } +} + +module.exports = { GlobusTokenModel, GlobusToken }; diff --git a/core/database/foxx/api/models/user.js b/core/database/foxx/api/models/user.js new file mode 100644 index 000000000..0c252033b --- /dev/null +++ b/core/database/foxx/api/models/user.js @@ -0,0 +1,156 @@ +"use strict"; + +const support = require("../support"); +const { DataFedOAuthToken } = require("./DataFedOAuthToken"); + +const database = require("@arangodb").db; +const user_collection = database.u; + +class User { + static id; + static key; + static name; + static first_name; + static last_name; + static is_admin; + static maximum_collections; + static maximum_projects; + static maximum_saved_queries; + static creation_time; + static update_time; + static password; + static email; + static options; +} +class UserModel { + #user_id; + #user_key; + #exists; + #database_entry; + #is_fetched = false; + /** @type {User} */ + #user; + /** @type {DataFedOAuthToken} */ + #token; + // mapping specific to DB + #user_database_mapping = { + id: "_id", + key: "_key", + name: "name", + first_name: "first_name", + last_name: "last_name", + is_admin: "is_admin", + maximum_collections: "max_coll", + maximum_projects: "max_proj", + maximum_saved_queries: "max_sav_qry", + creation_time: "ct", + update_time: "ut", + password: "password", + email: "email", + options: "options", + }; + + constructor(id, key) { + if (!id && !key) { + throw [support.ERR_MISSING_REQ_PARAM, "User ID or Key must be provided"]; + } + this.#user_id = id; + this.#user_key = key; + } + + /** Checks database for existence of user + * + * @returns {boolean} Whether or not user exists on database + */ + exists() { + if (typeof this.#exists === "undefined") { + let query = { _id: this.#user_id }; + if (this.#user_key) { + query = { _key: this.#user_key }; + } + this.#exists = !!user_collection.exists(query); + } + return this.#exists; + } + + /** Gets entry from database and stores in private member + */ + #get_database_entry() { + if (typeof this.#database_entry !== "undefined") { + return; + } + if (this.exists()) { + // TODO: abstract database interactions + let query = { _id: this.#user_id }; + if (this.#user_key) { + query = { _key: this.#user_key }; + } + this.#database_entry = user_collection.document(query); + } else { + this.#database_entry = {}; + } + } + + /** Maps database entry to working model + */ + #map_entry_to_user() { + // TODO: abstract database objects + // NOTE: this is specific to current Arango setup + let user = new User(); + Object.entries(this.#user_database_mapping).map(([key, value]) => { + user[key] = this.#database_entry[value]; + }); + this.#user = user; + } + + /** Maps database entry to token model + */ + #map_entry_to_token() { + // TODO: abstract database objects + const { access, refresh, expiration } = this.#database_entry; + let token = new DataFedOAuthToken(); + token.access = access; + token.refresh = refresh; + token.expiration = expiration; + token.type = support.AccessTokenType.GLOBUS_DEFAULT; + token.dependent_scopes = ""; + this.#token = token; + } + + /** Fetches database entry and maps to model(s) if not already present + */ + #fetch_from_db() { + if (!this.#is_fetched) { + this.#get_database_entry(); + this.#map_entry_to_user(); + this.#map_entry_to_token(); + this.#is_fetched = true; + } + } + + /** Gets User information in read only state. + * Note that the database object is retrieved only once and stored. + * @returns {Readonly} User information + */ + get() { + if (!this.#is_fetched) { + this.#fetch_from_db(); + } + return Object.freeze(this.#user); + } + + /** Gets correctly typed token for usage with OAuth APIs + * + * @returns {Readonly} Formatted read only OAuth token + */ + get_token() { + if (!this.#is_fetched) { + this.#fetch_from_db(); + } + return Object.freeze(this.#token); + } + + // TODO: setters +} + +module.exports = { UserModel, User }; diff --git a/core/database/foxx/api/note_router.js b/core/database/foxx/api/note_router.js index 5bda40cde..210bce368 100644 --- a/core/database/foxx/api/note_router.js +++ b/core/database/foxx/api/note_router.js @@ -1,35 +1,42 @@ -'use strict'; +"use strict"; -const createRouter = require('@arangodb/foxx/router'); +const createRouter = require("@arangodb/foxx/router"); const router = createRouter(); -const joi = require('joi'); -const g_db = require('@arangodb').db; -const g_lib = require('./support'); +const joi = require("joi"); +const g_db = require("@arangodb").db; +const g_lib = require("./support"); module.exports = router; - //==================== ACL API FUNCTIONS -router.post('/create', function(req, res) { +router + .post("/create", function (req, res) { console.log("note/create"); try { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn", "d", "c"], - write: ["d", "n", "note"] + write: ["d", "n", "note"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var id = g_lib.resolveDataCollID(req.queryParams.subject, client), doc = g_db._document(id); if (!g_lib.hasAdminPermObject(client, id)) { - if ((g_lib.getPermissions(client, doc, g_lib.PERM_RD_REC) & g_lib.PERM_RD_REC) == 0) { + if ( + (g_lib.getPermissions(client, doc, g_lib.PERM_RD_REC) & + g_lib.PERM_RD_REC) == + 0 + ) { throw g_lib.ERR_PERM_DENIED; } if (req.queryParams.activate) { - throw [g_lib.ERR_PERM_DENIED, "Only owner or admin may create a new annotaion in active state."]; + throw [ + g_lib.ERR_PERM_DENIED, + "Only owner or admin may create a new annotaion in active state.", + ]; } } @@ -40,25 +47,27 @@ router.post('/create', function(req, res) { subject_id: id, ct: time, ut: time, - creator: client._id + creator: client._id, }, updates = {}; g_lib.procInputParam(req.queryParams, "title", false, obj); - obj.comments = [{ - user: client._id, - new_type: obj.type, - new_state: obj.state, - time: time - }]; + obj.comments = [ + { + user: client._id, + new_type: obj.type, + new_state: obj.state, + time: time, + }, + ]; g_lib.procInputParam(req.queryParams, "comment", false, obj.comments[0]); var note = g_db.n.save(obj, { - returnNew: true + returnNew: true, }); g_db.note.save({ _from: id, - _to: note._id + _to: note._id, }); // For ACTIVE errors and warnings, propagate to direct children @@ -74,44 +83,54 @@ router.post('/create', function(req, res) { res.send({ results: [note.new], - updates: Object.values(updates) + updates: Object.values(updates), }); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client UID") - .queryParam('subject', joi.string().required(), "ID or alias of data record or collection") - .queryParam('type', joi.number().min(0).max(3).required(), "Type of annotation (see SDMS.proto for NOTE_TYPE enum)") - .queryParam('title', joi.string().required(), "Title of annotaion") - .queryParam('comment', joi.string().required(), "Comments") - .queryParam('activate', joi.boolean().optional(), "Make new annotation active on create") - .summary('Create an annotation on an object') - .description('Create an annotation on an object'); - - -router.post('/update', function(req, res) { + .queryParam("client", joi.string().required(), "Client UID") + .queryParam("subject", joi.string().required(), "ID or alias of data record or collection") + .queryParam( + "type", + joi.number().min(0).max(3).required(), + "Type of annotation (see SDMS.proto for NOTE_TYPE enum)", + ) + .queryParam("title", joi.string().required(), "Title of annotaion") + .queryParam("comment", joi.string().required(), "Comments") + .queryParam("activate", joi.boolean().optional(), "Make new annotation active on create") + .summary("Create an annotation on an object") + .description("Create an annotation on an object"); + +router + .post("/update", function (req, res) { console.log("note/update"); try { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn"], - write: ["d", "n", "note"] + write: ["d", "n", "note"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); if (!req.queryParams.id.startsWith("n/")) - throw [g_lib.ERR_INVALID_PARAM, "Invalid annotaion ID '" + req.queryParams.id + "'"]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Invalid annotaion ID '" + req.queryParams.id + "'", + ]; if (!g_db._exists(req.queryParams.id)) - throw [g_lib.ERR_INVALID_PARAM, "Annotaion ID '" + req.queryParams.id + "' does not exist."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Annotaion ID '" + req.queryParams.id + "' does not exist.", + ]; var note = g_db.n.document(req.queryParams.id), ne = g_db.note.firstExample({ - _to: note._id + _to: note._id, }), old_state = note.state, old_type = note.type, @@ -134,9 +153,13 @@ router.post('/update', function(req, res) { if (!g_lib.hasAdminPermObject(client, ne._from)) { if (client._id == note.creator) { - if ((note.state == g_lib.NOTE_ACTIVE && (req.queryParams.new_state != undefined || - req.queryParams.new_type != undefined || req.queryParams.title != undefined)) || - req.queryParams.new_state == g_lib.NOTE_ACTIVE) { + if ( + (note.state == g_lib.NOTE_ACTIVE && + (req.queryParams.new_state != undefined || + req.queryParams.new_type != undefined || + req.queryParams.title != undefined)) || + req.queryParams.new_state == g_lib.NOTE_ACTIVE + ) { throw g_lib.ERR_PERM_DENIED; } } else { @@ -147,11 +170,11 @@ router.post('/update', function(req, res) { var time = Math.floor(Date.now() / 1000), obj = { ut: time, - comments: note.comments + comments: note.comments, }, comment = { user: client._id, - time: time + time: time, }; if (req.queryParams.new_type !== undefined) { @@ -173,15 +196,25 @@ router.post('/update', function(req, res) { obj.comments.push(comment); note = g_db.n.update(note._id, obj, { - returnNew: true + returnNew: true, }).new; // If this is an error or warning, must assess impact to dependent records (derived/component only) - if (g_db.note.byExample({ - _to: note._id - }).count() > 1) { + if ( + g_db.note + .byExample({ + _to: note._id, + }) + .count() > 1 + ) { //console.log("update existing dependent notes"); - g_lib.annotationUpdateDependents(client, note, old_type, old_state, updates); + g_lib.annotationUpdateDependents( + client, + note, + old_type, + old_state, + updates, + ); } else if (note.state == g_lib.NOTE_ACTIVE && note.type >= g_lib.NOTE_WARN) { //console.log("init new dependent notes"); g_lib.annotationInitDependents(client, note, updates); @@ -195,39 +228,49 @@ router.post('/update', function(req, res) { res.send({ results: [note], - updates: Object.values(updates) + updates: Object.values(updates), }); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client UID") - .queryParam('id', joi.string().required(), "ID of annotation") - .queryParam('new_type', joi.number().min(0).max(3).optional(), "Type of annotation (see SDMS.proto for NOTE_TYPE enum)") - .queryParam('new_state', joi.number().min(0).max(2).optional(), "New state (omit for comment)") - .queryParam('new_title', joi.string().optional(), "New title") - .queryParam('comment', joi.string().required(), "Comments") - .summary('Update an annotation') - .description('Update an annotation with new comment and optional new state'); - - -router.post('/comment/edit', function(req, res) { + .queryParam("client", joi.string().required(), "Client UID") + .queryParam("id", joi.string().required(), "ID of annotation") + .queryParam( + "new_type", + joi.number().min(0).max(3).optional(), + "Type of annotation (see SDMS.proto for NOTE_TYPE enum)", + ) + .queryParam("new_state", joi.number().min(0).max(2).optional(), "New state (omit for comment)") + .queryParam("new_title", joi.string().optional(), "New title") + .queryParam("comment", joi.string().required(), "Comments") + .summary("Update an annotation") + .description("Update an annotation with new comment and optional new state"); + +router + .post("/comment/edit", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn"], - write: ["n"] + write: ["n"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); if (!req.queryParams.id.startsWith("n/")) - throw [g_lib.ERR_INVALID_PARAM, "Invalid annotaion ID '" + req.queryParams.id + "'"]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Invalid annotaion ID '" + req.queryParams.id + "'", + ]; if (!g_db._exists(req.queryParams.id)) - throw [g_lib.ERR_INVALID_PARAM, "Annotaion ID '" + req.queryParams.id + "' does not exist."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Annotaion ID '" + req.queryParams.id + "' does not exist.", + ]; var note = g_db.n.document(req.queryParams.id); @@ -235,7 +278,7 @@ router.post('/comment/edit', function(req, res) { throw [g_lib.ERR_INVALID_PARAM, "Comment index out of range."]; var obj = { - ut: Math.floor(Date.now() / 1000) + ut: Math.floor(Date.now() / 1000), }, comment = note.comments[req.queryParams.comment_idx]; @@ -249,41 +292,47 @@ router.post('/comment/edit', function(req, res) { } note = g_db.n.update(note._id, obj, { - returnNew: true + returnNew: true, }); res.send({ - results: [note.new] + results: [note.new], }); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client UID") - .queryParam('id', joi.string().required(), "ID of annotation") - .queryParam('comment', joi.string().required(), "New description / comments") - .queryParam('comment_idx', joi.number().min(0).required(), "Comment index number to edit") - .summary('Edit an annotation comment') - .description('Edit a specific comment within an annotation.'); - - -router.get('/view', function(req, res) { + .queryParam("client", joi.string().required(), "Client UID") + .queryParam("id", joi.string().required(), "ID of annotation") + .queryParam("comment", joi.string().required(), "New description / comments") + .queryParam("comment_idx", joi.number().min(0).required(), "Comment index number to edit") + .summary("Edit an annotation comment") + .description("Edit a specific comment within an annotation."); + +router + .get("/view", function (req, res) { try { const client = g_lib.getUserFromClientID_noexcept(req.queryParams.client); if (!req.queryParams.id.startsWith("n/")) - throw [g_lib.ERR_INVALID_PARAM, "Invalid annotaion ID '" + req.queryParams.id + "'"]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Invalid annotaion ID '" + req.queryParams.id + "'", + ]; if (!g_db._exists(req.queryParams.id)) - throw [g_lib.ERR_INVALID_PARAM, "Annotaion ID '" + req.queryParams.id + "' does not exist."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Annotaion ID '" + req.queryParams.id + "' does not exist.", + ]; var note = g_db.n.document(req.queryParams.id); if (!client || client._id != note.creator) { var ne = g_db.note.firstExample({ - _to: note._id + _to: note._id, }); if (!client || !g_lib.hasAdminPermObject(client, ne._from)) { if (note.state == g_lib.NOTE_ACTIVE) { @@ -293,7 +342,11 @@ router.get('/view', function(req, res) { if (!g_lib.hasPublicRead(doc._id)) { throw g_lib.ERR_PERM_DENIED; } - } else if ((g_lib.getPermissions(client, doc, g_lib.PERM_RD_REC) & g_lib.PERM_RD_REC) == 0) { + } else if ( + (g_lib.getPermissions(client, doc, g_lib.PERM_RD_REC) & + g_lib.PERM_RD_REC) == + 0 + ) { throw g_lib.ERR_PERM_DENIED; } } else { @@ -302,85 +355,101 @@ router.get('/view', function(req, res) { } } - if (g_db.note.byExample({ - _to: note._id - }).count() > 1) + if ( + g_db.note + .byExample({ + _to: note._id, + }) + .count() > 1 + ) note.has_child = true; res.send({ - results: [note] + results: [note], }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client UID") - .queryParam('id', joi.string().required(), "ID of annotation") - .summary('View annotation') - .description('View annotation'); - + .queryParam("client", joi.string().required(), "Client UID") + .queryParam("id", joi.string().required(), "ID of annotation") + .summary("View annotation") + .description("View annotation"); -router.get('/list/by_subject', function(req, res) { +router + .get("/list/by_subject", function (req, res) { try { const client = g_lib.getUserFromClientID_noexcept(req.queryParams.client); - var results, qry, id = g_lib.resolveDataCollID(req.queryParams.subject, client); + var results, + qry, + id = g_lib.resolveDataCollID(req.queryParams.subject, client); if (!client) { - qry = "for v in 1..1 outbound @subj note filter v.state == 2 sort v.ut desc return {_id:v._id,state:v.state,type:v.type,subject_id:v.subject_id,title:v.title,creator:v.creator,parent_id:v.parent_id,ct:v.ct,ut:v.ut}"; + qry = + "for v in 1..1 outbound @subj note filter v.state == 2 sort v.ut desc return {_id:v._id,state:v.state,type:v.type,subject_id:v.subject_id,title:v.title,creator:v.creator,parent_id:v.parent_id,ct:v.ct,ut:v.ut}"; results = g_db._query(qry, { - subj: id + subj: id, }); } else if (g_lib.hasAdminPermObject(client, id)) { - qry = "for v in 1..1 outbound @subj note sort v.ut desc return {_id:v._id,state:v.state,type:v.type,subject_id:v.subject_id,title:v.title,creator:v.creator,parent_id:v.parent_id,ct:v.ct,ut:v.ut}"; + qry = + "for v in 1..1 outbound @subj note sort v.ut desc return {_id:v._id,state:v.state,type:v.type,subject_id:v.subject_id,title:v.title,creator:v.creator,parent_id:v.parent_id,ct:v.ct,ut:v.ut}"; results = g_db._query(qry, { - subj: id + subj: id, }); } else { - qry = "for v in 1..1 outbound @subj note filter v.state == 2 || v.creator == @client sort v.ut desc return {_id:v._id,state:v.state,type:v.type,subject_id:v.subject_id,title:v.title,creator:v.creator,parent_id:v.parent_id,ct:v.ct,ut:v.ut}"; + qry = + "for v in 1..1 outbound @subj note filter v.state == 2 || v.creator == @client sort v.ut desc return {_id:v._id,state:v.state,type:v.type,subject_id:v.subject_id,title:v.title,creator:v.creator,parent_id:v.parent_id,ct:v.ct,ut:v.ut}"; results = g_db._query(qry, { subj: id, - client: client._id + client: client._id, }); } res.send({ - results: results.toArray() + results: results.toArray(), }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client UID") - .queryParam('subject', joi.string().required(), "ID/alias of subject") - .summary('List annotations by subject') - .description('List annotations attached to subject data record or colelction'); - + .queryParam("client", joi.string().required(), "Client UID") + .queryParam("subject", joi.string().required(), "ID/alias of subject") + .summary("List annotations by subject") + .description("List annotations attached to subject data record or colelction"); -router.get('/purge', function(req, res) { +router + .get("/purge", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn"], - write: ["n", "note"] + write: ["n", "note"], }, - action: function() { + action: function () { //console.log("note purge, age:", req.queryParams.age_sec ); - var t = (Date.now() / 1000) - req.queryParams.age_sec; - var id, notes = g_db._query("for i in n filter i.state == " + g_lib.NOTE_CLOSED + " && i.ut < " + t + " and i.parent_id == null return i._id"); + var t = Date.now() / 1000 - req.queryParams.age_sec; + var id, + notes = g_db._query( + "for i in n filter i.state == " + + g_lib.NOTE_CLOSED + + " && i.ut < " + + t + + " and i.parent_id == null return i._id", + ); while (notes.hasNext()) { id = notes.next(); console.log("purging", id); // This will also delete all dependent annotations g_lib.annotationDelete(id); } - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('age_sec', joi.number().integer().min(0).required(), "Purge age (seconds)") - .summary('Purge old closed annotations') - .description('Purge old closed annotations'); \ No newline at end of file + .queryParam("age_sec", joi.number().integer().min(0).required(), "Purge age (seconds)") + .summary("Purge old closed annotations") + .description("Purge old closed annotations"); diff --git a/core/database/foxx/api/posix_path.js b/core/database/foxx/api/posix_path.js new file mode 100644 index 000000000..f171b1d8b --- /dev/null +++ b/core/database/foxx/api/posix_path.js @@ -0,0 +1,49 @@ +"use strict"; + +const path = require("path"); + +module.exports = (function () { + let obj = {}; + + /** + * Splits a POSIX path string into its components. + * + * @param {string} a_posix_path - The POSIX path to be split. + * + * @returns {string[]} An array of path components. + * + * @throws {Error} If the provided path is not a valid string. + * + * @example + * // Input: + * const posixPath = '/usr/local/bin/node'; + * + * // Execution: + * const splitPath = splitPOSIXPath(posixPath); + * console.log(splitPath); + * + * // Output: + * ['usr', 'local', 'bin', 'node'] + */ + obj.splitPOSIXPath = function (a_posix_path) { + if (!a_posix_path) { + throw new Error("Invalid POSIX path"); + } else if (typeof a_posix_path !== "string") { + throw new Error( + "Invalid POSIX path type: ", + typeof a_posix_path, + " path content: ", + a_posix_path, + ); + } + // Split the path into components + // components: ['', 'usr', 'local', 'bin', 'node'] + // The empty '' is for root + const components = a_posix_path.split(path.posix.sep); + + // components: ['usr', 'local', 'bin', 'node'] + return components.filter((component) => component !== ""); + }; + + return obj; +})(); diff --git a/core/database/foxx/api/process.js b/core/database/foxx/api/process.js index 0ea2c8965..c989f0a57 100644 --- a/core/database/foxx/api/process.js +++ b/core/database/foxx/api/process.js @@ -1,26 +1,58 @@ -'use strict'; +"use strict"; -const g_db = require('@arangodb').db; -const g_lib = require('./support'); +const g_db = require("@arangodb").db; +const g_lib = require("./support"); -module.exports = (function() { +module.exports = (function () { var obj = {}; - /** @brief Pre-process data/collection IDs for permissions and required data + /** + * @function + * Pre-processes data and collection IDs for permissions and required data. + * + * This function examines the specified data and collections for the appropriate permissions + * based on the given mode and recursively processes items (data/collections) in included collections. + * It does not resolve IDs. On success, it returns lists of data records for Globus and external data, + * as well as records without data. Additionally, it returns a flat list of all collections. + * + * In delete mode, only data that is not linked elsewhere will be returned for data records within collections. + * + * @param {object} a_client - The client object containing the client ID and admin status. + * @param {string} a_client._id - The unique identifier of the client. + * @param {boolean} a_client.is_admin - A flag indicating if the client is an administrator. + * @param {string} a_new_owner_id - The ID of the new owner to assign. + * @param {Array} a_ids - An array of data and collection IDs to process. + * @param {string} a_mode - The mode in which the operation is being performed. It can be one of the following: + * - `g_lib.TT_DATA_GET`: Read data permissions. + * - `g_lib.TT_DATA_PUT`: Write data permissions. + * - `g_lib.TT_REC_ALLOC_CHG`: Allocate/change record permissions. + * - `g_lib.TT_REC_OWNER_CHG`: Change record owner permissions. + * - `g_lib.TT_REC_DEL`: Delete record permissions. + * - `g_lib.TT_DATA_EXPORT`: Export data permissions. + * + * @returns {object} ctxt - An object containing the following properties: + * - `client`: The client information. + * - `new_owner`: The ID of the new owner. + * - `mode`: The mode for the operation. + * - `coll_perm`: The collection permission level. + * - `data_perm`: The data permission level. + * - `coll`: A list of collections. + * - `glob_data`: A list of Globus data records. + * - `ext_data`: A list of external data records. + * - `visited`: A record of visited items during recursion. * - * Examine data and collections for proper permissions for the given mode and - * recursively process items (data/collections) in included collections. Does - * not resolve IDs. On success, returns lists of data records for globus and - * external data, as well as records without data. Also returns a flat list of - * all collections. In delete mode, for data records in collections, only data - * that isn't linked elsewhere are returned. + * @throws {Error} g_lib.ERR_INVALID_MODE - If an invalid mode is passed. + * + * @example + * const result = obj.preprocessItems(client, newOwnerId, dataIds, g_lib.TT_DATA_GET); + * console.log(result.glob_data); */ - obj.preprocessItems = function(a_client, a_new_owner_id, a_ids, a_mode) { + obj.preprocessItems = function (a_client, a_new_owner_id, a_ids, a_mode) { //console.log( "preprocessItems start" ); var ctxt = { client: { _id: a_client._id, - is_admin: a_client.is_admin + is_admin: a_client.is_admin, }, new_owner: a_new_owner_id, mode: a_mode, @@ -30,7 +62,7 @@ module.exports = (function() { coll: [], glob_data: [], ext_data: [], - visited: {} + visited: {}, }; switch (a_mode) { @@ -72,7 +104,9 @@ module.exports = (function() { // For deletion, must further process data records to determine if they // are to be deleted or not (if they are linked elsewhere) if (a_mode == g_lib.TT_REC_DEL) { - var cnt, data, remove = []; + var cnt, + data, + remove = []; for (i in ctxt.ext_data) { data = ctxt.ext_data[i]; @@ -109,21 +143,23 @@ module.exports = (function() { return ctxt; }; - /** - * @brief Recursive preprocessing of data/collections for data operations - * @param a_ctxt - Recursion context object - * @param a_ids - Current list of data/collection IDs to process - * @param a_perm - Inherited permission (undefined initially) - * - * This function pre-processes with optimized permission verification by - * using a depth-first analysis of collections. If the required permission - * is satisfied via inherited ACLs, then no further permission checks are - * required below that point. The end result is a flat list of collections - * and data segregated into those with Globus data (regardless of data - * size) and those with external data. + * Recursively preprocesses data and collections for data operations. + * + * This function performs a depth-first analysis of collections, verifying permissions. + * It ensures that if the required permission is satisfied via inherited ACLs, no further + * permission checks are needed below that point. The function segregates collections and + * data into two categories: those with Globus data (regardless of data size) and those + * with external data. The final result is a flat list of collections and data. + * + * @param {object} a_ctxt - The recursion context object, containing relevant state such as permissions and mode. + * @param {Array} a_ids - The current list of data/collection IDs to process. + * @param {number} [a_data_perm] - The inherited data permission (undefined initially). + * @param {number} [a_coll_perm] - The inherited collection permission (undefined initially). + * + * @throws {Array} Throws error with permission or parameter issues. */ - obj._preprocessItemsRecursive = function(a_ctxt, a_ids, a_data_perm, a_coll_perm) { + obj._preprocessItemsRecursive = function (a_ctxt, a_ids, a_data_perm, a_coll_perm) { var i, id, ids, is_coll, doc, perm, ok, data_perm, coll_perm; for (i in a_ids) { @@ -131,9 +167,12 @@ module.exports = (function() { //console.log( "preprocessItem", id ); - if (id.charAt(0) == 'c') { + if (id.charAt(0) == "c") { if (a_ctxt.mode == g_lib.TT_DATA_PUT) - throw [g_lib.ERR_INVALID_PARAM, "Collections not supported for PUT operations."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Collections not supported for PUT operations.", + ]; is_coll = true; } else { is_coll = false; @@ -144,30 +183,31 @@ module.exports = (function() { if (id in a_ctxt.visited) { if (a_ctxt.mode == g_lib.TT_REC_DEL) { var cnt = a_ctxt.visited[id]; - if (cnt != -1) - a_ctxt.visited[id] = cnt + 1; + if (cnt != -1) a_ctxt.visited[id] = cnt + 1; } continue; } else { // NOTE: a_data_perm is null, then this indicates a record has been specified explicitly, which // is indicated with a cnt of -1 (and will be deleted regardless of other collection links) - a_ctxt.visited[id] = (a_data_perm == null ? -1 : 1); + a_ctxt.visited[id] = a_data_perm == null ? -1 : 1; } } if (!g_db._exists(id)) - throw [g_lib.ERR_INVALID_PARAM, (is_coll ? "Collection '" : "Data record '") + id + "' does not exist."]; + throw [ + g_lib.ERR_INVALID_PARAM, + (is_coll ? "Collection '" : "Data record '") + id + "' does not exist.", + ]; doc = g_db._document(id); - if (doc.public) - a_ctxt.has_pub = true; + if (doc.public) a_ctxt.has_pub = true; // Check permissions if (is_coll) { - data_perm = (a_data_perm == null ? 0 : a_data_perm); - coll_perm = (a_coll_perm == null ? 0 : a_coll_perm); + data_perm = a_data_perm == null ? 0 : a_data_perm; + coll_perm = a_coll_perm == null ? 0 : a_coll_perm; // Make sure user isn't trying to delete root if (doc.is_root && a_ctxt.mode == g_lib.TT_REC_DEL) @@ -178,15 +218,21 @@ module.exports = (function() { permissions. Local ACLs could apply additional inherited permissions.*/ - if (((coll_perm & a_ctxt.coll_perm) != a_ctxt.coll_perm) || - ((data_perm & a_ctxt.data_perm) != a_ctxt.data_perm)) { - + if ( + (coll_perm & a_ctxt.coll_perm) != a_ctxt.coll_perm || + (data_perm & a_ctxt.data_perm) != a_ctxt.data_perm + ) { if (!g_lib.hasAdminPermObjectLoaded(a_ctxt.client, doc)) { - - if (a_coll_perm != null) // Already have inherited permission, don't ask again + if (a_coll_perm != null) + // Already have inherited permission, don't ask again perm = g_lib.getPermissionsLocal(a_ctxt.client._id, doc); else - perm = g_lib.getPermissionsLocal(a_ctxt.client._id, doc, true, a_ctxt.comb_perm); + perm = g_lib.getPermissionsLocal( + a_ctxt.client._id, + doc, + true, + a_ctxt.comb_perm, + ); /* Note: collection inherit-grant permissions do not apply to the collection itself - only to items linked beneath the collection. Thus permission checks at this point should only @@ -194,13 +240,16 @@ module.exports = (function() { is available in perm.inherited) */ - if (((perm.grant | perm.inherited) & a_ctxt.coll_perm) != a_ctxt.coll_perm) { + if ( + ((perm.grant | perm.inherited) & a_ctxt.coll_perm) != + a_ctxt.coll_perm + ) { throw [g_lib.ERR_PERM_DENIED, "Permission denied for collection " + id]; } // inherited and inhgrant perms only apply to recursion - data_perm |= (perm.inhgrant | perm.inherited); - coll_perm |= (perm.inhgrant | perm.inherited); + data_perm |= perm.inhgrant | perm.inherited; + coll_perm |= perm.inhgrant | perm.inherited; } else { data_perm = a_ctxt.data_perm; coll_perm = a_ctxt.coll_perm; @@ -208,9 +257,11 @@ module.exports = (function() { } a_ctxt.coll.push(id); - ids = g_db._query("for v in 1..1 outbound @coll item return v._id", { - coll: id - }).toArray(); + ids = g_db + ._query("for v in 1..1 outbound @coll item return v._id", { + coll: id, + }) + .toArray(); obj._preprocessItemsRecursive(a_ctxt, ids, data_perm, coll_perm); } else { // Data record @@ -224,17 +275,27 @@ module.exports = (function() { // Put project ID in visited to avoid checking permissions again a_ctxt.visited[doc.owner] = 1; } else { - throw [g_lib.ERR_PERM_DENIED, "Permission denied for data record " + id]; + throw [ + g_lib.ERR_PERM_DENIED, + "Permission denied for data record " + id, + ]; } } } else { - throw [g_lib.ERR_PERM_DENIED, "Permission denied for data record " + id]; + throw [ + g_lib.ERR_PERM_DENIED, + "Permission denied for data record " + id, + ]; } } } else if (a_ctxt.mode == g_lib.TT_REC_OWNER_CHG) { // Must be data owner or creator OR if owned by a project, the project or // an admin. - if (doc.owner != a_ctxt.client._id && doc.creator != a_ctxt.client._id && !a_ctxt.client.is_admin) { + if ( + doc.owner != a_ctxt.client._id && + doc.creator != a_ctxt.client._id && + !a_ctxt.client.is_admin + ) { ok = false; if (doc.owner.startsWith("p/")) { @@ -250,25 +311,49 @@ module.exports = (function() { } if (!ok && (a_data_perm & a_ctxt.data_perm) != a_ctxt.data_perm) { - if (a_data_perm != null) // Already have inherited permission, don't ask again + if (a_data_perm != null) + // Already have inherited permission, don't ask again perm = g_lib.getPermissionsLocal(a_ctxt.client._id, doc); else - perm = g_lib.getPermissionsLocal(a_ctxt.client._id, doc, true, a_ctxt.data_perm); - - if (((perm.grant | perm.inherited) & a_ctxt.data_perm) != a_ctxt.data_perm) - throw [g_lib.ERR_PERM_DENIED, "Permission denied for data record " + id]; + perm = g_lib.getPermissionsLocal( + a_ctxt.client._id, + doc, + true, + a_ctxt.data_perm, + ); + + if ( + ((perm.grant | perm.inherited) & a_ctxt.data_perm) != + a_ctxt.data_perm + ) + throw [ + g_lib.ERR_PERM_DENIED, + "Permission denied for data record " + id, + ]; } } } else { if ((a_data_perm & a_ctxt.data_perm) != a_ctxt.data_perm) { if (!g_lib.hasAdminPermObjectLoaded(a_ctxt.client, doc)) { - if (a_data_perm != null) // Already have inherited permission, don't ask again + if (a_data_perm != null) + // Already have inherited permission, don't ask again perm = g_lib.getPermissionsLocal(a_ctxt.client._id, doc); else - perm = g_lib.getPermissionsLocal(a_ctxt.client._id, doc, true, a_ctxt.data_perm); - - if (((perm.grant | perm.inherited) & a_ctxt.data_perm) != a_ctxt.data_perm) { - throw [g_lib.ERR_PERM_DENIED, "Permission denied for data record " + id]; + perm = g_lib.getPermissionsLocal( + a_ctxt.client._id, + doc, + true, + a_ctxt.data_perm, + ); + + if ( + ((perm.grant | perm.inherited) & a_ctxt.data_perm) != + a_ctxt.data_perm + ) { + throw [ + g_lib.ERR_PERM_DENIED, + "Permission denied for data record " + id, + ]; } } } @@ -276,7 +361,10 @@ module.exports = (function() { if (doc.external) { if (a_ctxt.mode == g_lib.TT_DATA_PUT) - throw [g_lib.ERR_INVALID_PARAM, "Cannot upload to external data on record '" + doc.id + "'."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Cannot upload to external data on record '" + doc.id + "'.", + ]; a_ctxt.ext_data.push({ _id: id, @@ -285,7 +373,7 @@ module.exports = (function() { owner: doc.owner, size: doc.size, source: doc.source, - ext: doc.ext + ext: doc.ext, }); } else if (a_ctxt.mode != g_lib.TT_DATA_GET || doc.size) { a_ctxt.glob_data.push({ @@ -295,28 +383,32 @@ module.exports = (function() { owner: doc.owner, size: doc.size, source: doc.source, - ext: doc.ext + ext: doc.ext, }); } } } }; - obj._processTaskDeps = function(a_task_id, a_ids, a_lock_lev, a_owner_lock_lev, a_context) { - var i, id, lock, locks, block = new Set(), - owner, owners = new Set(); + obj._processTaskDeps = function (a_task_id, a_ids, a_lock_lev, a_owner_lock_lev, a_context) { + var i, + id, + lock, + locks, + block = new Set(), + owner, + owners = new Set(); for (i in a_ids) { id = a_ids[i]; owner = g_db.owner.firstExample({ - _from: id + _from: id, }); - if (owner) - owners.add(owner._to); + if (owner) owners.add(owner._to); // Gather other tasks with priority over this new one locks = g_db.lock.byExample({ - _to: id + _to: id, }); while (locks.hasNext()) { lock = locks.next(); @@ -333,19 +425,19 @@ module.exports = (function() { _from: a_task_id, _to: id, level: a_lock_lev, - context: a_context + context: a_context, }); else g_db.lock.save({ _from: a_task_id, _to: id, - level: a_lock_lev + level: a_lock_lev, }); } - owners.forEach(function(owner_id) { + owners.forEach(function (owner_id) { locks = g_db.lock.byExample({ - _to: owner_id + _to: owner_id, }); while (locks.hasNext()) { lock = locks.next(); @@ -361,21 +453,21 @@ module.exports = (function() { _from: a_task_id, _to: owner_id, level: a_owner_lock_lev, - context: a_context + context: a_context, }); else g_db.lock.save({ _from: a_task_id, _to: owner_id, - level: a_owner_lock_lev + level: a_owner_lock_lev, }); }); if (block.size) { - block.forEach(function(val) { + block.forEach(function (val) { g_db.block.save({ _from: a_task_id, - _to: val + _to: val, }); }); @@ -384,15 +476,18 @@ module.exports = (function() { return false; }; - - obj._lockDepsGeneral = function(a_task_id, a_deps) { - var i, dep, lock, locks, block = new Set(); + obj._lockDepsGeneral = function (a_task_id, a_deps) { + var i, + dep, + lock, + locks, + block = new Set(); for (i in a_deps) { dep = a_deps[i]; // Gather other tasks with priority over this new one locks = g_db.lock.byExample({ - _to: dep.id + _to: dep.id, }); while (locks.hasNext()) { lock = locks.next(); @@ -409,21 +504,21 @@ module.exports = (function() { _from: a_task_id, _to: dep.id, level: dep.lev, - context: dep.ctx + context: dep.ctx, }); else g_db.lock.save({ _from: a_task_id, _to: dep.id, - level: dep.lev + level: dep.lev, }); } if (block.size) { - block.forEach(function(val) { + block.forEach(function (val) { g_db.block.save({ _from: a_task_id, - _to: val + _to: val, }); }); @@ -433,4 +528,4 @@ module.exports = (function() { }; return obj; -}()); \ No newline at end of file +})(); diff --git a/core/database/foxx/api/proj_router.js b/core/database/foxx/api/proj_router.js index f2ab7fef7..0dfb1674b 100644 --- a/core/database/foxx/api/proj_router.js +++ b/core/database/foxx/api/proj_router.js @@ -1,44 +1,73 @@ -'use strict'; +"use strict"; -const createRouter = require('@arangodb/foxx/router'); +const createRouter = require("@arangodb/foxx/router"); const router = createRouter(); -const joi = require('joi'); +const joi = require("joi"); -const g_db = require('@arangodb').db; -const g_lib = require('./support'); -const g_tasks = require('./tasks'); +const g_db = require("@arangodb").db; +const g_lib = require("./support"); +const g_tasks = require("./tasks"); module.exports = router; //==================== PROJECT API FUNCTIONS - -router.get('/create', function(req, res) { +router + .get("/create", function (req, res) { try { var result; g_db._executeTransaction({ collections: { read: ["u", "p"], - write: ["p", "c", "a", "g", "acl", "owner", "ident", "alias", "admin", "member"] + write: [ + "p", + "c", + "a", + "g", + "acl", + "owner", + "ident", + "alias", + "admin", + "member", + ], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); // Must be a repo admin to create a project - var repos = g_db._query("for v in 1..1 inbound @user admin filter is_same_collection('repo',v) limit 1 return v._key", { - user: client._id - }).toArray(); + var repos = g_db + ._query( + "for v in 1..1 inbound @user admin filter is_same_collection('repo',v) limit 1 return v._key", + { + user: client._id, + }, + ) + .toArray(); if (repos.length == 0) - throw [g_lib.ERR_PERM_DENIED, "Projects can only be created by repository administrators."]; + throw [ + g_lib.ERR_PERM_DENIED, + "Projects can only be created by repository administrators.", + ]; // Enforce project limit if set if (client.max_proj >= 0) { - var count = g_db._query("return length(FOR i IN owner FILTER i._to == @id and is_same_collection('p',i._from) RETURN 1)", { - id: client._id - }).next(); + var count = g_db + ._query( + "return length(FOR i IN owner FILTER i._to == @id and is_same_collection('p',i._from) RETURN 1)", + { + id: client._id, + }, + ) + .next(); if (count >= client.max_proj) - throw [g_lib.ERR_ALLOCATION_EXCEEDED, "Project limit reached (" + client.max_proj + "). Contact system administrator to increase limit."]; + throw [ + g_lib.ERR_ALLOCATION_EXCEEDED, + "Project limit reached (" + + client.max_proj + + "). Contact system administrator to increase limit.", + ]; } var time = Math.floor(Date.now() / 1000); @@ -46,7 +75,7 @@ router.get('/create', function(req, res) { owner: client._id, max_coll: g_lib.DEF_MAX_COLL, ct: time, - ut: time + ut: time, }; g_lib.procInputParam(req.queryParams, "id", false, proj_data); // Sets _key field @@ -54,65 +83,74 @@ router.get('/create', function(req, res) { g_lib.procInputParam(req.queryParams, "desc", false, proj_data); var proj = g_db.p.save(proj_data, { - returnNew: true + returnNew: true, }); g_db.owner.save({ _from: proj._id, - _to: client._id - }); - - var root = g_db.c.save({ - _key: "p_" + proj_data._key + "_root", - is_root: true, - owner: proj._id, - title: "Root Collection", - desc: "Root collection for project " + proj_data._key, - alias: "root", - acls: 2 - }, { - returnNew: true + _to: client._id, }); - var alias = g_db.a.save({ - _key: "p:" + proj_data._key + ":root" - }, { - returnNew: true - }); + var root = g_db.c.save( + { + _key: "p_" + proj_data._key + "_root", + is_root: true, + owner: proj._id, + title: "Root Collection", + desc: "Root collection for project " + proj_data._key, + alias: "root", + acls: 2, + }, + { + returnNew: true, + }, + ); + + var alias = g_db.a.save( + { + _key: "p:" + proj_data._key + ":root", + }, + { + returnNew: true, + }, + ); g_db.owner.save({ _from: alias._id, - _to: proj._id + _to: proj._id, }); g_db.alias.save({ _from: root._id, - _to: alias._id + _to: alias._id, }); g_db.owner.save({ _from: root._id, - _to: proj._id + _to: proj._id, }); var i; var mem_grp; // Projects have a special "members" group associated with root - mem_grp = g_db.g.save({ - uid: "p/" + proj_data._key, - gid: "members", - title: "Project Members", - desc: "Use to set baseline project member permissions." - }, { - returnNew: true - }); + mem_grp = g_db.g.save( + { + uid: "p/" + proj_data._key, + gid: "members", + title: "Project Members", + desc: "Use to set baseline project member permissions.", + }, + { + returnNew: true, + }, + ); g_db.owner.save({ _from: mem_grp._id, - _to: proj._id + _to: proj._id, }); g_db.acl.save({ _from: root._id, _to: mem_grp._id, grant: g_lib.PERM_MEMBER, - inhgrant: g_lib.PERM_MEMBER + inhgrant: g_lib.PERM_MEMBER, }); proj.new.admins = []; @@ -122,14 +160,13 @@ router.get('/create', function(req, res) { if (req.queryParams.admins) { for (i in req.queryParams.admins) { uid = req.queryParams.admins[i]; - if (uid == client._id) - continue; + if (uid == client._id) continue; if (!g_db._exists(uid)) throw [g_lib.ERR_NOT_FOUND, "User, " + uid + ", not found"]; g_db.admin.save({ _from: proj._id, - _to: uid + _to: uid, }); proj.new.admins.push(uid); } @@ -138,14 +175,13 @@ router.get('/create', function(req, res) { if (req.queryParams.members) { for (i in req.queryParams.members) { uid = req.queryParams.members[i]; - if (uid == client._id || proj.new.admins.indexOf(uid) != -1) - continue; + if (uid == client._id || proj.new.admins.indexOf(uid) != -1) continue; if (!g_db._exists(uid)) throw [g_lib.ERR_NOT_FOUND, "User, " + uid + ", not found"]; g_db.member.save({ _from: mem_grp._id, - _to: uid + _to: uid, }); proj.new.members.push(uid); } @@ -157,7 +193,7 @@ router.get('/create', function(req, res) { delete proj.new._rev; result = [proj.new]; - } + }, }); res.send(result); @@ -165,26 +201,30 @@ router.get('/create', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().optional().allow(""), "ID for new project") - .queryParam('title', joi.string().optional().allow(""), "Title") - .queryParam('desc', joi.string().optional().allow(""), "Description") - .queryParam('admins', joi.array().items(joi.string()).optional(), "Additional project administrators (uids)") - .queryParam('members', joi.array().items(joi.string()).optional(), "Project members (uids)") - .summary('Create new project') - .description('Create new project.'); - - -router.get('/update', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().optional().allow(""), "ID for new project") + .queryParam("title", joi.string().optional().allow(""), "Title") + .queryParam("desc", joi.string().optional().allow(""), "Description") + .queryParam( + "admins", + joi.array().items(joi.string()).optional(), + "Additional project administrators (uids)", + ) + .queryParam("members", joi.array().items(joi.string()).optional(), "Project members (uids)") + .summary("Create new project") + .description("Create new project."); + +router + .get("/update", function (req, res) { try { var result; g_db._executeTransaction({ collections: { read: ["u", "p", "uuid", "accn"], - write: ["p", "admin", "member", "acl"] + write: ["p", "admin", "member", "acl"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var proj_id = req.queryParams.id; @@ -201,11 +241,11 @@ router.get('/update', function(req, res) { } var owner_id = g_db.owner.firstExample({ - _from: proj_id + _from: proj_id, })._to; var time = Math.floor(Date.now() / 1000); var obj = { - ut: time + ut: time, }; g_lib.procInputParam(req.queryParams, "title", true, obj); @@ -213,14 +253,18 @@ router.get('/update', function(req, res) { // Managers can only update members if (!is_admin) { - if (obj.title !== undefined || obj.desc != undefined || req.queryParams.admins != undefined) { + if ( + obj.title !== undefined || + obj.desc != undefined || + req.queryParams.admins != undefined + ) { throw g_lib.ERR_PERM_DENIED; } } var proj = g_db._update(proj_id, obj, { keepNull: false, - returnNew: true + returnNew: true, }); var uid, i; @@ -230,31 +274,36 @@ router.get('/update', function(req, res) { if (req.queryParams.admins) { var links; g_db.admin.removeByExample({ - _from: proj_id + _from: proj_id, }); for (i in req.queryParams.admins) { uid = req.queryParams.admins[i]; - if (uid == owner_id) - continue; + if (uid == owner_id) continue; if (!g_db._exists(uid)) throw [g_lib.ERR_NOT_FOUND, "User, " + uid + ", not found"]; g_db.admin.save({ _from: proj_id, - _to: uid + _to: uid, }); // Remove Admin from all groups and ACLs - links = g_db._query("for v,e,p in 2..2 inbound @user acl, outbound owner filter v._id == @proj return p.edges[0]._id", { - user: uid, - proj: proj_id - }); + links = g_db._query( + "for v,e,p in 2..2 inbound @user acl, outbound owner filter v._id == @proj return p.edges[0]._id", + { + user: uid, + proj: proj_id, + }, + ); while (links.hasNext()) { g_db.acl.remove(links.next()); } - links = g_db._query("for v,e,p in 2..2 inbound @user member, outbound owner filter v._id == @proj return p.edges[0]._id", { - user: uid, - proj: proj_id - }); + links = g_db._query( + "for v,e,p in 2..2 inbound @user member, outbound owner filter v._id == @proj return p.edges[0]._id", + { + user: uid, + proj: proj_id, + }, + ); while (links.hasNext()) { g_db.member.remove(links.next()); } @@ -262,9 +311,11 @@ router.get('/update', function(req, res) { } } else { // TODO - Why not just assign query result directly to new? - var admins = g_db._query("for i in admin filter i._from == @proj return i._to", { - proj: proj_id - }).toArray(); + var admins = g_db + ._query("for i in admin filter i._from == @proj return i._to", { + proj: proj_id, + }) + .toArray(); for (i in admins) { proj.new.admins.push(admins[i]); } @@ -273,31 +324,34 @@ router.get('/update', function(req, res) { if (req.queryParams.members) { var mem_grp = g_db.g.firstExample({ uid: proj_id, - gid: "members" + gid: "members", }); g_db.member.removeByExample({ - _from: mem_grp._id + _from: mem_grp._id, }); for (i in req.queryParams.members) { uid = req.queryParams.members[i]; - if (uid == owner_id || proj.new.admins.indexOf(uid) != -1) - continue; + if (uid == owner_id || proj.new.admins.indexOf(uid) != -1) continue; if (!g_db._exists(uid)) throw [g_lib.ERR_NOT_FOUND, "User, " + uid + ", not found"]; g_db.member.save({ _from: mem_grp._id, - _to: uid + _to: uid, }); proj.new.members.push(uid); } } else { - var members = g_db._query("for v,e,p in 2..2 inbound @proj owner, outbound member filter p.vertices[1].gid == 'members' return v._id", { - proj: proj_id - }).toArray(); - - if (members.length) - proj.new.members = members; + var members = g_db + ._query( + "for v,e,p in 2..2 inbound @proj owner, outbound member filter p.vertices[1].gid == 'members' return v._id", + { + proj: proj_id, + }, + ) + .toArray(); + + if (members.length) proj.new.members = members; } proj.new.id = proj.new._id; @@ -307,7 +361,7 @@ router.get('/update', function(req, res) { delete proj.new._rev; result = [proj.new]; - } + }, }); res.send(result); @@ -315,17 +369,21 @@ router.get('/update', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().required(), "Project ID") - .queryParam('title', joi.string().optional().allow(''), "New title") - .queryParam('desc', joi.string().optional().allow(''), "Description") - .queryParam('admins', joi.array().items(joi.string()).optional(), "Account administrators (uids)") - .queryParam('members', joi.array().items(joi.string()).optional(), "Project members (uids)") - .summary('Update project information') - .description('Update project information'); - - -router.get('/view', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().required(), "Project ID") + .queryParam("title", joi.string().optional().allow(""), "New title") + .queryParam("desc", joi.string().optional().allow(""), "Description") + .queryParam( + "admins", + joi.array().items(joi.string()).optional(), + "Account administrators (uids)", + ) + .queryParam("members", joi.array().items(joi.string()).optional(), "Project members (uids)") + .summary("Update project information") + .description("Update project information"); + +router + .get("/view", function (req, res) { try { // TODO Enforce view permission @@ -335,31 +393,38 @@ router.get('/view', function(req, res) { throw [g_lib.ERR_INVALID_PARAM, "No such project '" + req.queryParams.id + "'"]; var proj = g_db.p.document({ - _id: req.queryParams.id + _id: req.queryParams.id, }); //var owner_id = g_db.owner.firstExample({_from: proj._id })._to; - var admins = g_db._query("for v in 1..1 outbound @proj admin return v._id", { - proj: proj._id - }).toArray(); + var admins = g_db + ._query("for v in 1..1 outbound @proj admin return v._id", { + proj: proj._id, + }) + .toArray(); if (admins.length) { proj.admins = admins; - } else - proj.admins = []; + } else proj.admins = []; if (client) { - var members = g_db._query("for v,e,p in 2..2 inbound @proj owner, outbound member filter p.vertices[1].gid == 'members' return v._id", { - proj: proj._id - }).toArray(); + var members = g_db + ._query( + "for v,e,p in 2..2 inbound @proj owner, outbound member filter p.vertices[1].gid == 'members' return v._id", + { + proj: proj._id, + }, + ) + .toArray(); if (members.length) { proj.members = members; - } else - proj.members = []; + } else proj.members = []; - proj.allocs = g_db.alloc.byExample({ - _from: proj._id - }).toArray(); + proj.allocs = g_db.alloc + .byExample({ + _from: proj._id, + }) + .toArray(); if (proj.allocs.length) { g_lib.sortAllocations(proj.allocs); @@ -388,46 +453,50 @@ router.get('/view', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().required(), "Project ID") - .summary('View project information') - .description('View project information'); + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().required(), "Project ID") + .summary("View project information") + .description("View project information"); - -router.get('/list', function(req, res) { +router + .get("/list", function (req, res) { const client = g_lib.getUserFromClientID(req.queryParams.client); - var qry, result, count = (req.queryParams.as_owner ? 1 : 0) + (req.queryParams.as_admin ? 1 : 0) + (req.queryParams.as_member ? 1 : 0); + var qry, + result, + count = + (req.queryParams.as_owner ? 1 : 0) + + (req.queryParams.as_admin ? 1 : 0) + + (req.queryParams.as_member ? 1 : 0); if (count) { var comma = false; - if (count > 1) - qry = "for i in union(("; - else - qry = ""; + if (count > 1) qry = "for i in union(("; + else qry = ""; if (req.queryParams.as_owner) { qry += "for i in 1..1 inbound @user owner filter IS_SAME_COLLECTION('p',i)"; - if (count > 1) - qry += " return { _id: i._id, title: i.title, owner: i.owner }"; + if (count > 1) qry += " return { _id: i._id, title: i.title, owner: i.owner }"; comma = true; } if (!count || req.queryParams.as_admin) { - qry += (comma ? "),(" : "") + "for i in 1..1 inbound @user admin filter IS_SAME_COLLECTION('p',i)"; + qry += + (comma ? "),(" : "") + + "for i in 1..1 inbound @user admin filter IS_SAME_COLLECTION('p',i)"; if (count > 1) qry += " return { _id: i._id, title: i.title, owner: i.owner, creator: @user }"; comma = true; } if (req.queryParams.as_member) { - qry += (comma ? "),(" : "") + "for i,e,p in 2..2 inbound @user member, outbound owner filter p.vertices[1].gid == 'members'"; - if (count > 1) - qry += " return { _id: i._id, title: i.title, owner: i.owner }"; + qry += + (comma ? "),(" : "") + + "for i,e,p in 2..2 inbound @user member, outbound owner filter p.vertices[1].gid == 'members'"; + if (count > 1) qry += " return { _id: i._id, title: i.title, owner: i.owner }"; } - if (count > 1) - qry += "))"; + if (count > 1) qry += "))"; } else { qry = "for i in p"; } @@ -452,58 +521,74 @@ router.get('/list', function(req, res) { break; } - if (req.queryParams.sort_rev) - qry += " desc"; + if (req.queryParams.sort_rev) qry += " desc"; var user_id; if (req.queryParams.subject) { g_lib.ensureAdminPermUser(client, req.queryParams.subject); - } else - user_id = client._id; + } else user_id = client._id; if (req.queryParams.offset != undefined && req.queryParams.count != undefined) { qry += " limit " + req.queryParams.offset + ", " + req.queryParams.count; qry += " return { id: i._id, title: i.title, owner: i.owner, creator: i.creator }"; //console.log("proj list qry:",qry); - result = g_db._query(qry, count ? { - user: user_id - } : {}, {}, { - fullCount: true - }); + result = g_db._query( + qry, + count + ? { + user: user_id, + } + : {}, + {}, + { + fullCount: true, + }, + ); var tot = result.getExtra().stats.fullCount; result = result.toArray(); result.push({ paging: { off: req.queryParams.offset, cnt: req.queryParams.count, - tot: tot - } + tot: tot, + }, }); } else { qry += " return { id: i._id, title: i.title, owner: i.owner, creator: i.creator }"; //console.log("proj list qry:",qry); - result = g_db._query(qry, count ? { - user: user_id - } : {}); + result = g_db._query( + qry, + count + ? { + user: user_id, + } + : {}, + ); } //res.send( g_db._query( qry, { user: client._id })); res.send(result); }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().optional(), "Subject (user) ID") - .queryParam('as_owner', joi.bool().optional(), "List projects owned by client/subject") - .queryParam('as_admin', joi.bool().optional(), "List projects administered by client/subject") - .queryParam('as_member', joi.bool().optional(), "List projects where client is a member/subject") - .queryParam('sort', joi.number().optional(), "Sort field (default = id)") - .queryParam('sort_rev', joi.bool().optional(), "Sort in reverse order") - .queryParam('offset', joi.number().optional(), "Offset") - .queryParam('count', joi.number().optional(), "Count") - .summary('List projects') - .description('List projects. If no options are provided, lists all projects associated with client.'); - - -router.get('/search', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().optional(), "Subject (user) ID") + .queryParam("as_owner", joi.bool().optional(), "List projects owned by client/subject") + .queryParam("as_admin", joi.bool().optional(), "List projects administered by client/subject") + .queryParam( + "as_member", + joi.bool().optional(), + "List projects where client is a member/subject", + ) + .queryParam("sort", joi.number().optional(), "Sort field (default = id)") + .queryParam("sort_rev", joi.bool().optional(), "Sort in reverse order") + .queryParam("offset", joi.number().optional(), "Offset") + .queryParam("count", joi.number().optional(), "Count") + .summary("List projects") + .description( + "List projects. If no options are provided, lists all projects associated with client.", + ); + +router + .get("/search", function (req, res) { try { g_lib.getUserFromClientID(req.queryParams.client); @@ -512,50 +597,53 @@ router.get('/search', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('query', joi.string().required(), "Query") - .summary('Find all projects that match query') - .description('Find all projects that match query'); - + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("query", joi.string().required(), "Query") + .summary("Find all projects that match query") + .description("Find all projects that match query"); -router.post('/delete', function(req, res) { +router + .post("/delete", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn", "p", "alloc"], write: ["g", "owner", "acl", "admin", "member"], - exclusive: ["lock", "task", "block"] + exclusive: ["lock", "task", "block"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var result = g_tasks.taskInitProjDelete(client, req.body.ids); res.send(result); - } + }, }); - } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.object({ - ids: joi.array().items(joi.string()).required(), - }).required(), 'Parameters') - .summary('Delete project(s) and all associated data records and raw data.') - .description('Delete project(s) and all associated data records and raw data.'); - - -router.get('/get_role', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .object({ + ids: joi.array().items(joi.string()).required(), + }) + .required(), + "Parameters", + ) + .summary("Delete project(s) and all associated data records and raw data.") + .description("Delete project(s) and all associated data records and raw data."); + +router + .get("/get_role", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var subj; if (req.queryParams.subject) subj = g_lib.getUserFromClientID(req.queryParams.subject)._id; - else - subj = client._id; + else subj = client._id; if (!req.queryParams.id.startsWith("p/")) throw [g_lib.ERR_INVALID_PARAM, "Invalid project ID: " + req.queryParams.id]; @@ -566,14 +654,14 @@ router.get('/get_role', function(req, res) { var role = g_lib.getProjectRole(subj, req.queryParams.id); res.send({ - role: role + role: role, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().optional(), "Optional subject (user) ID") - .queryParam('id', joi.string().required(), "Project ID") - .summary('Get client/subject project role') - .description('Get client/subject project role'); \ No newline at end of file + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().optional(), "Optional subject (user) ID") + .queryParam("id", joi.string().required(), "Project ID") + .summary("Get client/subject project role") + .description("Get client/subject project role"); diff --git a/core/database/foxx/api/query_router.js b/core/database/foxx/api/query_router.js index df33931f1..3a3bedbfa 100644 --- a/core/database/foxx/api/query_router.js +++ b/core/database/foxx/api/query_router.js @@ -1,38 +1,48 @@ -'use strict'; +"use strict"; -const createRouter = require('@arangodb/foxx/router'); +const createRouter = require("@arangodb/foxx/router"); const router = createRouter(); -const joi = require('joi'); +const joi = require("joi"); -const g_db = require('@arangodb').db; -const g_graph = require('@arangodb/general-graph')._graph('sdmsg'); -const g_lib = require('./support'); +const g_db = require("@arangodb").db; +const g_graph = require("@arangodb/general-graph")._graph("sdmsg"); +const g_lib = require("./support"); module.exports = router; //==================== QUERY API FUNCTIONS - -router.post('/create', function(req, res) { +router + .post("/create", function (req, res) { try { var result; g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn", "admin"], - write: ["q", "owner"] + write: ["q", "owner"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); // Check max number of saved queries if (client.max_sav_qry >= 0) { - var count = g_db._query("return length(FOR i IN owner FILTER i._to == @id and is_same_collection('q',i._from) RETURN 1)", { - id: client._id - }).next(); + var count = g_db + ._query( + "return length(FOR i IN owner FILTER i._to == @id and is_same_collection('q',i._from) RETURN 1)", + { + id: client._id, + }, + ) + .next(); if (count >= client.max_sav_qry) - throw [g_lib.ERR_ALLOCATION_EXCEEDED, "Saved query limit reached (" + client.max_sav_qry + "). Contact system administrator to increase limit."]; + throw [ + g_lib.ERR_ALLOCATION_EXCEEDED, + "Saved query limit reached (" + + client.max_sav_qry + + "). Contact system administrator to increase limit.", + ]; } var time = Math.floor(Date.now() / 1000); @@ -48,11 +58,11 @@ router.post('/create', function(req, res) { //console.log("qry/create filter:",obj.qry_filter); var qry = g_db.q.save(obj, { - returnNew: true + returnNew: true, }).new; g_db.owner.save({ _from: qry._id, - _to: client._id + _to: client._id, }); qry.id = qry._id; @@ -67,7 +77,7 @@ router.post('/create', function(req, res) { delete qry.lmit; result = qry; - } + }, }); res.send(result); @@ -75,30 +85,35 @@ router.post('/create', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.object({ - title: joi.string().required(), - qry_begin: joi.string().required(), - qry_end: joi.string().required(), - qry_filter: joi.string().allow('').required(), - params: joi.any().required(), - limit: joi.number().integer().required(), - query: joi.any().required() - }).required(), 'Query fields') - .summary('Create a query') - .description('Create a query'); - - -router.post('/update', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .object({ + title: joi.string().required(), + qry_begin: joi.string().required(), + qry_end: joi.string().required(), + qry_filter: joi.string().allow("").required(), + params: joi.any().required(), + limit: joi.number().integer().required(), + query: joi.any().required(), + }) + .required(), + "Query fields", + ) + .summary("Create a query") + .description("Create a query"); + +router + .post("/update", function (req, res) { try { var result; g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn", "admin"], - write: ["q", "owner"] + write: ["q", "owner"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var qry = g_db.q.document(req.body.id); @@ -126,7 +141,7 @@ router.post('/update', function(req, res) { //console.log("qry/upd filter:",obj.qry_filter); qry = g_db._update(qry._id, qry, { mergeObjects: false, - returnNew: true + returnNew: true, }).new; qry.id = qry._id; @@ -141,7 +156,7 @@ router.post('/update', function(req, res) { delete qry.lmit; result = qry; - } + }, }); res.send(result); @@ -149,21 +164,27 @@ router.post('/update', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.object({ - id: joi.string().required(), - title: joi.string().optional(), - qry_begin: joi.string().required(), - qry_end: joi.string().required(), - qry_filter: joi.string().allow('').required(), - params: joi.any().required(), - limit: joi.number().integer().required(), - query: joi.any().required() - }).required(), 'Query fields') - .summary('Update a saved query') - .description('Update a saved query'); - -router.get('/view', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .object({ + id: joi.string().required(), + title: joi.string().optional(), + qry_begin: joi.string().required(), + qry_end: joi.string().required(), + qry_filter: joi.string().allow("").required(), + params: joi.any().required(), + limit: joi.number().integer().required(), + query: joi.any().required(), + }) + .required(), + "Query fields", + ) + .summary("Update a saved query") + .description("Update a saved query"); + +router + .get("/view", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var qry = g_db.q.document(req.queryParams.id); @@ -187,27 +208,33 @@ router.get('/view', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().required(), "Query ID") - .summary('View specified query') - .description('View specified query'); - + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().required(), "Query ID") + .summary("View specified query") + .description("View specified query"); -router.get('/delete', function(req, res) { +router + .get("/delete", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var owner; for (var i in req.queryParams.ids) { if (!req.queryParams.ids[i].startsWith("q/")) { - throw [g_lib.ERR_INVALID_PARAM, "Invalid query ID '" + req.queryParams.ids[i] + "'."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Invalid query ID '" + req.queryParams.ids[i] + "'.", + ]; } owner = g_db.owner.firstExample({ - _from: req.queryParams.ids[i] + _from: req.queryParams.ids[i], }); if (!owner) { - throw [g_lib.ERR_NOT_FOUND, "Query '" + req.queryParams.ids[i] + "' not found."]; + throw [ + g_lib.ERR_NOT_FOUND, + "Query '" + req.queryParams.ids[i] + "' not found.", + ]; } if (client._id != owner._to && !client.is_admin) { @@ -220,59 +247,66 @@ router.get('/delete', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('ids', joi.array().items(joi.string()).required(), "Query IDs") - .summary('Delete specified query') - .description('Delete specified query'); + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("ids", joi.array().items(joi.string()).required(), "Query IDs") + .summary("Delete specified query") + .description("Delete specified query"); - -router.get('/list', function(req, res) { +router + .get("/list", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); - var qry = "for v in 1..1 inbound @user owner filter is_same_collection('q',v) sort v.title"; + var qry = + "for v in 1..1 inbound @user owner filter is_same_collection('q',v) sort v.title"; var result; if (req.queryParams.offset != undefined && req.queryParams.count != undefined) { qry += " limit " + req.queryParams.offset + ", " + req.queryParams.count; qry += " return { id: v._id, title: v.title }"; - result = g_db._query(qry, { - user: client._id - }, {}, { - fullCount: true - }); + result = g_db._query( + qry, + { + user: client._id, + }, + {}, + { + fullCount: true, + }, + ); var tot = result.getExtra().stats.fullCount; result = result.toArray(); result.push({ paging: { off: req.queryParams.offset, cnt: req.queryParams.count, - tot: tot - } + tot: tot, + }, }); } else { qry += " return { id: v._id, title: v.title }"; result = g_db._query(qry, { - user: client._id + user: client._id, }); } res.send(result); - } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('offset', joi.number().integer().min(0).optional(), "Offset") - .queryParam('count', joi.number().integer().min(1).optional(), "Count") - .summary('List client saved queries') - .description('List client saved queries'); + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("offset", joi.number().integer().min(0).optional(), "Offset") + .queryParam("count", joi.number().integer().min(1).optional(), "Count") + .summary("List client saved queries") + .description("List client saved queries"); -function execQuery(client, mode, published, query) { +function execQuery(client, mode, published, orig_query) { var col_chk = true, ctxt = client._id; - + let query = { + ...orig_query, + }; if (!published) { // For searches over private data, must perform access checks based on owner field and client id @@ -285,12 +319,20 @@ function execQuery(client, mode, published, query) { // Build list of accessible collections shared with client if (!query.params.cols) { - query.params.cols = g_db._query("for v in 1..2 inbound @client member, acl filter v.owner == @owner and is_same_collection('c',v) return v._id", { - client: client._id, - owner: query.params.owner - }).toArray(); + query.params.cols = g_db + ._query( + "for v in 1..2 inbound @client member, acl filter v.owner == @owner and is_same_collection('c',v) return v._id", + { + client: client._id, + owner: query.params.owner, + }, + ) + .toArray(); if (!query.params.cols) { - throw [g_lib.ERR_PERM_DENIED, "No access to user '" + query.params.owner + "' data/collections."]; + throw [ + g_lib.ERR_PERM_DENIED, + "No access to user '" + query.params.owner + "' data/collections.", + ]; } col_chk = false; } @@ -311,12 +353,20 @@ function execQuery(client, mode, published, query) { if (role == g_lib.PROJ_MEMBER || role == g_lib.PROJ_NO_ROLE) { // Build list of accessible collections shared with client if (!query.params.cols) { - query.params.cols = g_db._query("for v in 1..2 inbound @client member, acl filter v.owner == @owner and is_same_collection('c',v) return v._id", { - client: client._id, - owner: query.params.owner - }).toArray(); + query.params.cols = g_db + ._query( + "for v in 1..2 inbound @client member, acl filter v.owner == @owner and is_same_collection('c',v) return v._id", + { + client: client._id, + owner: query.params.owner, + }, + ) + .toArray(); if (!query.params.cols) { - throw [g_lib.ERR_PERM_DENIED, "No access to project '" + query.params.owner + "'."]; + throw [ + g_lib.ERR_PERM_DENIED, + "No access to project '" + query.params.owner + "'.", + ]; } col_chk = false; } @@ -332,16 +382,22 @@ function execQuery(client, mode, published, query) { if (query.params.cols) { //console.log("proc cols"); if (col_chk) { - var col, cols = []; + var col, + cols = []; for (var c in query.params.cols) { col = g_lib.resolveCollID2(query.params.cols[c], ctxt); //console.log("col:", query.params.cols[c],",ctxt:", ctxt,",id:", col); if (query.params.owner) { - if (g_db.owner.firstExample({ - _from: col - })._to != query.params.owner) { - throw [g_lib.ERR_INVALID_PARAM, "Collection '" + col + "' not in search scope."]; + if ( + g_db.owner.firstExample({ + _from: col, + })._to != query.params.owner + ) { + throw [ + g_lib.ERR_INVALID_PARAM, + "Collection '" + col + "' not in search scope.", + ]; } } cols.push(col); @@ -365,7 +421,7 @@ function execQuery(client, mode, published, query) { query.params.sch = g_db.sch.firstExample({ id: sch_id, - ver: sch_ver + ver: sch_ver, }); if (!query.params.sch) throw [g_lib.ERR_NOT_FOUND, "Schema '" + sch_id + "-" + sch_ver + "' does not exist."]; @@ -424,10 +480,8 @@ function execQuery(client, mode, published, query) { for (var i in result) { item = result[i]; - if (item.owner_name && item.owner_name.length) - item.owner_name = item.owner_name[0]; - else - item.owner_name = null; + if (item.owner_name && item.owner_name.length) item.owner_name = item.owner_name[0]; + else item.owner_name = null; if (item.desc && item.desc.length > 120) { item.desc = item.desc.slice(0, 120) + " ..."; @@ -440,14 +494,15 @@ function execQuery(client, mode, published, query) { paging: { off: query.params.off, cnt: result.length, - tot: query.params.off + cnt - } + tot: query.params.off + cnt, + }, }); return result; } -router.get('/exec', function(req, res) { +router + .get("/exec", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var qry = g_db.q.document(req.queryParams.id); @@ -468,34 +523,43 @@ router.get('/exec', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().required(), "Query ID") - .queryParam('offset', joi.number().integer().min(0).max(999).optional(), "Offset") - .queryParam('count', joi.number().integer().min(1).max(1000).optional(), "Count") - .summary('Execute specified query') - .description('Execute specified query'); - - -router.post('/exec/direct', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().required(), "Query ID") + .queryParam("offset", joi.number().integer().min(0).max(999).optional(), "Offset") + .queryParam("count", joi.number().integer().min(1).max(1000).optional(), "Count") + .summary("Execute specified query") + .description("Execute specified query"); + +router + .post("/exec/direct", function (req, res) { try { const client = g_lib.getUserFromClientID_noexcept(req.queryParams.client); - var results = execQuery(client, req.body.mode, req.body.published, req.body); + const query = { + ...req.body, + params: JSON.parse(req.body.params), + }; + var results = execQuery(client, req.body.mode, req.body.published, query); res.send(results); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.object({ - mode: joi.number().integer().required(), - published: joi.boolean().required(), - qry_begin: joi.string().required(), - qry_end: joi.string().required(), - qry_filter: joi.string().optional().allow(""), - params: joi.object().required(), - limit: joi.number().integer().required() - }).required(), 'Collection fields') - .summary('Execute published data search query') - .description('Execute published data search query'); \ No newline at end of file + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .object({ + mode: joi.number().integer().required(), + published: joi.boolean().required(), + qry_begin: joi.string().required(), + qry_end: joi.string().required(), + qry_filter: joi.string().optional().allow(""), + params: joi.string().required(), + limit: joi.number().integer().required(), + }) + .required(), + "Collection fields", + ) + .summary("Execute published data search query") + .description("Execute published data search query"); diff --git a/core/database/foxx/api/record.js b/core/database/foxx/api/record.js new file mode 100644 index 000000000..36c330672 --- /dev/null +++ b/core/database/foxx/api/record.js @@ -0,0 +1,250 @@ +"use strict"; + +const g_db = require("@arangodb").db; +const g_lib = require("./support"); +const { errors } = require("@arangodb"); + +/** + * Represents a record in the database and provides methods to manage it. + * + * @class + */ +class Record { + // ERROR code + #error = null; + // Error message should be a string if defined + #err_msg = null; + // Boolean value that determines if the record exists in the database + #exists = false; + // location object, determines what the allocation the data item is associated with + #loc = null; + // Allocation object, determines what allocation data item is associated with + #alloc = null; + // Determines what repo the data item is associated with + #repo = null; + // The data key + #key = null; + // The data id simply the key prepended with 'd/' + #data_id = null; + + /** + * Constructs a Record object and checks if the key exists in the database. + * + * @class + * @param {string} a_key - The unique identifier for the record. Must be a valid key in the database. + */ + constructor(a_key) { + // Define the collection + const collection = g_db._collection("d"); + + // This function is designed to check if the provided key exists in the + // database as a record. Searches are only made in the 'd' collection + // + // Will return true if it does and false if it does not. + this.#key = a_key; + this.#data_id = "d/" + a_key; + if (a_key) { + // Check if the document exists + try { + if (collection.exists(this.#key)) { + this.#exists = true; + } else { + this.#exists = false; + this.#error = g_lib.ERR_NOT_FOUND; + this.#err_msg = "Invalid key: (" + a_key + "). No record found."; + } + } catch (e) { + this.#exists = false; + this.#error = g_lib.ERR_INTERNAL_FAULT; + this.#err_msg = "Unknown error encountered."; + console.log(e); + } + } + } + + /** + * Generates the full path to the record as it should appear in the repository. + * + * @param {object} loc - The location object which specifies the owner of the record. + * @param {string} basePath - The base path where the record is stored. + * + * @returns {string} - the path to the record or null if error + */ + _pathToRecord(loc, basePath) { + const path = basePath.endsWith("/") ? basePath : basePath + "/"; + if (loc.uid.charAt(0) == "u") { + return path + "user/" + loc.uid.substr(2) + "/" + this.#key; + } else if (loc.uid.charAt(0) == "p") { + return path + "project/" + loc.uid.substr(2) + "/" + this.#key; + } else { + this.#error = g_lib.ERR_INTERNAL_FAULT; + this.#err_msg = "Provided path does not fit within supported directory "; + this.#err_msg += "structure for repository, no user or project folder has"; + this.#err_msg += " been determined for the record."; + console.log(e); + return null; + } + } + + /** + * Compares two paths and if an error is detected will save the error code and message. + * + * @param {string} storedPath - the path stored in the database + * @param {string} inputPath - the path being checked + * @returns {boolean} - true if paths are equal false otherwise + **/ + _comparePaths(storedPath, inputPath) { + if (storedPath === null) { + return false; + } + if (storedPath !== inputPath) { + this.#error = g_lib.ERR_PERM_DENIED; + this.#err_msg = + "Record path is not consistent with repo expected path is: " + + storedPath + + " attempted path is " + + inputPath; + return false; + } + return true; + } + + /** + * Checks if the record exists in the database. + * + * @returns {boolean} - True if the record exists, otherwise false. + */ + exists() { + return this.#exists; + } + + key() { + return this.#key; + } + + id() { + return this.#data_id; + } + /** + * Will return error code of last run method. + * + * @returns {number} - error code + **/ + error() { + return this.#error; + } + + /** + * Retrieves the error code of the last run method. + * + * @returns {string|null} Error code or null if no error. + */ + errorMessage() { + return this.#err_msg; + } + + /** + * Checks if the record is managed by DataFed. + * + * @returns {boolean} True if managed, otherwise false. + */ + isManaged() { + //{ + // _from: data._id, + // _to: repo_alloc._to, + // uid: owner_id + //}; + this.#loc = g_db.loc.firstExample({ + _from: this.#data_id, + }); + + if (!this.#loc) { + this.#error = g_lib.ERR_PERM_DENIED; + this.#err_msg = + "Permission denied data is not managed by DataFed. This can happen if you try to do a transfer directly from Globus."; + return false; + } + this.#alloc = g_db.alloc.firstExample({ + _from: this.#loc.uid, + _to: this.#loc._to, + }); + + // If alloc is null then will return false if not null will return true. + return !!this.#alloc; + } + + /** + * Validates if the provided record path is consistent with the database. + * + * @param {string} a_path - The path to validate. + * @returns {boolean} True if consistent, otherwise false. + */ + isPathConsistent(a_path) { + // This function will populate the this.#loc member and the this.#alloc + // member + if (!this.isManaged()) { + return false; + } + + // If there is a new repo we need to check the path there and use that + if (this.#loc.hasOwnProperty("new_repo") && this.#loc.new_repo) { + // Below we get the allocation associated with data item by + // 1. Checking if the data item is in flight, is in the process + // of being moved to a new location or new owner and using that + // oweners id. + // 2. Using the loc.uid parameter if not inflight to get the owner + // id. + const new_alloc = g_db.alloc.firstExample({ + _from: this.#loc.new_owner ? this.#loc.new_owner : this.#loc.uid, + _to: this.#loc.new_repo, + }); + + // If no allocation is found for the item throw an error + // if the paths do not align also throw an error. + if (!new_alloc) { + this.#error = g_lib.ERR_PERM_DENIED; + this.#err_msg = + "Permission denied, '" + this.#key + "' is not part of an allocation '"; + return false; + } + + this.#repo = g_db._document(this.#loc.new_repo); + + if (!this.#repo) { + this.#error = g_lib.ERR_INTERNAL_FAULT; + this.#err_msg = + "Unable to find repo that record is meant to be allocated too, '" + + this.#loc.new_repo + + "' record '" + + this.#data_id; + return false; + } + + // If path is missing the starting "/" add it back in + if (!a_path.startsWith("/") && this.#repo.path.startsWith("/")) { + a_path = "/" + a_path; + } + + let stored_path = this._pathToRecord(this.#loc, this.#repo.path); + + if (!this._comparePaths(stored_path, a_path)) { + return false; + } + } else { + this.#repo = g_db._document(this.#loc._to); + + if (!a_path.startsWith("/") && this.#repo.path.startsWith("/")) { + a_path = "/" + a_path; + } + let stored_path = this._pathToRecord(this.#loc, this.#repo.path); + + // If there is no new repo check that the paths align + if (!this._comparePaths(stored_path, a_path)) { + return false; + } + } + return true; + } +} + +module.exports = Record; diff --git a/core/database/foxx/api/repo.js b/core/database/foxx/api/repo.js new file mode 100644 index 000000000..baea100b9 --- /dev/null +++ b/core/database/foxx/api/repo.js @@ -0,0 +1,189 @@ +"use strict"; + +const g_db = require("@arangodb").db; +const g_lib = require("./support"); +const { errors } = require("@arangodb"); +const pathModule = require("./posix_path"); + +/** + * All DataFed repositories have the following path structure on a POSIX file system + * + * E.g. + * /mnt/science/datafed/project/foo/904u42 + * /mnt/science/datafed/user/bob/352632 + * + * In these cases + * + * PROJECT_PATH = /mnt/science/datafed/project/foo + * USER_PATH = /mnt/science/datafed/user/bob + * + * USER_RECORD_PATH = /mnt/science/datafed/user/bob/352632 + * and + * PROJECT_RECORD_PATH = /mnt/science/datafed/project/foo/904u42 + * + * REPO_BASE_PATH = /mnt/science + * REPO_ROOT_PATH = /mnt/science/datafed + * REPO_PATH = /mnt/science/datafed/project + * REPO_PATH = /mnt/science/datafed/user + **/ +const PathType = { + USER_PATH: "USER_PATH", + USER_RECORD_PATH: "USER_RECORD_PATH", + PROJECT_PATH: "PROJECT_PATH", + PROJECT_RECORD_PATH: "PROJECT_RECORD_PATH", + REPO_BASE_PATH: "REPO_BASE_PATH", + REPO_ROOT_PATH: "REPO_ROOT_PATH", + REPO_PATH: "REPO_PATH", + UNKNOWN: "UNKNOWN", +}; + +class Repo { + // ERROR code + #error = null; + // Error message should be a string if defined + #err_msg = null; + // Boolean value that determines if the repo exists in the database + #exists = false; + // The repo id simply the key prepended with 'repo/' + #repo_id = null; + #repo_key = null; + + /** + * Constructs a Repo object and checks if the key exists in the database. + * + * @param {string} a_key or id - The unique identifier for the repo, of repo key. + * e.g. can be either + * repo/repo_name + * or + * repo_name + */ + constructor(a_key) { + // Define the collection + const collection = g_db._collection("repo"); + + // This function is designed to check if the provided key exists in the + // database as a record. Searches are only made in the 'd' collection + // + // Will return true if it does and false if it does not. + if (a_key && a_key !== "repo/") { + if (a_key.startsWith("repo/")) { + this.#repo_id = a_key; + this.#repo_key = a_key.slice("repo/".length); + } else { + this.#repo_id = "repo/" + a_key; + this.#repo_key = a_key; + } + + // Check if the repo document exists + try { + if (collection.exists(this.#repo_key)) { + this.#exists = true; + } else { + this.#exists = false; + this.#error = g_lib.ERR_NOT_FOUND; + this.#err_msg = "Invalid repo: (" + a_key + "). No record found."; + } + } catch (e) { + this.#exists = false; + this.#error = g_lib.ERR_INTERNAL_FAULT; + this.#err_msg = "Unknown error encountered."; + console.log(e); + } + } + } + + /** + * Checks if the repo exists in the database. + * + * @returns {boolean} True if the repo exists, otherwise false. + */ + exists() { + return this.#exists; + } + + key() { + return this.#repo_key; + } + + id() { + return this.#repo_id; + } + + /** + * Will return error code of last run method. + * @returns {number} - If no error code, will return null + **/ + error() { + return this.#error; + } + + /** + * Retrieves the error code of the last run method. + * + * @returns {string|null} Error code or null if no error. + */ + errorMessage() { + return this.#err_msg; + } + + /** + * Detect what kind of POSIX path has been provided + * + * @param {string} a_path - the POSIX path that is supposed to exist on the repo + * @returns {string} - posix path type + **/ + pathType(a_path) { + // Ensure the repo exists + if (!this.#exists) { + throw [g_lib.ERR_PERM_DENIED, "Repo does not exist " + this.#repo_id]; + } + + let repo = g_db._document(this.#repo_id); + if (!repo.path) { + throw [g_lib.ERR_INTERNAL_FAULT, "Repo document is missing path: " + this.#repo_id]; + } + + // Get and sanitize the repo root path by removing the trailing slash if one exists + let repo_root_path = repo.path.replace(/\/$/, ""); + let sanitized_path = a_path.replace(/\/$/, ""); + + // Check if the sanitized path is exactly the repo root path + if (sanitized_path === repo_root_path) { + return PathType.REPO_ROOT_PATH; + } + + // Check if the sanitized path is a valid base path + if ( + sanitized_path.length < repo_root_path.length && + repo_root_path.startsWith(sanitized_path + "/") + ) { + return PathType.REPO_BASE_PATH; + } + + // Ensure the sanitized path starts with the repo root path + if (!sanitized_path.startsWith(repo_root_path + "/")) { + return PathType.UNKNOWN; + } + + // Get the relative path and its components + const relative_path = sanitized_path.substr(repo_root_path.length); + const relative_path_components = pathModule.splitPOSIXPath(relative_path); + + // Map the first component to its corresponding PathType + const pathMapping = { + project: [PathType.REPO_PATH, PathType.PROJECT_PATH, PathType.PROJECT_RECORD_PATH], + user: [PathType.REPO_PATH, PathType.USER_PATH, PathType.USER_RECORD_PATH], + }; + + const firstComponent = relative_path_components[0]; + if (pathMapping[firstComponent]) { + return ( + pathMapping[firstComponent][relative_path_components.length - 1] || PathType.UNKNOWN + ); + } + + return PathType.UNKNOWN; + } +} + +module.exports = { Repo, PathType }; diff --git a/core/database/foxx/api/repo_router.js b/core/database/foxx/api/repo_router.js index 54a83067a..d0c828e8a 100644 --- a/core/database/foxx/api/repo_router.js +++ b/core/database/foxx/api/repo_router.js @@ -1,17 +1,17 @@ -'use strict'; +"use strict"; -const createRouter = require('@arangodb/foxx/router'); +const createRouter = require("@arangodb/foxx/router"); const router = createRouter(); -const joi = require('joi'); +const joi = require("joi"); -const g_db = require('@arangodb').db; -const g_lib = require('./support'); -const g_tasks = require('./tasks'); +const g_db = require("@arangodb").db; +const g_lib = require("./support"); +const g_tasks = require("./tasks"); module.exports = router; - -router.get('/list', function(req, res) { +router + .get("/list", function (req, res) { var client; if (req.queryParams.client) { client = g_lib.getUserFromClientID(req.queryParams.client); @@ -35,9 +35,14 @@ router.get('/list', function(req, res) { result = g_db._query("for v in repo return {id:v._id,title:v.title,domain:v.domain}"); } else { if (req.queryParams.details) { - result = g_db._query("for v in 1..1 inbound @admin admin filter is_same_collection('repo',v) return v", { - admin: client._id - }).toArray(); + result = g_db + ._query( + "for v in 1..1 inbound @admin admin filter is_same_collection('repo',v) return v", + { + admin: client._id, + }, + ) + .toArray(); for (i in result) { repo = result[i]; repo.id = repo._id; @@ -46,31 +51,37 @@ router.get('/list', function(req, res) { delete repo._rev; } } else { - result = g_db._query("for v in 1..1 inbound @admin admin filter is_same_collection('repo',v) return {id:v._id,title:v.title,domain:v.domain}", { - admin: client._id - }); + result = g_db._query( + "for v in 1..1 inbound @admin admin filter is_same_collection('repo',v) return {id:v._id,title:v.title,domain:v.domain}", + { + admin: client._id, + }, + ); } } res.send(result); }) - .queryParam('client', joi.string().allow('').optional(), "Client ID") - .queryParam('details', joi.boolean().optional(), "Show additional record details") - .queryParam('all', joi.boolean().optional(), "List all repos (requires admin)") - .summary('List repo servers administered by client') - .description('List repo servers administered by client. If client is an admin and all flag is specified, will list all repos in system.'); - - -router.get('/view', function(req, res) { + .queryParam("client", joi.string().allow("").optional(), "Client ID") + .queryParam("details", joi.boolean().optional(), "Show additional record details") + .queryParam("all", joi.boolean().optional(), "List all repos (requires admin)") + .summary("List repo servers administered by client") + .description( + "List repo servers administered by client. If client is an admin and all flag is specified, will list all repos in system.", + ); + +router + .get("/view", function (req, res) { try { var repo = g_db.repo.document(req.queryParams.id); repo.admins = []; - var admins = g_db.admin.byExample({ - _from: req.queryParams.id - }).toArray(); - for (var i in admins) - repo.admins.push(admins[i]._to); + var admins = g_db.admin + .byExample({ + _from: req.queryParams.id, + }) + .toArray(); + for (var i in admins) repo.admins.push(admins[i]._to); repo.id = repo._id; delete repo._id; delete repo._key; @@ -81,29 +92,28 @@ router.get('/view', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('id', joi.string().required(), "Repo server ID") - .summary('View repo server record') - .description('View repo server record'); + .queryParam("id", joi.string().required(), "Repo server ID") + .summary("View repo server record") + .description("View repo server record"); - -router.post('/create', function(req, res) { +router + .post("/create", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u"], - write: ["repo", "admin"] + write: ["repo", "admin"], }, - action: function() { + action: function () { var client = g_lib.getUserFromClientID(req.queryParams.client); - if (!client.is_admin) - throw g_lib.ERR_PERM_DENIED; + if (!client.is_admin) throw g_lib.ERR_PERM_DENIED; var obj = { capacity: req.body.capacity, pub_key: req.body.pub_key, address: req.body.address, endpoint: req.body.endpoint, - path: req.body.path + path: req.body.path, }; g_lib.procInputParam(req.body, "id", false, obj); @@ -112,32 +122,41 @@ router.post('/create', function(req, res) { g_lib.procInputParam(req.body, "domain", false, obj); if (!obj.path.startsWith("/")) - throw [g_lib.ERR_INVALID_PARAM, "Repository path must be an absolute path file system path."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Repository path must be an absolute path file system path.", + ]; - if (!obj.path.endsWith("/")) - obj.path += "/"; + if (!obj.path.endsWith("/")) obj.path += "/"; var idx = obj.path.lastIndexOf("/", obj.path.length - 2); if (obj.path.substr(idx + 1, obj.path.length - idx - 2) != obj._key) - throw [g_lib.ERR_INVALID_PARAM, "Last part of repository path must be repository ID suffix (" + obj._key + ")"]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Last part of repository path must be repository ID suffix (" + + obj._key + + ")", + ]; if (req.body.exp_path) { obj.exp_path = req.body.exp_path; - if (!obj.exp_path.endsWith("/")) - obj.path += "/"; + if (!obj.exp_path.endsWith("/")) obj.path += "/"; } var repo = g_db.repo.save(obj, { - returnNew: true + returnNew: true, }); for (var i in req.body.admins) { if (!g_db._exists(req.body.admins[i])) - throw [g_lib.ERR_NOT_FOUND, "User, " + req.body.admins[i] + ", not found"]; + throw [ + g_lib.ERR_NOT_FOUND, + "User, " + req.body.admins[i] + ", not found", + ]; g_db.admin.save({ _from: repo._id, - _to: req.body.admins[i] + _to: req.body.admins[i], }); } @@ -146,39 +165,44 @@ router.post('/create', function(req, res) { delete repo.new._key; delete repo.new._rev; res.send([repo.new]); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.object({ - id: joi.string().required(), - title: joi.string().required(), - desc: joi.string().optional(), - domain: joi.string().optional(), - capacity: joi.number().integer().min(0).required(), - pub_key: joi.string().required(), - address: joi.string().required(), - endpoint: joi.string().required(), - path: joi.string().required(), - exp_path: joi.string().optional(), - admins: joi.array().items(joi.string()).required() - }).required(), 'Repo fields') - .summary('Create a repo server record') - .description('Create a repo server record.'); + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .object({ + id: joi.string().required(), + title: joi.string().required(), + desc: joi.string().optional(), + domain: joi.string().optional(), + capacity: joi.number().integer().min(0).required(), + pub_key: joi.string().required(), + address: joi.string().required(), + endpoint: joi.string().required(), + path: joi.string().required(), + exp_path: joi.string().optional(), + admins: joi.array().items(joi.string()).required(), + }) + .required(), + "Repo fields", + ) + .summary("Create a repo server record") + .description("Create a repo server record."); // TODO Add base path to repo - -router.post('/update', function(req, res) { +router + .post("/update", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u"], - write: ["repo", "admin"] + write: ["repo", "admin"], }, - action: function() { + action: function () { var client = g_lib.getUserFromClientID(req.queryParams.client); g_lib.ensureAdminPermRepo(client, req.body.id); var obj = {}; @@ -189,51 +213,56 @@ router.post('/update', function(req, res) { if (req.body.path) { if (!req.body.path.startsWith("/")) - throw [g_lib.ERR_INVALID_PARAM, "Repository path must be an absolute path file system path."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Repository path must be an absolute path file system path.", + ]; obj.path = req.body.path; - if (!obj.path.endsWith("/")) - obj.path += "/"; + if (!obj.path.endsWith("/")) obj.path += "/"; // Last part of storage path MUST end with the repo ID var idx = obj.path.lastIndexOf("/", obj.path.length - 2); var key = req.body.id.substr(5); if (obj.path.substr(idx + 1, obj.path.length - idx - 2) != key) - throw [g_lib.ERR_INVALID_PARAM, "Last part of repository path must be repository ID suffix (" + key + ")"]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Last part of repository path must be repository ID suffix (" + + key + + ")", + ]; } if (req.body.exp_path) { obj.exp_path = req.body.exp_path; - if (!obj.exp_path.endsWith("/")) - obj.exp_path += "/"; + if (!obj.exp_path.endsWith("/")) obj.exp_path += "/"; } - if (req.body.capacity) - obj.capacity = req.body.capacity; + if (req.body.capacity) obj.capacity = req.body.capacity; - if (req.body.pub_key) - obj.pub_key = req.body.pub_key; + if (req.body.pub_key) obj.pub_key = req.body.pub_key; - if (req.body.address) - obj.address = req.body.address; + if (req.body.address) obj.address = req.body.address; - if (req.body.endpoint) - obj.endpoint = req.body.endpoint; + if (req.body.endpoint) obj.endpoint = req.body.endpoint; var repo = g_db._update(req.body.id, obj, { - returnNew: true + returnNew: true, }); if (req.body.admins) { g_db.admin.removeByExample({ - _from: req.body.id + _from: req.body.id, }); for (var i in req.body.admins) { if (!g_db._exists(req.body.admins[i])) - throw [g_lib.ERR_NOT_FOUND, "User, " + req.body.admins[i] + ", not found"]; + throw [ + g_lib.ERR_NOT_FOUND, + "User, " + req.body.admins[i] + ", not found", + ]; g_db.admin.save({ _from: req.body.id, - _to: req.body.admins[i] + _to: req.body.admins[i], }); } } @@ -244,51 +273,61 @@ router.post('/update', function(req, res) { delete repo.new._rev; res.send([repo.new]); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .body(joi.object({ - id: joi.string().required(), - title: joi.string().optional(), - desc: joi.string().optional(), - domain: joi.string().optional(), - capacity: joi.number().optional(), - pub_key: joi.string().optional(), - address: joi.string().optional(), - endpoint: joi.string().optional(), - path: joi.string().optional(), - exp_path: joi.string().optional(), - admins: joi.array().items(joi.string()).optional() - }).required(), 'Repo fields') - .summary('Update a repo server record') - .description('Update a repo server record'); - - -router.get('/delete', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .body( + joi + .object({ + id: joi.string().required(), + title: joi.string().optional(), + desc: joi.string().optional(), + domain: joi.string().optional(), + capacity: joi.number().optional(), + pub_key: joi.string().optional(), + address: joi.string().optional(), + endpoint: joi.string().optional(), + path: joi.string().optional(), + exp_path: joi.string().optional(), + admins: joi.array().items(joi.string()).optional(), + }) + .required(), + "Repo fields", + ) + .summary("Update a repo server record") + .description("Update a repo server record"); + +router + .get("/delete", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["lock"], - write: ["repo", "admin", "alloc"] + write: ["repo", "admin", "alloc"], }, - action: function() { - + action: function () { // Begin by checking that there are no relationships to repo object, because // if they exist and we remove the repo record we break things const aqlQuery = ` FOR edge IN lock FILTER edge._to == @repoVertex RETURN edge._from - ` - var items_connected_to_repo = g_db._query(aqlQuery, { - repoVertex: req.queryParams.id - }).toArray(); + `; + var items_connected_to_repo = g_db + ._query(aqlQuery, { + repoVertex: req.queryParams.id, + }) + .toArray(); if (items_connected_to_repo.length > 0) { - throw [g_lib.ERR_IN_USE, "Cannot delete repo. The repository is in use: " + items_connected_to_repo.join(", ")]; + throw [ + g_lib.ERR_IN_USE, + "Cannot delete repo. The repository is in use: " + + items_connected_to_repo.join(", "), + ]; } var client = g_lib.getUserFromClientID(req.queryParams.client); @@ -297,40 +336,49 @@ router.get('/delete', function(req, res) { throw [g_lib.ERR_NOT_FOUND, "Repo, " + req.queryParams.id + ", not found"]; g_lib.ensureAdminPermRepo(client, req.queryParams.id); - const graph = require('@arangodb/general-graph')._graph('sdmsg'); + const graph = require("@arangodb/general-graph")._graph("sdmsg"); // Make sure there are no allocations present on repo var alloc = g_db._query("for v in 1..1 inbound @repo alloc return {id:v._id}", { - repo: req.queryParams.id + repo: req.queryParams.id, }); console.log(alloc); if (alloc.hasNext()) - throw [g_lib.ERR_IN_USE, "Cannot delete repo with associated allocations. Allocations still exist on the repository."]; + throw [ + g_lib.ERR_IN_USE, + "Cannot delete repo with associated allocations. Allocations still exist on the repository.", + ]; // Remove the repo vertex from the graph and all edges, this includes all // edges - such as the lock collection graph.repo.remove(req.queryParams.id); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().required(), "Repo server ID") - .summary('Delete repo server record') - .description('Delete repo server record'); - -/** @brief Calculate the total, per-repo size of selected items + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().required(), "Repo server ID") + .summary("Delete repo server record") + .description("Delete repo server record"); + +/** + * @function + * @description Calculates the total, per-repo size of selected items. + * Recursively analyzes collections but only counts each data record once regardless of how many places it is linked. + * This function is used for pre-processing data move operations (e.g., changing allocation or owner). * - * Recursively analyzes collections but only counts each data record once - * regardless of how many places it is linked. Used for pre-processing - * data move operations (change alloc or owner). + * @param {object} req - The request object, containing the query parameters. + * @param {object} res - The response object used to send the results. + * @returns {void} Sends an array of repository size statistics to the response. */ -router.get('/calc_size', function(req, res) { +router + .get("/calc_size", function (req, res) { g_lib.getUserFromClientID(req.queryParams.client); // TODO Check permissions - var i, repo_map = {}; + var i, + repo_map = {}; for (i in req.queryParams.items) { calcSize(req.queryParams.items[i], req.queryParams.recurse, 0, {}, repo_map); } @@ -345,20 +393,23 @@ router.get('/calc_size', function(req, res) { res.send(result); }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('items', joi.array().items(joi.string()).required(), "Array of data and/or collection IDs") - .queryParam('recurse', joi.boolean().required(), "Recursive flag") - .summary('Calculate per-repo sizes for specified data records and collections.') - .description('Calculate per-repo sizes for specified data records and collections.'); + .queryParam("client", joi.string().required(), "Client ID") + .queryParam( + "items", + joi.array().items(joi.string()).required(), + "Array of data and/or collection IDs", + ) + .queryParam("recurse", joi.boolean().required(), "Recursive flag") + .summary("Calculate per-repo sizes for specified data records and collections.") + .description("Calculate per-repo sizes for specified data records and collections."); function calcSize(a_item, a_recurse, a_depth, a_visited, a_result) { var item, loc, res; - if (a_item.charAt(0) == 'd') { - if (a_item in a_visited) - return; + if (a_item.charAt(0) == "d") { + if (a_item in a_visited) return; item = g_db.d.document(a_item); loc = g_db.loc.firstExample({ - _from: a_item + _from: a_item, }); // TODO - Should have a loc edge, but just skip if it doesn't if (loc) { @@ -372,47 +423,55 @@ function calcSize(a_item, a_recurse, a_depth, a_visited, a_result) { a_result[loc._to] = { records: 1, files: item.size ? 1 : 0, - total_sz: item.size + total_sz: item.size, }; } } a_visited[a_item] = true; - } else if (a_item.charAt(0) == 'c') { + } else if (a_item.charAt(0) == "c") { if (a_recurse || a_depth == 0) { item = g_db.c.document(a_item); var items = g_db._query("for v in 1..1 outbound @coll item return v._id", { - coll: a_item + coll: a_item, }); while (items.hasNext()) { calcSize(items.next(), a_recurse, a_depth + 1, a_visited, a_result); } } - } else - throw [g_lib.ERR_INVALID_PARAM, "Invalid item type for size calculation: " + a_item]; + } else throw [g_lib.ERR_INVALID_PARAM, "Invalid item type for size calculation: " + a_item]; } -router.get('/alloc/list/by_repo', function(req, res) { +router + .get("/alloc/list/by_repo", function (req, res) { var client = g_lib.getUserFromClientID(req.queryParams.client); var repo = g_db.repo.document(req.queryParams.repo); g_lib.ensureAdminPermRepo(client, repo._id); - var result = g_db._query("for v, e in 1..1 inbound @repo alloc sort v._id return {id:v._id,repo:@repo,data_limit:e.data_limit,data_size:e.data_size,rec_limit:e.rec_limit,rec_count:e.rec_count,path:e.path}", { - repo: repo._id - }).toArray(); + var result = g_db + ._query( + "for v, e in 1..1 inbound @repo alloc sort v._id return {id:v._id,repo:@repo,data_limit:e.data_limit,data_size:e.data_size,rec_limit:e.rec_limit,rec_count:e.rec_count,path:e.path}", + { + repo: repo._id, + }, + ) + .toArray(); res.send(result); }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('repo', joi.string().required(), "Repo ID") - .summary('List all allocations for a repo') - .description('List all allocations a repo'); - - -router.get('/alloc/list/by_owner', function(req, res) { - var obj, result = g_db.alloc.byExample({ - _from: req.queryParams.owner - }).toArray(); + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("repo", joi.string().required(), "Repo ID") + .summary("List all allocations for a repo") + .description("List all allocations a repo"); + +router + .get("/alloc/list/by_owner", function (req, res) { + var obj, + result = g_db.alloc + .byExample({ + _from: req.queryParams.owner, + }) + .toArray(); g_lib.sortAllocations(result); @@ -434,21 +493,24 @@ router.get('/alloc/list/by_owner', function(req, res) { res.send(result); }) - .queryParam('owner', joi.string().required(), "Owner ID (user or project)") - .queryParam('stats', joi.boolean().optional(), "Include statistics") - .summary('List owner\'s repo allocations') - .description('List owner\'s repo allocations (user or project ID)'); - + .queryParam("owner", joi.string().required(), "Owner ID (user or project)") + .queryParam("stats", joi.boolean().optional(), "Include statistics") + .summary("List owner's repo allocations") + .description("List owner's repo allocations (user or project ID)"); -router.get('/alloc/list/by_object', function(req, res) { +router + .get("/alloc/list/by_object", function (req, res) { var client = g_lib.getUserFromClientID(req.queryParams.client); var obj_id = g_lib.resolveID(req.queryParams.object, client); var owner_id = g_db.owner.firstExample({ - _from: obj_id + _from: obj_id, })._to; - var obj, result = g_db.alloc.byExample({ - _from: owner_id - }).toArray(); + var obj, + result = g_db.alloc + .byExample({ + _from: owner_id, + }) + .toArray(); g_lib.sortAllocations(result); @@ -466,30 +528,37 @@ router.get('/alloc/list/by_object', function(req, res) { res.send(result); }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('object', joi.string().required(), "Object ID (data or collection ID or alias)") - .summary('List object repo allocations') - .description('List object repo allocations'); + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("object", joi.string().required(), "Object ID (data or collection ID or alias)") + .summary("List object repo allocations") + .description("List object repo allocations"); - -router.get('/alloc/view', function(req, res) { +router + .get("/alloc/view", function (req, res) { try { - var owner_id, client = g_lib.getUserFromClientID(req.queryParams.client); + var owner_id, + client = g_lib.getUserFromClientID(req.queryParams.client); if (req.queryParams.subject) { owner_id = req.queryParams.subject; // Check permissions - if ((owner_id != client._id) && g_lib.getProjectRole(client._id, owner_id) == g_lib.PROJ_NO_ROLE) { + if ( + owner_id != client._id && + g_lib.getProjectRole(client._id, owner_id) == g_lib.PROJ_NO_ROLE + ) { throw g_lib.ERR_PERM_DENIED; } } else { owner_id = client._id; } - var obj, result = g_db.alloc.byExample({ - _from: owner_id, - _to: req.queryParams.repo - }).toArray(); + var obj, + result = g_db.alloc + .byExample({ + _from: owner_id, + _to: req.queryParams.repo, + }) + .toArray(); for (var i in result) { obj = result[i]; @@ -508,12 +577,11 @@ router.get('/alloc/view', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('repo', joi.string().required(), "Repo ID") - .queryParam('subject', joi.string().optional(), "User/project ID of allocation") - .summary('View allocation details') - .description('View allocation details'); - + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("repo", joi.string().required(), "Repo ID") + .queryParam("subject", joi.string().optional(), "User/project ID of allocation") + .summary("View allocation details") + .description("View allocation details"); function getAllocStats(a_repo, a_subject) { var sizes; @@ -521,18 +589,24 @@ function getAllocStats(a_repo, a_subject) { if (a_subject) { var alloc = g_db.alloc.firstExample({ _from: a_subject, - _to: a_repo + _to: a_repo, }); if (!alloc) - throw [g_lib.ERR_INVALID_PARAM, "Subject " + a_subject + " has no allocation on repo " + a_repo]; - - sizes = g_db._query("for v,e,p in 1..1 inbound @repo loc filter e.uid == @subj return v.size", { - repo: a_repo, - subj: a_subject - }); + throw [ + g_lib.ERR_INVALID_PARAM, + "Subject " + a_subject + " has no allocation on repo " + a_repo, + ]; + + sizes = g_db._query( + "for v,e,p in 1..1 inbound @repo loc filter e.uid == @subj return v.size", + { + repo: a_repo, + subj: a_subject, + }, + ); } else { sizes = g_db._query("for v in 1..1 inbound @repo loc return v.size", { - repo: a_repo + repo: a_repo, }); } @@ -560,11 +634,12 @@ function getAllocStats(a_repo, a_subject) { rec_count: rec_count, file_count: file_count, data_size: data_size, - histogram: hist + histogram: hist, }; } -router.get('/alloc/stats', function(req, res) { +router + .get("/alloc/stats", function (req, res) { try { var client = g_lib.getUserFromClientID(req.queryParams.client); g_lib.ensureAdminPermRepo(client, req.queryParams.repo); @@ -574,98 +649,120 @@ router.get('/alloc/stats', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('repo', joi.string().required(), "Repo ID") - .queryParam('subject', joi.string().optional(), "User/project ID of allocation") - .summary('View allocation statistics') - .description('View allocation statistics (or repo stats if no subject provided)'); - - -router.get('/alloc/create', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("repo", joi.string().required(), "Repo ID") + .queryParam("subject", joi.string().optional(), "User/project ID of allocation") + .summary("View allocation statistics") + .description("View allocation statistics (or repo stats if no subject provided)"); + +router + .get("/alloc/create", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn", "repo", "admin"], write: ["alloc"], - exclusive: ["task", "lock", "block"] + exclusive: ["task", "lock", "block"], }, - action: function() { + action: function () { var client = g_lib.getUserFromClientID(req.queryParams.client); var subject_id; if (req.queryParams.subject.startsWith("p/")) subject_id = req.queryParams.subject; - else - subject_id = g_lib.getUserFromClientID(req.queryParams.subject)._id; + else subject_id = g_lib.getUserFromClientID(req.queryParams.subject)._id; - var result = g_tasks.taskInitAllocCreate(client, req.queryParams.repo, subject_id, req.queryParams.data_limit, req.queryParams.rec_limit); + var result = g_tasks.taskInitAllocCreate( + client, + req.queryParams.repo, + subject_id, + req.queryParams.data_limit, + req.queryParams.rec_limit, + ); res.send(result); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().required(), "User/project ID to receive allocation") - .queryParam('repo', joi.string().required(), "Repo ID") - .queryParam('data_limit', joi.number().integer().min(1).required(), "Max total data size (bytes)") - .queryParam('rec_limit', joi.number().integer().min(1).required(), "Max number of records (files)") - .summary('Create user/project repo allocation') - .description('Create user repo/project allocation. Only repo admin can set allocations. Returns a task document.'); - - -router.get('/alloc/delete', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().required(), "User/project ID to receive allocation") + .queryParam("repo", joi.string().required(), "Repo ID") + .queryParam( + "data_limit", + joi.number().integer().min(1).required(), + "Max total data size (bytes)", + ) + .queryParam( + "rec_limit", + joi.number().integer().min(1).required(), + "Max number of records (files)", + ) + .summary("Create user/project repo allocation") + .description( + "Create user repo/project allocation. Only repo admin can set allocations. Returns a task document.", + ); + +router + .get("/alloc/delete", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn", "repo", "admin"], write: ["alloc"], - exclusive: ["task", "lock", "block"] + exclusive: ["task", "lock", "block"], }, - action: function() { + action: function () { var client = g_lib.getUserFromClientID(req.queryParams.client); var subject_id; if (req.queryParams.subject.startsWith("p/")) subject_id = req.queryParams.subject; - else - subject_id = g_lib.getUserFromClientID(req.queryParams.subject)._id; + else subject_id = g_lib.getUserFromClientID(req.queryParams.subject)._id; - var result = g_tasks.taskInitAllocDelete(client, req.queryParams.repo, subject_id); + var result = g_tasks.taskInitAllocDelete( + client, + req.queryParams.repo, + subject_id, + ); res.send(result); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().required(), "User/project ID to receive allocation") - .queryParam('repo', joi.string().required(), "Repo ID") - .summary('Delete user/project repo allocation') - .description('Delete user repo/project allocation. Only repo admin can set allocations. Returns a task document.'); - - -router.get('/alloc/set', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().required(), "User/project ID to receive allocation") + .queryParam("repo", joi.string().required(), "Repo ID") + .summary("Delete user/project repo allocation") + .description( + "Delete user repo/project allocation. Only repo admin can set allocations. Returns a task document.", + ); + +router + .get("/alloc/set", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn", "repo", "admin"], - write: ["alloc"] + write: ["alloc"], }, - action: function() { + action: function () { var client = g_lib.getUserFromClientID(req.queryParams.client); var subject_id; if (req.queryParams.subject.startsWith("p/")) subject_id = req.queryParams.subject; - else - subject_id = g_lib.getUserFromClientID(req.queryParams.subject)._id; + else subject_id = g_lib.getUserFromClientID(req.queryParams.subject)._id; if (!g_db._exists(req.queryParams.repo)) - throw [g_lib.ERR_NOT_FOUND, "Repo, '" + req.queryParams.repo + "', does not exist"]; + throw [ + g_lib.ERR_NOT_FOUND, + "Repo, '" + req.queryParams.repo + "', does not exist", + ]; if (!g_db._exists(subject_id)) throw [g_lib.ERR_NOT_FOUND, "Subject, " + subject_id + ", not found"]; @@ -676,84 +773,108 @@ router.get('/alloc/set', function(req, res) { var alloc = g_db.alloc.firstExample({ _from: subject_id, - _to: repo._id + _to: repo._id, }); if (!alloc) - throw [g_lib.ERR_NOT_FOUND, "Subject, '" + subject_id + "', has no allocation on " + repo._id]; + throw [ + g_lib.ERR_NOT_FOUND, + "Subject, '" + subject_id + "', has no allocation on " + repo._id, + ]; g_db.alloc.update(alloc._id, { data_limit: req.queryParams.data_limit, - rec_limit: req.queryParams.rec_limit + rec_limit: req.queryParams.rec_limit, }); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().required(), "User/project ID to receive allocation") - .queryParam('repo', joi.string().required(), "Repo ID") - .queryParam('data_limit', joi.number().integer().min(1).required(), "Max total data size (bytes)") - .queryParam('rec_limit', joi.number().integer().min(1).required(), "Max number of records (files)") - .summary('Set user/project repo allocation') - .description('Set user repo/project allocation. Only repo admin can set allocations.'); - - -router.get('/alloc/set/default', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().required(), "User/project ID to receive allocation") + .queryParam("repo", joi.string().required(), "Repo ID") + .queryParam( + "data_limit", + joi.number().integer().min(1).required(), + "Max total data size (bytes)", + ) + .queryParam( + "rec_limit", + joi.number().integer().min(1).required(), + "Max number of records (files)", + ) + .summary("Set user/project repo allocation") + .description("Set user repo/project allocation. Only repo admin can set allocations."); + +router + .get("/alloc/set/default", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn", "repo", "admin"], - write: ["alloc"] + write: ["alloc"], }, - action: function() { + action: function () { var client = g_lib.getUserFromClientID(req.queryParams.client); var subject_id = client._id; if (req.queryParams.subject) { if (req.queryParams.subject.startsWith("p/")) { if (!g_db._exists(subject_id)) - throw [g_lib.ERR_NOT_FOUND, "Project, " + req.queryParams.subject + ", not found"]; + throw [ + g_lib.ERR_NOT_FOUND, + "Project, " + req.queryParams.subject + ", not found", + ]; var role = g_lib.getProjectRole(client._id, req.queryParams.subject); if (role != g_lib.PROJ_MANAGER && role != g_lib.PROJ_ADMIN) - throw [g_lib.ERR_PERM_DENIED, "Setting default allocation on project requires admin/manager rights."]; + throw [ + g_lib.ERR_PERM_DENIED, + "Setting default allocation on project requires admin/manager rights.", + ]; subject_id = req.queryParams.subject; } else { subject_id = g_lib.getUserFromClientID(req.queryParams.subject)._id; if (subject_id != client._id && !client.is_admin) - throw [g_lib.ERR_PERM_DENIED, "Setting default allocation on user requires admin rights."]; + throw [ + g_lib.ERR_PERM_DENIED, + "Setting default allocation on user requires admin rights.", + ]; } } if (!g_db._exists(req.queryParams.repo)) - throw [g_lib.ERR_NOT_FOUND, "Repo, '" + req.queryParams.repo + "', does not exist"]; - - var alloc, allocs = g_db.alloc.byExample({ - _from: subject_id - }); + throw [ + g_lib.ERR_NOT_FOUND, + "Repo, '" + req.queryParams.repo + "', does not exist", + ]; + + var alloc, + allocs = g_db.alloc.byExample({ + _from: subject_id, + }); while (allocs.hasNext()) { alloc = allocs.next(); if (alloc._to == req.queryParams.repo) g_db.alloc.update(alloc._id, { - is_def: true + is_def: true, }); else if (alloc.is_def) g_db.alloc.update(alloc._id, { - is_def: false + is_def: false, }); } - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().optional(), "User/project ID to receive allocation") - .queryParam('repo', joi.string().required(), "Repo ID") - .summary('Set user/project repo allocation as default') - .description('Set user repo/project allocation as default.'); \ No newline at end of file + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().optional(), "User/project ID to receive allocation") + .queryParam("repo", joi.string().required(), "Repo ID") + .summary("Set user/project repo allocation as default") + .description("Set user repo/project allocation as default."); diff --git a/core/database/foxx/api/schema_router.js b/core/database/foxx/api/schema_router.js index 17a0a9d53..62d058fc7 100644 --- a/core/database/foxx/api/schema_router.js +++ b/core/database/foxx/api/schema_router.js @@ -1,25 +1,24 @@ -'use strict'; +"use strict"; -const createRouter = require('@arangodb/foxx/router'); +const createRouter = require("@arangodb/foxx/router"); const router = createRouter(); -const joi = require('joi'); +const joi = require("joi"); -const g_db = require('@arangodb').db; -const g_lib = require('./support'); -const g_graph = require('@arangodb/general-graph')._graph('sdmsg'); +const g_db = require("@arangodb").db; +const g_lib = require("./support"); +const g_graph = require("@arangodb/general-graph")._graph("sdmsg"); module.exports = router; function fixSchOwnNm(a_sch) { - if (!a_sch.own_nm) - return; + if (!a_sch.own_nm) return; - var j, nm = "", + var j, + nm = "", tmp = a_sch.own_nm.split(" "); for (j = 0; j < tmp.length - 1; j++) { - if (j) - nm += " "; + if (j) nm += " "; nm += tmp[j].charAt(0).toUpperCase() + tmp[j].substr(1); } @@ -30,13 +29,11 @@ function fixSchOwnNmAr(a_sch) { var sch, tmp, j, nm; for (var i in a_sch) { sch = a_sch[i]; - if (!sch.own_nm) - continue; + if (!sch.own_nm) continue; tmp = sch.own_nm.split(" "); nm = ""; for (j = 0; j < tmp.length - 1; j++) { - if (j) - nm += " "; + if (j) nm += " "; nm += tmp[j].charAt(0).toUpperCase() + tmp[j].substr(1); } sch.own_nm = nm; @@ -46,7 +43,10 @@ function fixSchOwnNmAr(a_sch) { // Find all references (internal and external), load them, then place in refs param (object) // This allows preloading schema dependencies for schema processing on client side function _resolveDeps(a_sch_id, a_refs) { - var res, dep, id, cur = new Set(), + var res, + dep, + id, + cur = new Set(), nxt; cur.add(a_sch_id); @@ -54,9 +54,9 @@ function _resolveDeps(a_sch_id, a_refs) { while (cur.size) { nxt = new Set(); - cur.forEach(function(a_id) { + cur.forEach(function (a_id) { res = g_db._query("for v in 1..1 outbound @id sch_dep return v", { - id: a_id + id: a_id, }); while (res.hasNext()) { @@ -73,18 +73,18 @@ function _resolveDeps(a_sch_id, a_refs) { } } - //==================== SCHEMA API FUNCTIONS -router.post('/create', function(req, res) { +router + .post("/create", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn"], - write: ["sch", "sch_dep"] + write: ["sch", "sch_dep"], }, waitForSync: true, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); // Schema validator has already been run at this point; however, DataFed further restricts @@ -95,12 +95,15 @@ router.post('/create', function(req, res) { cnt: 0, ver: 0, pub: req.body.pub, - def: req.body.def + def: req.body.def, }; if (req.body.sys) { if (!client.is_admin) - throw [g_lib.ERR_PERM_DENIED, "Creating a system schema requires admin privileges."]; + throw [ + g_lib.ERR_PERM_DENIED, + "Creating a system schema requires admin privileges.", + ]; if (!req.body.pub) throw [g_lib.ERR_INVALID_PARAM, "System schemas cannot be private."]; } else { @@ -112,7 +115,7 @@ router.post('/create', function(req, res) { g_lib.procInputParam(req.body, "desc", false, obj); var sch = g_db.sch.save(obj, { - returnNew: true + returnNew: true, }).new; updateSchemaRefs(sch); @@ -123,33 +126,38 @@ router.post('/create', function(req, res) { delete sch._rev; res.send([sch]); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().optional(), "Client ID") - .body(joi.object({ - id: joi.string().required(), - desc: joi.string().required(), - def: joi.object().required(), - pub: joi.boolean().optional().default(true), - sys: joi.boolean().optional().default(false) - }).required(), 'Schema fields') - .summary('Create schema') - .description('Create schema'); - - -router.post('/update', function(req, res) { + .queryParam("client", joi.string().optional(), "Client ID") + .body( + joi + .object({ + id: joi.string().required(), + desc: joi.string().required(), + def: joi.object().required(), + pub: joi.boolean().optional().default(true), + sys: joi.boolean().optional().default(false), + }) + .required(), + "Schema fields", + ) + .summary("Create schema") + .description("Create schema"); + +router + .post("/update", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn"], - write: ["sch", "sch_dep"] + write: ["sch", "sch_dep"], }, waitForSync: true, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var idx = req.queryParams.id.indexOf(":"); if (idx < 0) { @@ -159,23 +167,34 @@ router.post('/update', function(req, res) { sch_ver = parseInt(req.queryParams.id.substr(idx + 1)), sch_old = g_db.sch.firstExample({ id: sch_id, - ver: sch_ver + ver: sch_ver, }); if (!sch_old) { - throw [g_lib.ERR_NOT_FOUND, "Schema '" + req.queryParams.id + "' not found."]; + throw [ + g_lib.ERR_NOT_FOUND, + "Schema '" + req.queryParams.id + "' not found.", + ]; } // Cannot modify schemas that are in use if (sch_old.cnt) { - throw [g_lib.ERR_PERM_DENIED, "Schema is associated with data records - cannot update."]; + throw [ + g_lib.ERR_PERM_DENIED, + "Schema is associated with data records - cannot update.", + ]; } // Cannot modify schemas that are referenced by other schemas - if (g_db.sch_dep.firstExample({ - _to: sch_old._id - })) { - throw [g_lib.ERR_PERM_DENIED, "Schema is referenced by another schema - cannot update."]; + if ( + g_db.sch_dep.firstExample({ + _to: sch_old._id, + }) + ) { + throw [ + g_lib.ERR_PERM_DENIED, + "Schema is referenced by another schema - cannot update.", + ]; } if (sch_old.own_id != client._id && !client.is_admin) @@ -189,7 +208,10 @@ router.post('/update', function(req, res) { if (req.body.sys) { if (!client.is_admin) - throw [g_lib.ERR_PERM_DENIED, "Changing to a system schema requires admin privileges."]; + throw [ + g_lib.ERR_PERM_DENIED, + "Changing to a system schema requires admin privileges.", + ]; if (!sch_old.pub && !req.body.pub) throw [g_lib.ERR_INVALID_PARAM, "System schemas cannot be private."]; @@ -200,10 +222,17 @@ router.post('/update', function(req, res) { g_lib.procInputParam(req.body, "_sch_id", true, obj); - if (obj.id && (sch_old.ver || g_db.sch_ver.firstExample({ - _from: sch_old._id - }))) { - throw [g_lib.ERR_PERM_DENIED, "Cannot change schema ID once revisions exist."]; + if ( + obj.id && + (sch_old.ver || + g_db.sch_ver.firstExample({ + _from: sch_old._id, + })) + ) { + throw [ + g_lib.ERR_PERM_DENIED, + "Cannot change schema ID once revisions exist.", + ]; } g_lib.procInputParam(req.body, "desc", true, obj); @@ -216,7 +245,7 @@ router.post('/update', function(req, res) { var sch_new = g_db.sch.update(sch_old._id, obj, { returnNew: true, mergeObjects: false, - keepNull: false + keepNull: false, }).new; updateSchemaRefs(sch_new); @@ -227,33 +256,39 @@ router.post('/update', function(req, res) { delete sch_new._rev; res.send([sch_new]); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().optional(), "Client ID") - .queryParam('id', joi.string().required(), "Schema ID (with version suffix)") - .body(joi.object({ - id: joi.string().optional(), - desc: joi.string().optional(), - def: joi.object().optional(), - pub: joi.boolean().optional(), - sys: joi.boolean().optional() - }).required(), 'Schema fields') - .summary('Update schema') - .description('Update schema'); - -router.post('/revise', function(req, res) { + .queryParam("client", joi.string().optional(), "Client ID") + .queryParam("id", joi.string().required(), "Schema ID (with version suffix)") + .body( + joi + .object({ + id: joi.string().optional(), + desc: joi.string().optional(), + def: joi.object().optional(), + pub: joi.boolean().optional(), + sys: joi.boolean().optional(), + }) + .required(), + "Schema fields", + ) + .summary("Update schema") + .description("Update schema"); + +router + .post("/revise", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn"], - write: ["sch", "sch_dep", "sch_ver"] + write: ["sch", "sch_dep", "sch_ver"], }, waitForSync: true, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var idx = req.queryParams.id.indexOf(":"); if (idx < 0) { @@ -263,22 +298,32 @@ router.post('/revise', function(req, res) { sch_ver = parseInt(req.queryParams.id.substr(idx + 1)), sch = g_db.sch.firstExample({ id: sch_id, - ver: sch_ver + ver: sch_ver, }); if (!sch) - throw [g_lib.ERR_NOT_FOUND, "Schema '" + req.queryParams.id + "' not found."]; - - if (sch.own_id != client._id && !client.is_admin) - throw g_lib.ERR_PERM_DENIED; - - if (g_db.sch_ver.firstExample({ - _from: sch._id - })) - throw [g_lib.ERR_PERM_DENIED, "A revision of schema '" + req.queryParams.id + "' already exists."]; + throw [ + g_lib.ERR_NOT_FOUND, + "Schema '" + req.queryParams.id + "' not found.", + ]; + + if (sch.own_id != client._id && !client.is_admin) throw g_lib.ERR_PERM_DENIED; + + if ( + g_db.sch_ver.firstExample({ + _from: sch._id, + }) + ) + throw [ + g_lib.ERR_PERM_DENIED, + "A revision of schema '" + req.queryParams.id + "' already exists.", + ]; if (!sch.own_id && !client.is_admin) - throw [g_lib.ERR_PERM_DENIED, "Revising a system schema requires admin privileges."]; + throw [ + g_lib.ERR_PERM_DENIED, + "Revising a system schema requires admin privileges.", + ]; sch.ver++; sch.cnt = 0; @@ -294,7 +339,10 @@ router.post('/revise', function(req, res) { if (req.body.sys) { if (!client.is_admin) - throw [g_lib.ERR_PERM_DENIED, "Creating a system schema requires admin privileges."]; + throw [ + g_lib.ERR_PERM_DENIED, + "Creating a system schema requires admin privileges.", + ]; sch.own_id = null; sch.own_nm = null; @@ -316,12 +364,12 @@ router.post('/revise', function(req, res) { delete sch._rev; var sch_new = g_db.sch.save(sch, { - returnNew: true + returnNew: true, }).new; g_db.sch_ver.save({ _from: old_id, - _to: sch_new._id + _to: sch_new._id, }); updateSchemaRefs(sch_new); @@ -333,24 +381,30 @@ router.post('/revise', function(req, res) { delete sch_new._rev; res.send([sch_new]); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().optional(), "Client ID") - .queryParam('id', joi.string().required(), "Schema ID") - .body(joi.object({ - desc: joi.string().optional(), - def: joi.object().optional(), - pub: joi.boolean().optional(), - sys: joi.boolean().optional() - }).required(), 'Schema fields') - .summary('Revise schema') - .description('Revise schema'); - -router.post('/delete', function(req, res) { + .queryParam("client", joi.string().optional(), "Client ID") + .queryParam("id", joi.string().required(), "Schema ID") + .body( + joi + .object({ + desc: joi.string().optional(), + def: joi.object().optional(), + pub: joi.boolean().optional(), + sys: joi.boolean().optional(), + }) + .required(), + "Schema fields", + ) + .summary("Revise schema") + .description("Revise schema"); + +router + .post("/delete", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var idx = req.queryParams.id.indexOf(":"); @@ -361,33 +415,43 @@ router.post('/delete', function(req, res) { sch_ver = parseInt(req.queryParams.id.substr(idx + 1)), sch_old = g_db.sch.firstExample({ id: sch_id, - ver: sch_ver + ver: sch_ver, }); if (!sch_old) throw [g_lib.ERR_NOT_FOUND, "Schema '" + req.queryParams.id + "' not found."]; - if (sch_old.own_id != client._id && !client.is_admin) - throw g_lib.ERR_PERM_DENIED; + if (sch_old.own_id != client._id && !client.is_admin) throw g_lib.ERR_PERM_DENIED; // Cannot delete schemas that are in use if (sch_old.cnt) { - throw [g_lib.ERR_PERM_DENIED, "Schema is associated with data records - cannot update."]; + throw [ + g_lib.ERR_PERM_DENIED, + "Schema is associated with data records - cannot update.", + ]; } // Cannot delete schemas references by other schemas - if (g_db.sch_dep.firstExample({ - _to: sch_old._id - })) { - throw [g_lib.ERR_PERM_DENIED, "Schema is referenced by another schema - cannot update."]; + if ( + g_db.sch_dep.firstExample({ + _to: sch_old._id, + }) + ) { + throw [ + g_lib.ERR_PERM_DENIED, + "Schema is referenced by another schema - cannot update.", + ]; } // Only allow deletion of oldest and newest revisions of schemas - if (g_db.sch_ver.firstExample({ - _from: sch_old._id - }) && g_db.sch_ver.firstExample({ - _to: sch_old._id - })) { + if ( + g_db.sch_ver.firstExample({ + _from: sch_old._id, + }) && + g_db.sch_ver.firstExample({ + _to: sch_old._id, + }) + ) { throw [g_lib.ERR_PERM_DENIED, "Cannot delete intermediate schema revisions."]; } @@ -396,13 +460,13 @@ router.post('/delete', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().optional(), "Client ID") - .queryParam('id', joi.string().required(), "Schema ID") - .summary('Delete schema') - .description('Delete schema'); - + .queryParam("client", joi.string().optional(), "Client ID") + .queryParam("id", joi.string().required(), "Schema ID") + .summary("Delete schema") + .description("Delete schema"); -router.get('/view', function(req, res) { +router + .get("/view", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var idx = req.queryParams.id.indexOf(":"); @@ -413,11 +477,10 @@ router.get('/view', function(req, res) { sch_ver = parseInt(req.queryParams.id.substr(idx + 1)), sch = g_db.sch.firstExample({ id: sch_id, - ver: sch_ver + ver: sch_ver, }); - if (!sch) - throw [g_lib.ERR_NOT_FOUND, "Schema '" + req.queryParams.id + "' not found."]; + if (!sch) throw [g_lib.ERR_NOT_FOUND, "Schema '" + req.queryParams.id + "' not found."]; if (!(sch.pub || sch.own_id == client._id || client.is_admin)) throw g_lib.ERR_PERM_DENIED; @@ -429,14 +492,20 @@ router.get('/view', function(req, res) { } sch.depr = g_db.sch_ver.firstExample({ - _from: sch._id - }) ? true : false; - sch.uses = g_db._query("for i in 1..1 outbound @sch sch_dep return {id:i.id,ver:i.ver}", { - sch: sch._id - }).toArray(); - sch.used_by = g_db._query("for i in 1..1 inbound @sch sch_dep return {id:i.id,ver:i.ver}", { - sch: sch._id - }).toArray(); + _from: sch._id, + }) + ? true + : false; + sch.uses = g_db + ._query("for i in 1..1 outbound @sch sch_dep return {id:i.id,ver:i.ver}", { + sch: sch._id, + }) + .toArray(); + sch.used_by = g_db + ._query("for i in 1..1 inbound @sch sch_dep return {id:i.id,ver:i.ver}", { + sch: sch._id, + }) + .toArray(); delete sch._id; delete sch._key; @@ -449,23 +518,24 @@ router.get('/view', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().optional(), "Client ID") - .queryParam('id', joi.string().required(), "ID of schema") - .queryParam('resolve', joi.bool().optional(), "Resolve references") - .summary('View schema') - .description('View schema'); - - -router.get('/search', function(req, res) { + .queryParam("client", joi.string().optional(), "Client ID") + .queryParam("id", joi.string().required(), "ID of schema") + .queryParam("resolve", joi.bool().optional(), "Resolve references") + .summary("View schema") + .description("View schema"); + +router + .get("/search", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); - var qry, par = {}, - result, off = 0, + var qry, + par = {}, + result, + off = 0, cnt = 50, doc; - if (req.queryParams.offset != undefined) - off = req.queryParams.offset; + if (req.queryParams.offset != undefined) off = req.queryParams.offset; if (req.queryParams.count != undefined && req.queryParams.count <= 100) cnt = req.queryParams.count; @@ -479,7 +549,8 @@ router.get('/search', function(req, res) { qry += "(i.pub == true && i.own_id == @owner)"; } else { //qry += "(i.pub == true && analyzer(i.own_nm in tokens(@owner,'user_name'), 'user_name'))"; - qry += "(analyzer(i.own_nm in tokens(@owner,'user_name'), 'user_name') && (i.pub == true || i.own_id == @client_id))"; + qry += + "(analyzer(i.own_nm in tokens(@owner,'user_name'), 'user_name') && (i.pub == true || i.own_id == @client_id))"; par.client_id = client._id; } @@ -500,35 +571,48 @@ router.get('/search', function(req, res) { par.id = req.queryParams.id.toLowerCase(); } - if (req.queryParams.sort == g_lib.SORT_RELEVANCE && (req.queryParams.id || req.queryParams.text)) { + if ( + req.queryParams.sort == g_lib.SORT_RELEVANCE && + (req.queryParams.id || req.queryParams.text) + ) { qry += " let s = BM25(i) sort s desc"; } else if (req.queryParams.sort == g_lib.SORT_OWNER) { qry += " sort i.own_nm"; - qry += (req.queryParams.sort_rev ? " desc" : ""); + qry += req.queryParams.sort_rev ? " desc" : ""; } else { - if (req.queryParams.sort_rev) - qry += " sort i.id desc, i.ver"; - else - qry += " sort i.id,i.ver"; + if (req.queryParams.sort_rev) qry += " sort i.id desc, i.ver"; + else qry += " sort i.id,i.ver"; //qry += (req.queryParams.sort_rev?" desc":""); } - qry += " limit " + off + "," + cnt + " return {_id:i._id,id:i.id,ver:i.ver,cnt:i.cnt,pub:i.pub,own_nm:i.own_nm,own_id:i.own_id}"; + qry += + " limit " + + off + + "," + + cnt + + " return {_id:i._id,id:i.id,ver:i.ver,cnt:i.cnt,pub:i.pub,own_nm:i.own_nm,own_id:i.own_id}"; //qry += " filter (i.pub == true || i.own_id == @uid) sort i.id limit " + off + "," + cnt + " return {id:i.id,ver:i.ver,cnt:i.cnt,pub:i.pub,own_nm:i.own_nm,own_id:i.own_id}"; - result = g_db._query(qry, par, {}, { - fullCount: true - }); + result = g_db._query( + qry, + par, + {}, + { + fullCount: true, + }, + ); var tot = result.getExtra().stats.fullCount; result = result.toArray(); for (var i in result) { doc = result[i]; - if (g_db.sch_dep.firstExample({ - _to: doc._id - })) { + if ( + g_db.sch_dep.firstExample({ + _to: doc._id, + }) + ) { doc.ref = true; } } @@ -539,8 +623,8 @@ router.get('/search', function(req, res) { paging: { off: off, cnt: cnt, - tot: tot - } + tot: tot, + }, }); res.send(result); @@ -548,16 +632,16 @@ router.get('/search', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('id', joi.string().optional(), "ID (partial)") - .queryParam('text', joi.string().optional(), "Text or phrase") - .queryParam('owner', joi.string().optional(), "Owner ID") - .queryParam('sort', joi.number().integer().min(0).optional(), "Sort by") - .queryParam('sort_rev', joi.bool().optional(), "Sort in reverse order") - .queryParam('offset', joi.number().integer().min(0).optional(), "Offset") - .queryParam('count', joi.number().integer().min(1).optional(), "Count") - .summary('Search schemas') - .description('Search schema'); + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("id", joi.string().optional(), "ID (partial)") + .queryParam("text", joi.string().optional(), "Text or phrase") + .queryParam("owner", joi.string().optional(), "Owner ID") + .queryParam("sort", joi.number().integer().min(0).optional(), "Sort by") + .queryParam("sort_rev", joi.bool().optional(), "Sort in reverse order") + .queryParam("offset", joi.number().integer().min(0).optional(), "Offset") + .queryParam("count", joi.number().integer().min(1).optional(), "Count") + .summary("Search schemas") + .description("Search schema"); /* AQL rules: - Only a-z, A-Z, 0-9, and "_" are allowed @@ -566,7 +650,8 @@ router.get('/search', function(req, res) { - Can start with any number of "_", but must be followed by a-z, A-Z - not a number */ function validateKey(val) { - var code, i = 0, + var code, + i = 0, len = val.length; // Skip leading "_" @@ -581,8 +666,11 @@ function validateKey(val) { code = val.charCodeAt(i); // Fist char after prefix must be a letter - if ((code > 96 && code < 123) || // lower alpha (a-z) - (code > 64 && code < 91)) { // upper alpha (A-Z) + if ( + (code > 96 && code < 123) || // lower alpha (a-z) + (code > 64 && code < 91) + ) { + // upper alpha (A-Z) i++; } else { throw [g_lib.ERR_INVALID_CHAR, "Malformed property '" + val + "'."]; @@ -592,10 +680,13 @@ function validateKey(val) { for (; i < len; i++) { code = val.charCodeAt(i); - if (!(code > 47 && code < 58) && // numeric (0-9) + if ( + !(code > 47 && code < 58) && // numeric (0-9) !(code > 64 && code < 91) && // upper alpha (A-Z) !(code > 96 && code < 123) && // lower alpha (a-z) - code != 95) { // _ + code != 95 + ) { + // _ throw [g_lib.ERR_INVALID_CHAR, "Illegal character(s) in property '" + val + "'."]; } } @@ -607,7 +698,7 @@ function validateProperties(a_props) { validateKey(k); v = a_props[k]; - if (typeof v === 'object') { + if (typeof v === "object") { if (v.type === "object") { validateProperties(v.properties); } else if (v.type == "array" && Array.isArray(v.items)) { @@ -627,18 +718,25 @@ function updateSchemaRefs(a_sch) { // Find and update dependencies to other schemas (not versions) g_db.sch_dep.removeByExample({ - _from: a_sch._id + _from: a_sch._id, }); - var idx, id, ver, r, refs = new Set(); + var idx, + id, + ver, + r, + refs = new Set(); gatherRefs(a_sch.def.properties, refs); - refs.forEach(function(v) { + refs.forEach(function (v) { idx = v.indexOf(":"); if (idx < 0) - throw [g_lib.ERR_INVALID_PARAM, "Invalid reference ID '" + v + "' in schema (expected id:ver)."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Invalid reference ID '" + v + "' in schema (expected id:ver).", + ]; // TODO handle json pointer past # @@ -647,18 +745,16 @@ function updateSchemaRefs(a_sch) { r = g_db.sch.firstExample({ id: id, - ver: ver + ver: ver, }); - if (!r) - throw [g_lib.ERR_INVALID_PARAM, "Referenced schema '" + v + "' does not exist."]; + if (!r) throw [g_lib.ERR_INVALID_PARAM, "Referenced schema '" + v + "' does not exist."]; - if (r._id == a_sch._id) - throw [g_lib.ERR_INVALID_PARAM, "Schema references self."]; + if (r._id == a_sch._id) throw [g_lib.ERR_INVALID_PARAM, "Schema references self."]; g_graph.sch_dep.save({ _from: a_sch._id, - _to: r._id + _to: r._id, }); }); } @@ -669,10 +765,10 @@ function gatherRefs(a_doc, a_refs) { for (var k in a_doc) { v = a_doc[k]; - if (v !== null && (typeof v === 'object' || Array.isArray(v))) { + if (v !== null && (typeof v === "object" || Array.isArray(v))) { gatherRefs(v, a_refs); } else if (k == "$ref") { - if (typeof v !== 'string') + if (typeof v !== "string") throw [g_lib.ERR_INVALID_PARAM, "Invalid reference type in schema."]; // Add dependencies to external schemas, only once @@ -690,4 +786,4 @@ function gatherRefs(a_doc, a_refs) { } } } -} \ No newline at end of file +} diff --git a/core/database/foxx/api/support.js b/core/database/foxx/api/support.js index 87bfd3fe6..6133ed7c7 100644 --- a/core/database/foxx/api/support.js +++ b/core/database/foxx/api/support.js @@ -1,13 +1,12 @@ -'use strict'; +"use strict"; -const joi = require('joi'); +const joi = require("joi"); - -module.exports = (function() { +module.exports = (function () { var obj = {}; - obj.db = require('@arangodb').db; - obj.graph = require('@arangodb/general-graph')._graph('sdmsg'); + obj.db = require("@arangodb").db; + obj.graph = require("@arangodb/general-graph")._graph("sdmsg"); obj.PERM_RD_REC = 0x0001; // Read record info (description, keywords, details) obj.PERM_RD_META = 0x0002; // Read structured metadata @@ -28,7 +27,7 @@ module.exports = (function() { obj.PERM_NONE = 0x0000; obj.PERM_RD_ALL = 0x0007; // Read all obj.PERM_WR_ALL = 0x0038; // Write all - obj.PERM_ALL = 0x7FFF; + obj.PERM_ALL = 0x7fff; obj.PERM_MEMBER = 0x0047; // Project record perms obj.PERM_MANAGER = 0x0407; // Project record perms obj.PERM_PUBLIC = 0x0047; @@ -122,14 +121,14 @@ module.exports = (function() { obj.NOTE_MASK_INH_WARN = 0x0400; // Questions & info are not inherited obj.NOTE_MASK_INH_ERR = 0x0800; obj.NOTE_MASK_CLS_ANY = 0x1000; - obj.NOTE_MASK_LOC_ALL = 0x00FF; - obj.NOTE_MASK_INH_ALL = 0x0C00; + obj.NOTE_MASK_LOC_ALL = 0x00ff; + obj.NOTE_MASK_INH_ALL = 0x0c00; obj.NOTE_MASK_MD_ERR = 0x2000; obj.acl_schema = joi.object().keys({ id: joi.string().required(), grant: joi.number().optional(), - inhgrant: joi.number().optional() + inhgrant: joi.number().optional(), }); obj.ERR_INFO = []; @@ -166,7 +165,6 @@ module.exports = (function() { obj.ERR_ALLOCATION_EXCEEDED = obj.ERR_COUNT++; obj.ERR_INFO.push([400, "Storage allocation exceeded"]); - obj.CHARSET_ID = 0; obj.CHARSET_ALIAS = 1; obj.CHARSET_TOPIC = 2; @@ -182,7 +180,7 @@ module.exports = (function() { required: true, update: true, max_len: 80, - label: 'title' + label: "title", }, alias: { required: false, @@ -190,13 +188,13 @@ module.exports = (function() { max_len: 40, lower: true, charset: obj.CHARSET_ALIAS, - label: 'alias' + label: "alias", }, desc: { required: false, update: true, max_len: 2000, - label: 'description' + label: "description", }, summary: { required: false, @@ -204,7 +202,7 @@ module.exports = (function() { max_len: 500, in_field: "desc", out_field: "desc", - label: 'description' + label: "description", }, comment: { required: true, @@ -212,7 +210,7 @@ module.exports = (function() { max_len: 2000, in_field: "comment", out_field: "comment", - label: 'comment' + label: "comment", }, topic: { required: false, @@ -220,7 +218,7 @@ module.exports = (function() { max_len: 500, lower: true, charset: obj.CHARSET_TOPIC, - label: 'topic' + label: "topic", }, domain: { required: false, @@ -228,21 +226,21 @@ module.exports = (function() { max_len: 40, lower: true, charset: obj.CHARSET_ID, - label: 'domain' + label: "domain", }, source: { required: false, update: true, max_len: 4096, lower: false, - label: 'source' + label: "source", }, ext: { required: false, update: true, max_len: 40, lower: false, - label: 'extension' + label: "extension", }, gid: { required: true, @@ -250,7 +248,7 @@ module.exports = (function() { max_len: 40, lower: true, charset: obj.CHARSET_ID, - label: 'group ID' + label: "group ID", }, id: { required: true, @@ -259,7 +257,7 @@ module.exports = (function() { lower: true, charset: obj.CHARSET_ID, out_field: "_key", - label: 'ID' + label: "ID", }, doi: { required: false, @@ -267,7 +265,7 @@ module.exports = (function() { max_len: 40, lower: true, charset: obj.CHARSET_DOI, - label: 'doi' + label: "doi", }, data_url: { required: false, @@ -275,7 +273,7 @@ module.exports = (function() { max_len: 200, lower: false, charset: obj.CHARSET_URL, - label: 'data URL' + label: "data URL", }, sch_id: { required: false, @@ -283,7 +281,7 @@ module.exports = (function() { max_len: 120, lower: true, charset: obj.CHARSET_SCH_ID, - label: 'schema' + label: "schema", }, _sch_id: { required: true, @@ -293,8 +291,8 @@ module.exports = (function() { charset: obj.CHARSET_SCH_ID, in_field: "id", out_field: "id", - label: 'schema' - } + label: "schema", + }, }; obj.DEF_MAX_COLL = 50; @@ -304,21 +302,34 @@ module.exports = (function() { obj.GLOB_MAX_XFR_SIZE = 10000000000; // ~10GB //obj.GLOB_MAX_XFR_SIZE = 2000000; - obj.procInputParam = function(a_in, a_field, a_update, a_out) { - var val, spec = obj.field_reqs[a_field]; + // TODO: this will need to be updated every time the AccessTokenType enum is updated in SDMS.proto + obj.AccessTokenType = { + GENERIC: 1, + GLOBUS: 2, + GLOBUS_AUTH: 3, + GLOBUS_TRANSFER: 4, + GLOBUS_DEFAULT: 5, + ACCESS_SENTINEL: 255, + }; + + obj.procInputParam = function (a_in, a_field, a_update, a_out) { + var val, + spec = obj.field_reqs[a_field]; //console.log("procInput",a_field,",update:",a_update); if (!spec) { - throw [obj.ERR_INTERNAL_FAULT, "Input specification for '" + a_field + "' not found. Please contact system administrator."]; + throw [ + obj.ERR_INTERNAL_FAULT, + "Input specification for '" + + a_field + + "' not found. Please contact system administrator.", + ]; } - if (typeof a_in == "string") - val = a_in; - else if (spec.in_field) - val = a_in[spec.in_field]; - else - val = a_in[a_field]; + if (typeof a_in == "string") val = a_in; + else if (spec.in_field) val = a_in[spec.in_field]; + else val = a_in[a_field]; //console.log("init val",val); @@ -328,16 +339,21 @@ module.exports = (function() { return; } - if (val && val.length) - val = val.trim(); + if (val && val.length) val = val.trim(); if (val && val.length) { // Check length if specified - if (spec.max_len && (val.length > spec.max_len)) - throw [obj.ERR_INPUT_TOO_LONG, "'" + spec.label + "' field is too long. Maximum length is " + spec.max_len + "."]; - - if (spec.lower) - val = val.toLowerCase(); + if (spec.max_len && val.length > spec.max_len) + throw [ + obj.ERR_INPUT_TOO_LONG, + "'" + + spec.label + + "' field is too long. Maximum length is " + + spec.max_len + + ".", + ]; + + if (spec.lower) val = val.toLowerCase(); if (spec.charset != undefined) { var extra = obj.extra_chars[spec.charset]; @@ -345,51 +361,62 @@ module.exports = (function() { for (i = 0, len = val.length; i < len; i++) { code = val.charCodeAt(i); - if (!(code > 47 && code < 58) && // numeric (0-9) + if ( + !(code > 47 && code < 58) && // numeric (0-9) !(code > 64 && code < 91) && // upper alpha (A-Z) - !(code > 96 && code < 123)) { // lower alpha (a-z) + !(code > 96 && code < 123) + ) { + // lower alpha (a-z) if (extra.indexOf(val.charAt(i)) == -1) - throw [obj.ERR_INVALID_CHAR, "Invalid character(s) in '" + spec.label + "' field."]; + throw [ + obj.ERR_INVALID_CHAR, + "Invalid character(s) in '" + spec.label + "' field.", + ]; } } } //console.log("save new val:",val); - if (spec.out_field) - a_out[spec.out_field] = val; - else - a_out[a_field] = val; + if (spec.out_field) a_out[spec.out_field] = val; + else a_out[a_field] = val; } else { // Required params must have a value if (a_update) { if (val === "") { if (spec.required) - throw [obj.ERR_MISSING_REQ_PARAM, "Required field '" + spec.label + "' cannot be deleted."]; + throw [ + obj.ERR_MISSING_REQ_PARAM, + "Required field '" + spec.label + "' cannot be deleted.", + ]; - if (spec.out_field) - a_out[spec.out_field] = null; - else - a_out[a_field] = null; + if (spec.out_field) a_out[spec.out_field] = null; + else a_out[a_field] = null; } } else if (spec.required) throw [obj.ERR_MISSING_REQ_PARAM, "Missing required field '" + spec.label + "'."]; } }; - obj.isInteger = function(x) { - return (typeof x === 'number') && (x % 1 === 0); + obj.isInteger = function (x) { + return typeof x === "number" && x % 1 === 0; }; - obj.validatePassword = function(pw) { + obj.validatePassword = function (pw) { if (pw.length < obj.PASSWORD_MIN_LEN) { - throw [obj.ERR_INVALID_PARAM, "ERROR: password must be at least " + obj.PASSWORD_MIN_LEN + " characters in length."]; + throw [ + obj.ERR_INVALID_PARAM, + "ERROR: password must be at least " + + obj.PASSWORD_MIN_LEN + + " characters in length.", + ]; } - var i, j = 0, + var i, + j = 0, c; for (i in pw) { c = pw[i]; - if (c >= '0' && c <= '9') { + if (c >= "0" && c <= "9") { j |= 1; } else if (obj.pw_chars.indexOf(c) != -1) { j |= 2; @@ -400,9 +427,14 @@ module.exports = (function() { } if (j != 3) { - throw [obj.ERR_INVALID_PARAM, "ERROR: password must contain at least one number (0-9) and one special character (" + obj.pw_chars + ")."]; + throw [ + obj.ERR_INVALID_PARAM, + "ERROR: password must contain at least one number (0-9) and one special character (" + + obj.pw_chars + + ").", + ]; } - } + }; /* obj.isAlphaNumeric = function(str) { @@ -419,7 +451,7 @@ module.exports = (function() { return true; };*/ - obj.handleException = function(e, res) { + obj.handleException = function (e, res) { console.log("Service exception:", e); if (obj.isInteger(e) && e >= 0 && e < obj.ERR_COUNT) { @@ -451,7 +483,7 @@ module.exports = (function() { } }; - obj.isDomainAccount = function(a_client_id) { + obj.isDomainAccount = function (a_client_id) { // TODO This needs to have a test that doesn't conflict with email-style uids /*if ( a_client_id.indexOf( "." ) != -1 ) @@ -461,18 +493,16 @@ module.exports = (function() { }; // Quick check to determine if ID looks like a UUID (does not verify) - obj.isUUID = function(a_client_id) { - if (a_client_id.length == 36 && a_client_id.charAt(8) == "-") - return true; - else - return false; + obj.isUUID = function (a_client_id) { + if (a_client_id.length == 36 && a_client_id.charAt(8) == "-") return true; + else return false; }; // Quick check to see if a comma separated list of UUIDs has been provided // Must contain at least one comma - obj.isUUIDList = function(a_client_ids) { - if (a_client_ids.indexOf(',') > -1) { - var potential_uuids = a_client_ids.split(',') + obj.isUUIDList = function (a_client_ids) { + if (a_client_ids.indexOf(",") > -1) { + var potential_uuids = a_client_ids.split(","); for (var index in potential_uuids) { if (!obj.isUUID(potential_uuids[index])) { return false; @@ -485,7 +515,7 @@ module.exports = (function() { }; // Verify a_is is a valid UUID AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA (full check) - obj.isValidUUID = function(a_id) { + obj.isValidUUID = function (a_id) { if (a_id.length == 36) { var code; for (var i = 0; i < 36; i++) { @@ -495,9 +525,12 @@ module.exports = (function() { } } else { code = a_id.charCodeAt(i); - if (!(code > 47 && code < 58) && // numeric (0-9) + if ( + !(code > 47 && code < 58) && // numeric (0-9) !(code > 64 && code < 71) && // upper alpha (A-F) - !(code > 96 && code < 103)) { // lower alpha (a-F) + !(code > 96 && code < 103) + ) { + // lower alpha (a-F) return false; } } @@ -509,7 +542,7 @@ module.exports = (function() { return false; }; - obj.isFullGlobusPath = function(a_path, a_is_file = true) { + obj.isFullGlobusPath = function (a_path, a_is_file = true) { // Full Globus path can be UUID/ or legacy#name/ var idx = a_path.indexOf("/"); if (idx > 0) { @@ -538,53 +571,62 @@ module.exports = (function() { return false; }; - - obj.resolveUUIDsToID = function(uuid_list) { + obj.resolveUUIDsToID = function (uuid_list) { // This function will take a comma separated list of uuids as a string separate them and then either resolve them to a single uuid or // throw an error - var potential_uuids = uuid_list.split(',') + var potential_uuids = uuid_list.split(","); var uuids = []; for (var i in potential_uuids) { uuids.push("uuid/" + potential_uuids[i]); } - console.log("resolveUUIDsToID"); - console.log("uuids: ", uuids); - var result = obj.db._query("for i in ident filter i._to in @ids return distinct document(i._from)", { - ids: uuids - }).toArray(); + console.log("resolveUUIDsToID"); + console.log("uuids: ", uuids); + var result = obj.db + ._query("for i in ident filter i._to in @ids return distinct document(i._from)", { + ids: uuids, + }) + .toArray(); if (result.length !== 1) { throw [obj.ERR_NOT_FOUND, "No user matching Globus IDs found"]; } - var first_uuid = result[0]._id + var first_uuid = result[0]._id; // Next we need to make sure the provided ids are all the same if there is more than one for (var i = 1; i < result.length; i++) { if (first_uuid != result[i]._id) { - throw [obj.ERR_INVALID_PARAM, "uuid_list does not resolve to a single user, unable to unambiguously resolve user, it is possible that you have multiple accounts when you should have only a single one problematic ids are: " + first_uuid + " and " + array[i]]; + throw [ + obj.ERR_INVALID_PARAM, + "uuid_list does not resolve to a single user, unable to unambiguously resolve user, it is possible that you have multiple accounts when you should have only a single one problematic ids are: " + + first_uuid + + " and " + + array[i], + ]; } } return first_uuid; - } + }; - obj.resolveUUIDsToID_noexcept = function(uuid_list) { + obj.resolveUUIDsToID_noexcept = function (uuid_list) { // This function will take a comma separated list of uuids as a string separate them and then either resolve them to a single uuid or // throw an error - var potential_uuids = uuid_list.split(',') + var potential_uuids = uuid_list.split(","); var uuids = []; for (var i in potential_uuids) { uuids.push("uuid/" + potential_uuids[i]); } - console.log("resolveUUIDsToID_noexcept"); - console.log("uuids: ", uuids); - var result = obj.db._query("for i in ident filter i._to in @ids return distinct document(i._from)", { - ids: uuids - }).toArray(); + console.log("resolveUUIDsToID_noexcept"); + console.log("uuids: ", uuids); + var result = obj.db + ._query("for i in ident filter i._to in @ids return distinct document(i._from)", { + ids: uuids, + }) + .toArray(); if (result.length != 1) { throw [obj.ERR_NOT_FOUND, "No user matching Globus IDs found"]; } - var first_uuid = result[0]._id + var first_uuid = result[0]._id; // Next we need to make sure the provided ids are all the same if there is more than one for (var i = 1; i < result.length; i++) { console.log("resolveUUID comparing " + first_uuid + " with " + result[i]); @@ -593,9 +635,42 @@ module.exports = (function() { } } return first_uuid; - } + }; - obj.getUserFromClientID = function(a_client_id) { + /** + * Retrieves user information based on the provided client ID. + * + * The return value should be a client containing the following information: + * + * "_key" : "bob", + * "_id" : "u/bob", + * "name" : "bob junior", + * "name_first" : "bob", + * "name_last" : "jones", + * "is_admin" : true, + * "max_coll" : 50, + * "max_proj" : 10, + * "max_sav_qry" : 20, + * "email" : "bobjones@gmail.com" + * + * + * The client ID can be in the following formats: + * - SDMS uname (e.g., "xxxxx...") + * - UUID (e.g., "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") + * - Account (e.g., "domain.uname") + * + * UUIDs are defined by length and format, accounts have a "." (and known domains), + * and SDMS unames have no "." or "-" characters. + * + * @param {string} a_client_id - The client ID, which can be in various formats (SDMS uname, UUID, or Account). + * @throws {Array} Throws an error if the user does not exist, or the client ID is invalid. + * @returns {object} The user record containing details such as name, admin status, and email. + * + * @example + * const user = obj.getUserFromClientID('u/bob'); + * console.log(user.name); // "bob junior" + */ + obj.getUserFromClientID = function (a_client_id) { // Client ID can be an SDMS uname (xxxxx...), a UUID (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx), or an account (domain.uname) // UUID are defined by length and format, accounts have a "." (and known domains), SDMS unames have no "." or "-" characters @@ -605,24 +680,24 @@ module.exports = (function() { if (a_client_id.startsWith("u/")) { if (!obj.db.u.exists(a_client_id)) { throw [obj.ERR_INVALID_PARAM, "No such user '" + a_client_id + "'"]; - } + } return obj.db._document({ - _id: a_client_id + _id: a_client_id, }); } else if (obj.isDomainAccount(a_client_id)) { // Account params = { - 'id': 'accn/' + a_client_id + id: "accn/" + a_client_id, }; } else if (obj.isUUID(a_client_id)) { // UUID params = { - 'id': 'uuid/' + a_client_id + id: "uuid/" + a_client_id, }; } else if (obj.isUUIDList(a_client_id)) { // Check to make sure the UUIDs provided are all associated with the same DataFed account, if they are we can unambiguously - // determine the UUID, if they are not, then we will throw an error for now, + // determine the UUID, if they are not, then we will throw an error for now, var unambiguous_id = obj.resolveUUIDsToID(a_client_id); if (!unambiguous_id) { console.log("Undefined"); @@ -630,22 +705,22 @@ module.exports = (function() { } //params = { 'id': unambiguous_id }; return obj.db._document({ - _id: unambiguous_id + _id: unambiguous_id, }); - - } else { if (!obj.db.u.exists("u/" + a_client_id)) { throw [obj.ERR_INVALID_PARAM, "No such user 'u/" + a_client_id + "'"]; } return obj.db._document({ - _id: "u/" + a_client_id + _id: "u/" + a_client_id, }); } - var result = obj.db._query("for j in inbound @id ident return j", params, { - cache: true - }).toArray(); + var result = obj.db + ._query("for j in inbound @id ident return j", params, { + cache: true, + }) + .toArray(); if (result.length != 1) { //console.log("Client", a_client_id, "not found, params:", params ); @@ -655,32 +730,31 @@ module.exports = (function() { return result[0]; }; - obj.getUserFromClientID_noexcept = function(a_client_id) { + obj.getUserFromClientID_noexcept = function (a_client_id) { // Client ID can be an SDMS uname (xxxxx...), a UUID (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx), or an account (domain.uname) // UUID are defined by length and format, accounts have a "." (and known domains), SDMS unames have no "." or "-" characters var params; if (a_client_id.startsWith("u/")) { - if (!obj.db.u.exists(a_client_id)) - return; + if (!obj.db.u.exists(a_client_id)) return; return obj.db._document({ - _id: a_client_id + _id: a_client_id, }); } else if (obj.isDomainAccount(a_client_id)) { // Account params = { - 'id': 'accn/' + a_client_id + id: "accn/" + a_client_id, }; } else if (obj.isUUID(a_client_id)) { // UUID params = { - 'id': 'uuid/' + a_client_id + id: "uuid/" + a_client_id, }; } else if (obj.isUUIDList(a_client_id)) { // Check to make sure the UUIDs provided are all associated with the same DataFed account, if they are we can unambiguously - // determine the UUID, if they are not, then we will throw an error for now, + // determine the UUID, if they are not, then we will throw an error for now, var unambiguous_id = obj.resolveUUIDsToID_noexcept(a_client_id); if (!unambiguous_id) { console.log("Undefined"); @@ -688,21 +762,21 @@ module.exports = (function() { } //params = { 'id': unambiguous_id }; return obj.db._document({ - _id: unambiguous_id + _id: unambiguous_id, }); - } else { - if (!obj.db.u.exists("u/" + a_client_id)) - return; + if (!obj.db.u.exists("u/" + a_client_id)) return; return obj.db._document({ - _id: "u/" + a_client_id + _id: "u/" + a_client_id, }); } - var result = obj.db._query("for j in inbound @id ident return j", params, { - cache: true - }).toArray(); + var result = obj.db + ._query("for j in inbound @id ident return j", params, { + cache: true, + }) + .toArray(); if (result.length != 1) { return; @@ -711,37 +785,50 @@ module.exports = (function() { return result[0]; }; - obj.findUserFromUUIDs = function(a_uuids) { - console.log("findUserFromUUIDs"); - console.log("a_uuids: ", a_uuids); - var result = obj.db._query("for i in ident filter i._to in @ids return distinct document(i._from)", { - ids: a_uuids - }).toArray(); + obj.findUserFromUUIDs = function (a_uuids) { + console.log("findUserFromUUIDs"); + console.log("a_uuids: ", a_uuids); + var result = obj.db + ._query("for i in ident filter i._to in @ids return distinct document(i._from)", { + ids: a_uuids, + }) + .toArray(); if (result.length === 0) { throw [obj.ERR_NOT_FOUND, "No user matching Globus IDs found"]; - } else if (result.length > 1) { - throw [obj.ERR_NOT_FOUND, "Multiple DataFed accounts associated with the provided Globus identities" + result.toString() ]; - } + } else if (result.length > 1) { + throw [ + obj.ERR_NOT_FOUND, + "Multiple DataFed accounts associated with the provided Globus identities" + + result.toString(), + ]; + } return result[0]; }; - obj.uidFromPubKey = function(a_pub_key) { + obj.uidFromPubKey = function (a_pub_key) { //var result = obj.db._query( "for i in accn filter i.pub_key == @key let u = (for v in inbound i._id ident return v._key) return u[0]", { key: a_pub_key }).toArray(); - var result = obj.db._query("for i in u filter i.pub_key == @key return i._id", { - key: a_pub_key - }).toArray(); + var result = obj.db + ._query("for i in u filter i.pub_key == @key return i._id", { + key: a_pub_key, + }) + .toArray(); if (result.length !== 1) throw [obj.ERR_NOT_FOUND, "No user matching authentication key found"]; return result[0]; }; - obj.findUserFromPubKey = function(a_pub_key) { - var result = obj.db._query("for i in accn filter i.pub_key == @key let u = (for v in inbound i._id ident return v) return u[0]", { - key: a_pub_key - }).toArray(); + obj.findUserFromPubKey = function (a_pub_key) { + var result = obj.db + ._query( + "for i in accn filter i.pub_key == @key let u = (for v in inbound i._id ident return v) return u[0]", + { + key: a_pub_key, + }, + ) + .toArray(); //console.log( "key res:", result ); if (result.length != 1) @@ -750,62 +837,72 @@ module.exports = (function() { return result[0]; }; - obj.getAccessToken = function(a_user_id) { - var user = obj.db.u.document(a_user_id); - var exp_in = user.expiration - Math.floor(Date.now() / 1000); - var result = { + /** Get access token based on u._id + * + * @param {string} a_user_id - User ID field from database + * @returns {{acc_tok: string, ref_tok: string, acc_tok_exp_in: (number|number)}} - Access and refresh tokens, access expiration + * @throws Error - When user document does not exist, or when globus_token document does not exist + */ + obj.getAccessToken = function (a_user_id) { + let user = obj.db.u.document(a_user_id); // default to user token + const exp_in = user.expiration - Math.floor(Date.now() / 1000); + const result = { acc_tok: user.access, ref_tok: user.refresh, - acc_tok_exp_in: (exp_in > 0 ? exp_in : 0) + acc_tok_exp_in: exp_in > 0 ? exp_in : 0, }; return result; }; - obj.getProjectRole = function(a_client_id, a_proj_id) { - if (obj.db.owner.firstExample({ + obj.getProjectRole = function (a_client_id, a_proj_id) { + if ( + obj.db.owner.firstExample({ _from: a_proj_id, - _to: a_client_id - })) + _to: a_client_id, + }) + ) return obj.PROJ_ADMIN; - if (obj.db.admin.firstExample({ + if ( + obj.db.admin.firstExample({ _from: a_proj_id, - _to: a_client_id - })) + _to: a_client_id, + }) + ) return obj.PROJ_MANAGER; var grp = obj.db.g.firstExample({ uid: a_proj_id, - gid: "members" + gid: "members", }); - if (!grp) - return obj.PROJ_NO_ROLE; + if (!grp) return obj.PROJ_NO_ROLE; - if (obj.db.member.firstExample({ + if ( + obj.db.member.firstExample({ _from: grp._id, - _to: a_client_id - })) + _to: a_client_id, + }) + ) return obj.PROJ_MEMBER; - else - return obj.PROJ_NO_ROLE; + else return obj.PROJ_NO_ROLE; }; - obj.sortAllocations = function(allocs) { - allocs.sort(function(a, b) { - if (a.is_def) - return -1; - else if (b.is_def) - return 1; - else - return a._to < b._to ? -1 : 1; + obj.sortAllocations = function (allocs) { + allocs.sort(function (a, b) { + if (a.is_def) return -1; + else if (b.is_def) return 1; + else return a._to < b._to ? -1 : 1; }); }; - obj.assignRepo = function(a_user_id) { - var alloc, allocs = obj.db.alloc.byExample({ - _from: a_user_id - }).toArray(); + obj.assignRepo = function (a_user_id) { + var alloc, + allocs = obj.db.alloc + .byExample({ + _from: a_user_id, + }) + .toArray(); obj.sortAllocations(allocs); @@ -820,49 +917,54 @@ module.exports = (function() { return null; }; - obj.verifyRepo = function(a_user_id, a_repo_id) { + obj.verifyRepo = function (a_user_id, a_repo_id) { var alloc = obj.db.alloc.firstExample({ _from: a_user_id, - _to: a_repo_id + _to: a_repo_id, }); - if (!alloc) - throw [obj.ERR_NO_ALLOCATION, "No allocation on repo " + a_repo_id]; + if (!alloc) throw [obj.ERR_NO_ALLOCATION, "No allocation on repo " + a_repo_id]; if (alloc.data_size >= alloc.data_limit) - throw [obj.ERR_ALLOCATION_EXCEEDED, "Allocation data size exceeded (max: " + alloc.data_limit + ")"]; + throw [ + obj.ERR_ALLOCATION_EXCEEDED, + "Allocation data size exceeded (max: " + alloc.data_limit + ")", + ]; if (alloc.rec_count >= alloc.rec_limit) - throw [obj.ERR_ALLOCATION_EXCEEDED, "Allocation record count exceeded (max: " + alloc.rec_limit + ")"]; + throw [ + obj.ERR_ALLOCATION_EXCEEDED, + "Allocation record count exceeded (max: " + alloc.rec_limit + ")", + ]; return alloc; }; - obj.getRootID = function(owner_id) { + obj.getRootID = function (owner_id) { return "c/" + owner_id[0] + "_" + owner_id.substr(2) + "_root"; }; - obj.computeDataPath = function(a_loc, a_export) { + obj.computeDataPath = function (a_loc, a_export) { var repo = obj.db._document(a_loc._to); var repo_path = a_export ? repo.export_path : repo.path; - if (a_loc.uid.charAt(0) == 'u') { + if (a_loc.uid.charAt(0) == "u") { return repo_path + "user" + a_loc.uid.substr(1) + a_loc._from.substr(1); } else { return repo_path + "project" + a_loc.uid.substr(1) + a_loc._from.substr(1); } }; - obj.computeDataPathPrefix = function(a_repo_id, a_owner_id) { + obj.computeDataPathPrefix = function (a_repo_id, a_owner_id) { var repo = obj.db._document(a_repo_id); - if (a_owner_id.charAt(0) == 'u') { + if (a_owner_id.charAt(0) == "u") { return repo.path + "user" + a_owner_id.substr(1) + "/"; } else { return repo.path + "project" + a_owner_id.substr(1) + "/"; } }; - obj.getObject = function(a_obj_id, a_client) { + obj.getObject = function (a_obj_id, a_client) { var id = obj.resolveID(a_obj_id, a_client); if (!obj.db._exists(id)) @@ -873,13 +975,15 @@ module.exports = (function() { return doc; }; - obj.getDataCollectionLinkCount = function(id) { - return obj.db._query("for v in 1..1 inbound @id item return v._id", { - id: id - }).count(); + obj.getDataCollectionLinkCount = function (id) { + return obj.db + ._query("for v in 1..1 inbound @id item return v._id", { + id: id, + }) + .count(); }; - obj.hasAdminPermUser = function(a_client, a_user_id) { + obj.hasAdminPermUser = function (a_client, a_user_id) { //if ( a_client._id != a_user_id && !a_client.is_admin && !obj.db.owner.firstExample({ _from: a_user_id, _to: a_client._id }) && !obj.db.admin.firstExample({ _from: a_user_id, _to: a_client._id })){ if (a_client._id != a_user_id && !a_client.is_admin) { return false; @@ -888,168 +992,200 @@ module.exports = (function() { } }; - obj.hasAdminPermProj = function(a_client, a_proj_id) { - if (!a_client.is_admin && !obj.db.owner.firstExample({ + obj.hasAdminPermProj = function (a_client, a_proj_id) { + if ( + !a_client.is_admin && + !obj.db.owner.firstExample({ _from: a_proj_id, - _to: a_client._id - })) { + _to: a_client._id, + }) + ) { return false; } else { return true; } }; - obj.hasManagerPermProj = function(a_client, a_proj_id) { - if (!a_client.is_admin && !obj.db.owner.firstExample({ + obj.hasManagerPermProj = function (a_client, a_proj_id) { + if ( + !a_client.is_admin && + !obj.db.owner.firstExample({ _from: a_proj_id, - _to: a_client._id - }) && !obj.db.admin.firstExample({ + _to: a_client._id, + }) && + !obj.db.admin.firstExample({ _from: a_proj_id, - _to: a_client._id - })) { + _to: a_client._id, + }) + ) { return false; } else { return true; } }; - obj.hasAdminPermObjectLoaded = function(a_client, a_object) { + obj.hasAdminPermObjectLoaded = function (a_client, a_object) { // TODO Should collection creator have admin rights? if (a_object.owner == a_client._id || a_object.creator == a_client._id || a_client.is_admin) return true; - if (a_object.owner.charAt(0) == 'p') { - if (obj.db.owner.firstExample({ + if (a_object.owner.charAt(0) == "p") { + if ( + obj.db.owner.firstExample({ _from: a_object.owner, - _to: a_client._id - })) + _to: a_client._id, + }) + ) return true; - if (obj.db.admin.firstExample({ + if ( + obj.db.admin.firstExample({ _from: a_object.owner, - _to: a_client._id - })) + _to: a_client._id, + }) + ) return true; } return false; }; - obj.hasAdminPermObject = function(a_client, a_object_id) { - if (a_client.is_admin) - return true; + /** + * checks to make sure the client has admin permissions on an object + * + * @param {object} a_client - this is a user document i.e. + * + * + * "_key" : "bob", + * "_id" : "u/bob", + * "name" : "bob junior ", + * "name_first" : "bob", + * "name_last" : "jones", + * "is_admin" : true, + * "max_coll" : 50, + * "max_proj" : 10, + * "max_sav_qry" : 20, + * : + * "email" : "bobjones@gmail.com" + * + * @param {string} a_object_id - the identity of a record or collection or project + * + * "d/fdakjfla" + * "p/big_thing" + * "c/my_collection" + * + * @returns {boolean} - if client has admin rights on the object. + **/ + obj.hasAdminPermObject = function (a_client, a_object_id) { + if (a_client.is_admin) return true; var first_owner = obj.db.owner.firstExample({ - _from: a_object_id + _from: a_object_id, }); if (first_owner !== null) { var owner_id = first_owner._to; // obj.db.owner.firstExample({ _from: a_object_id })._to; } else { throw [obj.ERR_NOT_FOUND, "Data record for owner not found " + a_object_id + "."]; } - if (owner_id == a_client._id) - return true; + if (owner_id == a_client._id) return true; if (owner_id[0] == "p") { // Object owned by a project - if (obj.db.admin.firstExample({ + if ( + obj.db.admin.firstExample({ _from: owner_id, - _to: a_client._id - })) + _to: a_client._id, + }) + ) return true; - if (obj.db.owner.firstExample({ + if ( + obj.db.owner.firstExample({ _from: owner_id, - _to: a_client._id - })) + _to: a_client._id, + }) + ) return true; } - if (a_object_id[0] == 'd') { + if (a_object_id[0] == "d") { var data = obj.db._query("for i in d filter i._id == @id return i.creator", { - id: a_object_id + id: a_object_id, }); if (!data.hasNext()) { throw [obj.ERR_NOT_FOUND, "Data record " + a_object_id + " not found."]; } data = data.next(); - if (a_client._id == data) - return true; + if (a_client._id == data) return true; } return false; }; - obj.hasAdminPermRepo = function(a_client, a_repo_id) { - if (!a_client.is_admin && !obj.db.admin.firstExample({ + obj.hasAdminPermRepo = function (a_client, a_repo_id) { + if ( + !a_client.is_admin && + !obj.db.admin.firstExample({ _from: a_repo_id, - _to: a_client._id - })) { + _to: a_client._id, + }) + ) { return false; } else { return true; } }; - obj.ensureAdminPermUser = function(a_client, a_user_id) { - if (!obj.hasAdminPermUser(a_client, a_user_id)) - throw obj.ERR_PERM_DENIED; + obj.ensureAdminPermUser = function (a_client, a_user_id) { + if (!obj.hasAdminPermUser(a_client, a_user_id)) throw obj.ERR_PERM_DENIED; }; - obj.ensureAdminPermProj = function(a_client, a_user_id) { - if (!obj.hasAdminPermProj(a_client, a_user_id)) - throw obj.ERR_PERM_DENIED; + obj.ensureAdminPermProj = function (a_client, a_user_id) { + if (!obj.hasAdminPermProj(a_client, a_user_id)) throw obj.ERR_PERM_DENIED; }; - obj.ensureManagerPermProj = function(a_client, a_user_id) { - if (!obj.hasManagerPermProj(a_client, a_user_id)) - throw obj.ERR_PERM_DENIED; + obj.ensureManagerPermProj = function (a_client, a_user_id) { + if (!obj.hasManagerPermProj(a_client, a_user_id)) throw obj.ERR_PERM_DENIED; }; - obj.ensureAdminPermObject = function(a_client, a_object_id) { - if (!obj.hasAdminPermObject(a_client, a_object_id)) - throw obj.ERR_PERM_DENIED; + obj.ensureAdminPermObject = function (a_client, a_object_id) { + if (!obj.hasAdminPermObject(a_client, a_object_id)) throw obj.ERR_PERM_DENIED; }; - obj.ensureAdminPermRepo = function(a_client, a_repo_id) { - if (!obj.hasAdminPermRepo(a_client, a_repo_id)) - throw obj.ERR_PERM_DENIED; + obj.ensureAdminPermRepo = function (a_client, a_repo_id) { + if (!obj.hasAdminPermRepo(a_client, a_repo_id)) throw obj.ERR_PERM_DENIED; }; - obj.isSrcParentOfDest = function(a_src_id, a_dest_id) { + obj.isSrcParentOfDest = function (a_src_id, a_dest_id) { var parent; var child_id = a_dest_id; for (;;) { parent = obj.db.item.firstExample({ - _to: child_id + _to: child_id, }); - if (!parent) - return false; - if (parent._from == a_src_id) - return true; + if (!parent) return false; + if (parent._from == a_src_id) return true; child_id = parent._from; } }; // Data or Collection ID or alias - obj.resolveID = function(a_id, a_client) { - var id, i = a_id.indexOf('/'); + obj.resolveID = function (a_id, a_client) { + var id, + i = a_id.indexOf("/"); if (i != -1) { - if (!a_id.startsWith('d/') && !a_id.startsWith('c/') && !a_id.startsWith('p/')) + if (!a_id.startsWith("d/") && !a_id.startsWith("c/") && !a_id.startsWith("p/")) throw [obj.ERR_INVALID_PARAM, "Invalid ID '" + a_id + "'"]; id = a_id; } else { var alias_id = "a/"; - if (a_id.indexOf(":") == -1) - alias_id += "u:" + a_client._key + ":" + a_id; - else - alias_id += a_id; + if (a_id.indexOf(":") == -1) alias_id += "u:" + a_client._key + ":" + a_id; + else alias_id += a_id; var alias = obj.db.alias.firstExample({ - _to: alias_id + _to: alias_id, }); - if (!alias) - throw [obj.ERR_NOT_FOUND, "Alias '" + a_id + "' does not exist"]; + if (!alias) throw [obj.ERR_NOT_FOUND, "Alias '" + a_id + "' does not exist"]; id = alias._from; } @@ -1061,30 +1197,32 @@ module.exports = (function() { return id; }; - obj.resolveDataID = function(a_id, a_client) { - var alias, id, i = a_id.indexOf('/'); + obj.resolveDataID = function (a_id, a_client) { + var alias, + id, + i = a_id.indexOf("/"); if (i != -1) { - if (!a_id.startsWith('d/')) + if (!a_id.startsWith("d/")) throw [obj.ERR_INVALID_PARAM, "Invalid data record ID '" + a_id + "'"]; id = a_id; } else { var alias_id = "a/"; - if (a_id.indexOf(":") == -1) - alias_id += "u:" + a_client._key + ":" + a_id; - else - alias_id += a_id; + if (a_id.indexOf(":") == -1) alias_id += "u:" + a_client._key + ":" + a_id; + else alias_id += a_id; alias = obj.db.alias.firstExample({ - _to: alias_id + _to: alias_id, }); - if (!alias) - throw [obj.ERR_NOT_FOUND, "Alias '" + a_id + "' does not exist"]; + if (!alias) throw [obj.ERR_NOT_FOUND, "Alias '" + a_id + "' does not exist"]; id = alias._from; - if (!id.startsWith('d/')) - throw [obj.ERR_INVALID_PARAM, "Alias '" + a_id + "' does not identify a data record"]; + if (!id.startsWith("d/")) + throw [ + obj.ERR_INVALID_PARAM, + "Alias '" + a_id + "' does not identify a data record", + ]; } if (!obj.db.d.exists(id)) { @@ -1094,30 +1232,31 @@ module.exports = (function() { return id; }; - obj.resolveCollID = function(a_id, a_client) { - var id, i = a_id.indexOf('/'); + obj.resolveCollID = function (a_id, a_client) { + var id, + i = a_id.indexOf("/"); if (i != -1) { - if (!a_id.startsWith('c/')) + if (!a_id.startsWith("c/")) throw [obj.ERR_INVALID_PARAM, "Invalid collection ID '" + a_id + "'"]; id = a_id; } else { var alias_id = "a/"; - if (a_client && a_id.indexOf(":") == -1) - alias_id += "u:" + a_client._key + ":" + a_id; - else - alias_id += a_id; + if (a_client && a_id.indexOf(":") == -1) alias_id += "u:" + a_client._key + ":" + a_id; + else alias_id += a_id; var alias = obj.db.alias.firstExample({ - _to: alias_id + _to: alias_id, }); - if (!alias) - throw [obj.ERR_NOT_FOUND, "Alias '" + a_id + "' does not exist"]; + if (!alias) throw [obj.ERR_NOT_FOUND, "Alias '" + a_id + "' does not exist"]; id = alias._from; - if (!id.startsWith('c/')) - throw [obj.ERR_INVALID_PARAM, "Alias '" + a_id + "' does not identify a collection"]; + if (!id.startsWith("c/")) + throw [ + obj.ERR_INVALID_PARAM, + "Alias '" + a_id + "' does not identify a collection", + ]; } if (!obj.db.c.exists(id)) { @@ -1127,30 +1266,32 @@ module.exports = (function() { return id; }; - obj.resolveCollID2 = function(a_id, a_ctxt) { - var id, i = a_id.indexOf('/'); + obj.resolveCollID2 = function (a_id, a_ctxt) { + var id, + i = a_id.indexOf("/"); if (i != -1) { - if (!a_id.startsWith('c/')) + if (!a_id.startsWith("c/")) throw [obj.ERR_INVALID_PARAM, "Invalid collection ID '" + a_id + "'"]; id = a_id; } else { var alias_id = "a/"; if (a_ctxt && a_id.indexOf(":") == -1) alias_id += a_ctxt.charAt(0) + ":" + a_ctxt.substr(2) + ":" + a_id; - else - alias_id += a_id; + else alias_id += a_id; var alias = obj.db.alias.firstExample({ - _to: alias_id + _to: alias_id, }); - if (!alias) - throw [obj.ERR_NOT_FOUND, "Alias '" + alias_id + "' does not exist"]; + if (!alias) throw [obj.ERR_NOT_FOUND, "Alias '" + alias_id + "' does not exist"]; id = alias._from; - if (!id.startsWith('c/')) - throw [obj.ERR_INVALID_PARAM, "Alias '" + alias_id + "' does not identify a collection"]; + if (!id.startsWith("c/")) + throw [ + obj.ERR_INVALID_PARAM, + "Alias '" + alias_id + "' does not identify a collection", + ]; } if (!obj.db.c.exists(id)) { @@ -1160,31 +1301,32 @@ module.exports = (function() { return id; }; - obj.resolveDataCollID = function(a_id, a_client) { - var id, i = a_id.indexOf('/'); + obj.resolveDataCollID = function (a_id, a_client) { + var id, + i = a_id.indexOf("/"); if (i != -1) { - if (!a_id.startsWith('d/') && !a_id.startsWith('c/')) + if (!a_id.startsWith("d/") && !a_id.startsWith("c/")) throw [obj.ERR_INVALID_PARAM, "Invalid ID '" + a_id + "'"]; id = a_id; } else { var alias_id = "a/"; - if (a_client && a_id.indexOf(":") == -1) - alias_id += "u:" + a_client._key + ":" + a_id; - else - alias_id += a_id; + if (a_client && a_id.indexOf(":") == -1) alias_id += "u:" + a_client._key + ":" + a_id; + else alias_id += a_id; var alias = obj.db.alias.firstExample({ - _to: alias_id + _to: alias_id, }); - if (!alias) - throw [obj.ERR_NOT_FOUND, "Alias '" + a_id + "' does not exist"]; + if (!alias) throw [obj.ERR_NOT_FOUND, "Alias '" + a_id + "' does not exist"]; id = alias._from; } if (!obj.db._exists(id)) { - throw [obj.ERR_INVALID_PARAM, (id.charAt(0) == 'd' ? "Data record '" : "Collection '") + id + "' does not exist."]; + throw [ + obj.ERR_INVALID_PARAM, + (id.charAt(0) == "d" ? "Data record '" : "Collection '") + id + "' does not exist.", + ]; } return id; @@ -1199,22 +1341,25 @@ module.exports = (function() { */ // For use when creating a new record - obj.getCollCategoryTags = function(a_coll_id) { + obj.getCollCategoryTags = function (a_coll_id) { var coll = obj.db.c.document(a_coll_id), ctx = obj.catalogCalcParCtxt(coll, {}); - if (ctx.pub) - return Array.from(ctx.tags); + if (ctx.pub) return Array.from(ctx.tags); }; - obj.catalogUpdateRecord = function(a_data, a_coll, a_ctx, a_visited = {}) { - var p, par = obj.db.item.byExample({ - _to: a_data._id + obj.catalogUpdateRecord = function (a_data, a_coll, a_ctx, a_visited = {}) { + var p, + par = obj.db.item.byExample({ + _to: a_data._id, }), - tmp, _ctx = (a_ctx ? a_ctx : { - pub: false, - tags: new Set() - }); + tmp, + _ctx = a_ctx + ? a_ctx + : { + pub: false, + tags: new Set(), + }; while (par.hasNext()) { p = par.next(); @@ -1233,33 +1378,38 @@ module.exports = (function() { if (_ctx === a_ctx) { _ctx = { pub: a_ctx.pub, - tags: new Set(a_ctx.tags) + tags: new Set(a_ctx.tags), }; } - _ctx.pub = (_ctx.pub || tmp.pub); + _ctx.pub = _ctx.pub || tmp.pub; tmp.tags.forEach(_ctx.tags.add, _ctx.tags); } } } // Update record with pub flag & tags - obj.db._update(a_data._id, { - public: _ctx.pub, - cat_tags: _ctx.pub ? Array.from(_ctx.tags) : null - }, { - keepNull: false - }); + obj.db._update( + a_data._id, + { + public: _ctx.pub, + cat_tags: _ctx.pub ? Array.from(_ctx.tags) : null, + }, + { + keepNull: false, + }, + ); }; - obj.catalogCalcParCtxt = function(a_coll, a_visited) { + obj.catalogCalcParCtxt = function (a_coll, a_visited) { //console.log("catalogCalcParCtxt",a_coll._id); - var c, ctx = { + var c, + ctx = { pub: a_coll.public ? true : false, - tags: new Set(a_coll.cat_tags ? a_coll.cat_tags : []) + tags: new Set(a_coll.cat_tags ? a_coll.cat_tags : []), }, item = obj.db.item.firstExample({ - _to: a_coll._id + _to: a_coll._id, }); while (item) { @@ -1267,7 +1417,7 @@ module.exports = (function() { c = a_visited[item._from]; if (c) { - ctx.pub = (ctx.pub || c.pub); + ctx.pub = ctx.pub || c.pub; if (c.tags) { c.tags.forEach(ctx.tags.add, ctx.tags); } @@ -1275,14 +1425,14 @@ module.exports = (function() { break; } else { c = obj.db.c.document(item._from); - ctx.pub = (ctx.pub || c.public); + ctx.pub = ctx.pub || c.public; if (c.cat_tags) { c.cat_tags.forEach(ctx.tags.add, ctx.tags); } } item = obj.db.item.firstExample({ - _to: item._from + _to: item._from, }); } //console.log("update visited",ctx); @@ -1297,13 +1447,13 @@ module.exports = (function() { calling this function. Note that the public state and category tags of child collections are not changed by this function. */ - obj.catalogUpdateColl = function(a_coll, a_ctx, a_visited = {}) { + obj.catalogUpdateColl = function (a_coll, a_ctx, a_visited = {}) { var ctx; if (a_ctx) { ctx = { - pub: (a_coll.public || a_ctx.pub), - tags: new Set(a_ctx.tags) + pub: a_coll.public || a_ctx.pub, + tags: new Set(a_ctx.tags), }; if (a_coll.cat_tags) { a_coll.cat_tags.forEach(ctx.tags.add, ctx.tags); @@ -1314,14 +1464,19 @@ module.exports = (function() { ctx = obj.catalogCalcParCtxt(a_coll, a_visited); } - var p, par, _ctx, tmp, item, items = obj.db.item.byExample({ - _from: a_coll._id - }); + var p, + par, + _ctx, + tmp, + item, + items = obj.db.item.byExample({ + _from: a_coll._id, + }); while (items.hasNext()) { item = items.next(); - if (item._to.charAt(0) == 'c') { + if (item._to.charAt(0) == "c") { par = obj.db.c.document(item._to); obj.catalogUpdateColl(par, ctx, a_visited); } else { @@ -1329,7 +1484,7 @@ module.exports = (function() { // Determine if this record is published by other collections par = obj.db.item.byExample({ - _to: item._to + _to: item._to, }); _ctx = ctx; @@ -1358,11 +1513,11 @@ module.exports = (function() { if (_ctx === ctx) { _ctx = { pub: ctx.pub, - tags: new Set(ctx.tags) + tags: new Set(ctx.tags), }; } - _ctx.pub = (_ctx.pub || tmp.pub); + _ctx.pub = _ctx.pub || tmp.pub; tmp.tags.forEach(_ctx.tags.add, _ctx.tags); } } else { @@ -1371,19 +1526,23 @@ module.exports = (function() { } // Update record with pub flag & tags - obj.db._update(item._to, { - public: _ctx.pub, - cat_tags: _ctx.pub ? Array.from(_ctx.tags) : null - }, { - keepNull: false - }); + obj.db._update( + item._to, + { + public: _ctx.pub, + cat_tags: _ctx.pub ? Array.from(_ctx.tags) : null, + }, + { + keepNull: false, + }, + ); } } }; - - obj.topicCreate = function(a_topics, a_idx, a_par_id, a_owner_id) { - var topic, par_id = a_par_id; //, doc; + obj.topicCreate = function (a_topics, a_idx, a_par_id, a_owner_id) { + var topic, + par_id = a_par_id; //, doc; for (var i = a_idx; i < a_topics.length; i++) { topic = a_topics[i]; @@ -1394,16 +1553,19 @@ module.exports = (function() { obj.db.tag.save({ _key: topic, count: 1 }); }*/ - topic = obj.db.t.save({ - title: topic, - creator: a_owner_id, - coll_cnt: 1 - }, { - returnNew: true - }); + topic = obj.db.t.save( + { + title: topic, + creator: a_owner_id, + coll_cnt: 1, + }, + { + returnNew: true, + }, + ); obj.db.top.save({ _from: topic._id, - _to: par_id + _to: par_id, }); par_id = topic._id; } @@ -1411,20 +1573,20 @@ module.exports = (function() { return par_id; }; - obj.topicLink = function(a_topic, a_coll_id, a_owner_id) { - var i, topics = a_topic.split("."); + obj.topicLink = function (a_topic, a_coll_id, a_owner_id) { + var i, + topics = a_topic.split("."); // Detect misplaced topic delimiters for (i in topics) { - if (topics[i].length === 0) - throw [obj.ERR_INVALID_PARAM, "Invalid category"]; + if (topics[i].length === 0) throw [obj.ERR_INVALID_PARAM, "Invalid category"]; } var topic, parent; //,tag; // Find or create top-level topics parent = obj.db._query("for i in t filter i.top == true && i.title == @title return i", { - title: topics[0] + title: topics[0], }); if (parent.hasNext()) { @@ -1432,7 +1594,7 @@ module.exports = (function() { // Increment coll_cnt obj.db.t.update(parent._id, { - coll_cnt: parent.coll_cnt + 1 + coll_cnt: parent.coll_cnt + 1, }); parent = parent._id; @@ -1443,15 +1605,18 @@ module.exports = (function() { }*/ for (i = 1; i < topics.length; i++) { - topic = obj.db._query("for v in 1..1 inbound @par top filter v.title == @title filter is_same_collection('t',v) return v", { - par: parent, - title: topics[i] - }); + topic = obj.db._query( + "for v in 1..1 inbound @par top filter v.title == @title filter is_same_collection('t',v) return v", + { + par: parent, + title: topics[i], + }, + ); if (topic.hasNext()) { parent = topic.next(); // Increment coll_cnt obj.db.t.update(parent._id, { - coll_cnt: parent.coll_cnt + 1 + coll_cnt: parent.coll_cnt + 1, }); /*if (( tag = obj.db.tag.firstExample({ _key: topics[i] })) != null ){ @@ -1467,40 +1632,46 @@ module.exports = (function() { } } } else { - parent = obj.db.t.save({ - title: topics[0], - top: true, - creator: a_owner_id, - coll_cnt: 1 - }, { - returnNew: true - })._id; + parent = obj.db.t.save( + { + title: topics[0], + top: true, + creator: a_owner_id, + coll_cnt: 1, + }, + { + returnNew: true, + }, + )._id; parent = this.topicCreate(topics, 1, parent, a_owner_id); } - if (!obj.db.top.firstExample({ + if ( + !obj.db.top.firstExample({ _from: a_coll_id, - _to: parent - })) { + _to: parent, + }) + ) { obj.db.top.save({ _from: a_coll_id, - _to: parent + _to: parent, }); } }; - obj.topicUnlink = function(a_coll_id) { + obj.topicUnlink = function (a_coll_id) { //console.log("topicUnlink"); var top_lnk = obj.db.top.firstExample({ - _from: a_coll_id + _from: a_coll_id, }); if (!top_lnk) { return; } // Save parent topic id, delete link from collection - var topic, topic_id = top_lnk._to, + var topic, + topic_id = top_lnk._to, dec_only = false; //, tags = []; //console.log("rem top lnk",top_lnk._id); obj.db.top.remove(top_lnk); @@ -1511,19 +1682,23 @@ module.exports = (function() { // Decrement coll_cnt obj.db.t.update(topic._id, { - coll_cnt: topic.coll_cnt - 1 + coll_cnt: topic.coll_cnt - 1, }); //tags.push( topic.title ); // If parent is admin controlled, or other topics are linked to parent, stop - if (dec_only || topic.admin || obj.db.top.firstExample({ - _to: topic_id - })) { + if ( + dec_only || + topic.admin || + obj.db.top.firstExample({ + _to: topic_id, + }) + ) { //console.log("stop no del topic",topic); dec_only = true; top_lnk = obj.db.top.firstExample({ - _from: topic_id + _from: topic_id, }); if (top_lnk) { topic_id = top_lnk._to; @@ -1532,7 +1707,7 @@ module.exports = (function() { } } else { top_lnk = obj.db.top.firstExample({ - _from: topic_id + _from: topic_id, }); if (top_lnk) { @@ -1550,62 +1725,59 @@ module.exports = (function() { //obj.removeTags( tags ); }; - obj.getParents = function(item_id) { - var p, idx = 0, - parents, results = []; + obj.getParents = function (item_id) { + var p, + idx = 0, + parents, + results = []; parents = obj.db.item.byExample({ - _to: item_id + _to: item_id, }); - if (!parents.hasNext()) - return [ - [] - ]; + if (!parents.hasNext()) return [[]]; while (parents.hasNext()) { p = parents.next(); p = obj.db.c.document(p._from); - results.push([{ - id: p._id, - title: p.title, - alias: p.alias - }]); + results.push([ + { + id: p._id, + title: p.title, + alias: p.alias, + }, + ]); p = obj.db.item.firstExample({ - _to: p._id + _to: p._id, }); while (p) { p = obj.db.c.document(p._from); results[idx].push({ id: p._id, title: p.title, - alias: p.alias + alias: p.alias, }); p = obj.db.item.firstExample({ - _to: p._id + _to: p._id, }); } idx++; } // Sort paths alphabetically as in collection listings - results.sort(function(a, b) { + results.sort(function (a, b) { var i, j; if (a.length < b.length) { for (i = a.length - 1, j = b.length - 1; i >= 0; i--, j--) { - if (a[i].title < b[j].title) - return -1; - else if (a[i].title > b[j].title) - return 1; + if (a[i].title < b[j].title) return -1; + else if (a[i].title > b[j].title) return 1; } return 1; } else { for (i = a.length - 1, j = b.length - 1; j >= 0; i--, j--) { - if (a[i].title < b[j].title) - return -1; - else if (a[i].title > b[j].title) - return 1; + if (a[i].title < b[j].title) return -1; + else if (a[i].title > b[j].title) return 1; } return -1; } @@ -1614,60 +1786,59 @@ module.exports = (function() { return results; }; - - obj.makeTitleUnique = function(a_parent_id, a_doc) { - var conflicts = obj.db._query("for v in 1..1 outbound @coll item filter is_same_collection(@type,v) and v.title == @title return {id:v._id}", { - coll: a_parent_id, - title: a_doc.title, - type: a_doc._id.charAt(0) - }); + obj.makeTitleUnique = function (a_parent_id, a_doc) { + var conflicts = obj.db._query( + "for v in 1..1 outbound @coll item filter is_same_collection(@type,v) and v.title == @title return {id:v._id}", + { + coll: a_parent_id, + title: a_doc.title, + type: a_doc._id.charAt(0), + }, + ); if (conflicts.hasNext()) { obj.db._update(a_doc._id, { - title: a_doc.title + "_" + a_doc._key + title: a_doc.title + "_" + a_doc._key, }); } }; - - obj.hasAnyCommonAccessScope = function(src_item_id, dst_coll_id) { + obj.hasAnyCommonAccessScope = function (src_item_id, dst_coll_id) { //console.log("hasAnyCommonAccessScope",src_item_id, dst_coll_id); - if (src_item_id[0] == 'c') { + if (src_item_id[0] == "c") { // Collections can only be linked in one place, can use hasCommonAccessScope on parent var parent = obj.db.item.firstExample({ - _to: src_item_id + _to: src_item_id, }); - if (!parent) - return false; + if (!parent) return false; else { return obj.hasCommonAccessScope(parent._from, dst_coll_id); } } else { var parents = obj.db.item.byExample({ - _to: src_item_id + _to: src_item_id, }); while (parents.hasNext()) { - if (obj.hasCommonAccessScope(parents.next()._from, dst_coll_id)) - return true; + if (obj.hasCommonAccessScope(parents.next()._from, dst_coll_id)) return true; } } return false; }; - obj.hasCommonAccessScope = function(src_coll_id, dst_coll_id) { + obj.hasCommonAccessScope = function (src_coll_id, dst_coll_id) { //console.log("hasCommonAccessScope",src_coll_id, dst_coll_id); var p1 = [src_coll_id], p2 = [dst_coll_id]; - var parent, child = src_coll_id; + var parent, + child = src_coll_id; for (;;) { parent = obj.db.item.firstExample({ - _to: child + _to: child, }); - if (!parent) - break; + if (!parent) break; p1.unshift(parent._from); child = parent._from; } @@ -1676,19 +1847,18 @@ module.exports = (function() { for (;;) { parent = obj.db.item.firstExample({ - _to: child + _to: child, }); - if (!parent) - break; + if (!parent) break; p2.unshift(parent._from); child = parent._from; } - var i, len = Math.min(p1.length, p2.length); + var i, + len = Math.min(p1.length, p2.length); for (i = 0; i < len; i++) { - if (p1[i] != p2[i]) - break; + if (p1[i] != p2[i]) break; } //console.log("hasCommonAccessScope",p1, p2,i); @@ -1700,17 +1870,21 @@ module.exports = (function() { var j; for (j = i; j < p1.length; j++) { - if (obj.db.acl.firstExample({ - _from: p1[j] - })) { + if ( + obj.db.acl.firstExample({ + _from: p1[j], + }) + ) { return false; } } for (j = i; j < p2.length; j++) { - if (obj.db.acl.firstExample({ - _from: p2[j] - })) { + if ( + obj.db.acl.firstExample({ + _from: p2[j], + }) + ) { return false; } } @@ -1718,26 +1892,30 @@ module.exports = (function() { return true; }; - obj.hasPublicRead = function(a_id) { + obj.hasPublicRead = function (a_id) { console.log("Has public read a_id is ", a_id); // Check for local topic on collections if (a_id.startsWith("c/")) { var col = obj.db.c.document(a_id); - if (col.topic) - return true; + if (col.topic) return true; } - var i, children = [a_id], + var i, + children = [a_id], parents; for (;;) { // Find all parent collections owned by object owner - parents = obj.db._query("for i in @children for v in 1..1 inbound i item return {_id:v._id,topic:v.topic}", { - children: children - }).toArray(); + parents = obj.db + ._query( + "for i in @children for v in 1..1 inbound i item return {_id:v._id,topic:v.topic}", + { + children: children, + }, + ) + .toArray(); console.log("children are ", children, " parents are, ", parents); - if (parents.length === 0) - return false; + if (parents.length === 0) return false; for (i in parents) { if (parents[i].topic) { @@ -1754,12 +1932,21 @@ module.exports = (function() { * known not to be owned by the client (and that the client is not an admin). In this case, those checks * would add performance cost for no benefit. */ - obj.hasPermissions = function(a_client, a_object, a_req_perm, a_inherited = false, any = false) { + obj.hasPermissions = function ( + a_client, + a_object, + a_req_perm, + a_inherited = false, + any = false, + ) { //console.log("check perm:", a_req_perm, "client:", a_client._id, "object:", a_object._id, "any:", any ); //console.log("grant:", a_object.grant ); var perm_found = 0, - acl, acls, result, i; + acl, + acls, + result, + i; // If object is marked "public", everyone is granted VIEW, and READ permissions // The current implementation allows users to be denied access to public data (maybe wrong?) @@ -1768,50 +1955,52 @@ module.exports = (function() { perm_found = obj.PERM_PUBLIC; result = obj.evalPermissions(a_req_perm, perm_found, any); - if (result != null) - return result; + if (result != null) return result; } // Evaluate user permissions set directly on object if (a_object.acls & 1) { - acls = obj.db._query("for v, e in 1..1 outbound @object acl filter v._id == @client return e", { - object: a_object._id, - client: a_client._id - }).toArray(); + acls = obj.db + ._query("for v, e in 1..1 outbound @object acl filter v._id == @client return e", { + object: a_object._id, + client: a_client._id, + }) + .toArray(); if (acls.length) { for (i in acls) { acl = acls[i]; //console.log("user_perm:",acl); perm_found |= acl.grant; - if (a_inherited && acl.inhgrant) - perm_found |= acl.inhgrant; + if (a_inherited && acl.inhgrant) perm_found |= acl.inhgrant; } result = obj.evalPermissions(a_req_perm, perm_found, any); - if (result != null) - return result; + if (result != null) return result; } } // Evaluate group permissions on object if (a_object.acls & 2) { - acls = obj.db._query("for v, e, p in 2..2 outbound @object acl, outbound member filter p.vertices[2]._id == @client return p.edges[0]", { - object: a_object._id, - client: a_client._id - }).toArray(); + acls = obj.db + ._query( + "for v, e, p in 2..2 outbound @object acl, outbound member filter p.vertices[2]._id == @client return p.edges[0]", + { + object: a_object._id, + client: a_client._id, + }, + ) + .toArray(); if (acls.length) { for (i in acls) { acl = acls[i]; //console.log("group_perm:",acl); perm_found |= acl.grant; - if (a_inherited && acl.inhgrant) - perm_found |= acl.inhgrant; + if (a_inherited && acl.inhgrant) perm_found |= acl.inhgrant; } result = obj.evalPermissions(a_req_perm, perm_found, any); - if (result != null) - return result; + if (result != null) return result; } } @@ -1825,12 +2014,16 @@ module.exports = (function() { for (;;) { // Find all parent collections owned by object owner - parents = obj.db._query("for i in @children for v in 1..1 inbound i item return {_id:v._id,topic:v.topic,acls:v.acls}", { - children: children - }).toArray(); + parents = obj.db + ._query( + "for i in @children for v in 1..1 inbound i item return {_id:v._id,topic:v.topic,acls:v.acls}", + { + children: children, + }, + ) + .toArray(); - if (parents.length == 0) - break; + if (parents.length == 0) break; for (i in parents) { parent = parents[i]; @@ -1839,16 +2032,20 @@ module.exports = (function() { perm_found |= obj.PERM_PUBLIC; result = obj.evalPermissions(a_req_perm, perm_found, any); - if (result != null) - return result; + if (result != null) return result; } // User ACL first - if (parent.acls && ((parent.acls & 1) !== 0)) { - acls = obj.db._query("for v, e in 1..1 outbound @object acl filter v._id == @client return e", { - object: parent._id, - client: a_client._id - }).toArray(); + if (parent.acls && (parent.acls & 1) !== 0) { + acls = obj.db + ._query( + "for v, e in 1..1 outbound @object acl filter v._id == @client return e", + { + object: parent._id, + client: a_client._id, + }, + ) + .toArray(); if (acls.length) { for (i in acls) { acl = acls[i]; @@ -1856,17 +2053,21 @@ module.exports = (function() { } result = obj.evalPermissions(a_req_perm, perm_found, any); - if (result != null) - return result; + if (result != null) return result; } } // Group ACL next - if (parent.acls && ((parent.acls & 2) !== 0)) { - acls = obj.db._query("for v, e, p in 2..2 outbound @object acl, outbound member filter is_same_collection('g',p.vertices[1]) and p.vertices[2]._id == @client return p.edges[0]", { - object: parent._id, - client: a_client._id - }).toArray(); + if (parent.acls && (parent.acls & 2) !== 0) { + acls = obj.db + ._query( + "for v, e, p in 2..2 outbound @object acl, outbound member filter is_same_collection('g',p.vertices[1]) and p.vertices[2]._id == @client return p.edges[0]", + { + object: parent._id, + client: a_client._id, + }, + ) + .toArray(); if (acls.length) { for (i in acls) { acl = acls[i]; @@ -1874,8 +2075,7 @@ module.exports = (function() { } result = obj.evalPermissions(a_req_perm, perm_found, any); - if (result != null) - return result; + if (result != null) return result; } } } @@ -1889,28 +2089,26 @@ module.exports = (function() { return false; }; - obj.evalPermissions = function(a_req_perm, a_perm_found, any) { + obj.evalPermissions = function (a_req_perm, a_perm_found, any) { if (any) { // If any requested permission have been found, return true (granted) - if (a_perm_found & a_req_perm) - return true; - else - return null; // Else, keep looking + if (a_perm_found & a_req_perm) return true; + else return null; // Else, keep looking } else { // If not all requested permissions have been found return NULL (keep looking) - if ((a_perm_found & a_req_perm) != a_req_perm) - return null; - else - return true; // Else, permission granted + if ((a_perm_found & a_req_perm) != a_req_perm) return null; + else return true; // Else, permission granted } }; - obj.getPermissions = function(a_client, a_object, a_req_perm, a_inherited = false) { + obj.getPermissions = function (a_client, a_object, a_req_perm, a_inherited = false) { //console.log("get perm:", a_req_perm, "client:", a_client._id, "object:", a_object._id, "any:", any ); //console.log("grant:", a_object.grant ); var perm_found = 0, - acl, acls, i; + acl, + acls, + i; // If object has a topic (collections only), everyone is granted VIEW, and READ permissions // The current implementation allows users to be denied access to public data (maybe wrong?) @@ -1918,51 +2116,53 @@ module.exports = (function() { if (a_object.topic) { perm_found = obj.PERM_PUBLIC; - if ((a_req_perm & perm_found) == a_req_perm) - return a_req_perm; + if ((a_req_perm & perm_found) == a_req_perm) return a_req_perm; } // Evaluate permissions set directly on object - if (a_object.acls && ((a_object.acls & 1) !== 0)) { - acls = obj.db._query("for v, e in 1..1 outbound @object acl filter v._id == @client return e", { - object: a_object._id, - client: a_client._id - }).toArray(); + if (a_object.acls && (a_object.acls & 1) !== 0) { + acls = obj.db + ._query("for v, e in 1..1 outbound @object acl filter v._id == @client return e", { + object: a_object._id, + client: a_client._id, + }) + .toArray(); if (acls.length) { for (i in acls) { acl = acls[i]; //console.log("user_perm:",acl); perm_found |= acl.grant; - if (a_inherited && acl.inhgrant) - perm_found |= acl.inhgrant; + if (a_inherited && acl.inhgrant) perm_found |= acl.inhgrant; } - if ((a_req_perm & perm_found) == a_req_perm) - return a_req_perm; + if ((a_req_perm & perm_found) == a_req_perm) return a_req_perm; } } // Evaluate group permissions on object - if (a_object.acls && ((a_object.acls & 2) !== 0)) { - acls = obj.db._query("for v, e, p in 2..2 outbound @object acl, outbound member filter p.vertices[2]._id == @client return p.edges[0]", { - object: a_object._id, - client: a_client._id - }).toArray(); + if (a_object.acls && (a_object.acls & 2) !== 0) { + acls = obj.db + ._query( + "for v, e, p in 2..2 outbound @object acl, outbound member filter p.vertices[2]._id == @client return p.edges[0]", + { + object: a_object._id, + client: a_client._id, + }, + ) + .toArray(); if (acls.length) { for (i in acls) { acl = acls[i]; //console.log("group_perm:",acl); perm_found |= acl.grant; - if (a_inherited && acl.inhgrant) - perm_found |= acl.inhgrant; + if (a_inherited && acl.inhgrant) perm_found |= acl.inhgrant; } - if ((a_req_perm & perm_found) == a_req_perm) - return a_req_perm; + if ((a_req_perm & perm_found) == a_req_perm) return a_req_perm; } } @@ -1975,12 +2175,16 @@ module.exports = (function() { for (;;) { // Find all parent collections owned by object owner - parents = obj.db._query("for i in @children for v in 1..1 inbound i item return {_id:v._id,topic:v.topic,acls:v.acls}", { - children: children - }).toArray(); + parents = obj.db + ._query( + "for i in @children for v in 1..1 inbound i item return {_id:v._id,topic:v.topic,acls:v.acls}", + { + children: children, + }, + ) + .toArray(); - if (parents.length == 0) - break; + if (parents.length == 0) break; for (i in parents) { parent = parents[i]; @@ -1988,41 +2192,48 @@ module.exports = (function() { if (parent.topic) { perm_found |= obj.PERM_PUBLIC; - if ((a_req_perm & perm_found) == a_req_perm) - return a_req_perm; + if ((a_req_perm & perm_found) == a_req_perm) return a_req_perm; } // User ACL - if (parent.acls && ((parent.acls & 1) != 0)) { - acls = obj.db._query("for v, e in 1..1 outbound @object acl filter v._id == @client return e", { - object: parent._id, - client: a_client._id - }).toArray(); + if (parent.acls && (parent.acls & 1) != 0) { + acls = obj.db + ._query( + "for v, e in 1..1 outbound @object acl filter v._id == @client return e", + { + object: parent._id, + client: a_client._id, + }, + ) + .toArray(); if (acls.length) { for (i in acls) { acl = acls[i]; perm_found |= acl.inhgrant; } - if ((a_req_perm & perm_found) == a_req_perm) - return a_req_perm; + if ((a_req_perm & perm_found) == a_req_perm) return a_req_perm; } } // Group ACL - if (parent.acls && ((parent.acls & 2) != 0)) { - acls = obj.db._query("for v, e, p in 2..2 outbound @object acl, outbound member filter is_same_collection('g',p.vertices[1]) and p.vertices[2]._id == @client return p.edges[0]", { - object: parent._id, - client: a_client._id - }).toArray(); + if (parent.acls && (parent.acls & 2) != 0) { + acls = obj.db + ._query( + "for v, e, p in 2..2 outbound @object acl, outbound member filter is_same_collection('g',p.vertices[1]) and p.vertices[2]._id == @client return p.edges[0]", + { + object: parent._id, + client: a_client._id, + }, + ) + .toArray(); if (acls.length) { for (i in acls) { acl = acls[i]; perm_found |= acl.inhgrant; } - if ((a_req_perm & perm_found) == a_req_perm) - return a_req_perm; + if ((a_req_perm & perm_found) == a_req_perm) return a_req_perm; } } } @@ -2035,13 +2246,15 @@ module.exports = (function() { return perm_found & a_req_perm; }; - obj.getPermissionsLocal = function(a_client_id, a_object, a_get_inherited, a_req_perm) { + obj.getPermissionsLocal = function (a_client_id, a_object, a_get_inherited, a_req_perm) { var perm = { grant: 0, inhgrant: 0, - inherited: 0 + inherited: 0, }, - acl, acls, i; + acl, + acls, + i; //console.log("getPermissionsLocal",a_object._id); @@ -2054,10 +2267,12 @@ module.exports = (function() { if (a_object.acls & 1) { //console.log("chk local user acls"); - acls = obj.db._query("for v, e in 1..1 outbound @object acl filter v._id == @client return e", { - object: a_object._id, - client: a_client_id - }).toArray(); + acls = obj.db + ._query("for v, e in 1..1 outbound @object acl filter v._id == @client return e", { + object: a_object._id, + client: a_client_id, + }) + .toArray(); for (i in acls) { acl = acls[i]; @@ -2070,10 +2285,15 @@ module.exports = (function() { if (a_object.acls & 2) { //console.log("chk local group acls"); - acls = obj.db._query("for v, e, p in 2..2 outbound @object acl, outbound member filter p.vertices[2]._id == @client return p.edges[0]", { - object: a_object._id, - client: a_client_id - }).toArray(); + acls = obj.db + ._query( + "for v, e, p in 2..2 outbound @object acl, outbound member filter p.vertices[2]._id == @client return p.edges[0]", + { + object: a_object._id, + client: a_client_id, + }, + ) + .toArray(); for (i in acls) { acl = acls[i]; perm.grant |= acl.grant; @@ -2090,14 +2310,18 @@ module.exports = (function() { for (;;) { // Find all parent collections owned by object owner - parents = obj.db._query("for i in @children for v in 1..1 inbound i item return {_id:v._id,topic:v.topic,acls:v.acls}", { - children: children - }).toArray(); + parents = obj.db + ._query( + "for i in @children for v in 1..1 inbound i item return {_id:v._id,topic:v.topic,acls:v.acls}", + { + children: children, + }, + ) + .toArray(); //console.log("parents",parents); - if (parents.length == 0) - break; + if (parents.length == 0) break; for (i in parents) { parent = parents[i]; @@ -2107,45 +2331,52 @@ module.exports = (function() { perm.inherited |= obj.PERM_PUBLIC; - if ((a_req_perm & perm.inherited) == a_req_perm) - break; + if ((a_req_perm & perm.inherited) == a_req_perm) break; } // User ACL - if (parent.acls && ((parent.acls & 1) != 0)) { + if (parent.acls && (parent.acls & 1) != 0) { //console.log("chk par user acls"); - acls = obj.db._query("for v, e in 1..1 outbound @object acl filter v._id == @client return e", { - object: parent._id, - client: a_client_id - }).toArray(); + acls = obj.db + ._query( + "for v, e in 1..1 outbound @object acl filter v._id == @client return e", + { + object: parent._id, + client: a_client_id, + }, + ) + .toArray(); if (acls.length) { for (i in acls) { acl = acls[i]; perm.inherited |= acl.inhgrant; } - if ((a_req_perm & perm.inherited) == a_req_perm) - break; + if ((a_req_perm & perm.inherited) == a_req_perm) break; } } // Group ACL - if (parent.acls && ((parent.acls & 2) != 0)) { + if (parent.acls && (parent.acls & 2) != 0) { //console.log("chk par group acls"); - acls = obj.db._query("for v, e, p in 2..2 outbound @object acl, outbound member filter is_same_collection('g',p.vertices[1]) and p.vertices[2]._id == @client return p.edges[0]", { - object: parent._id, - client: a_client_id - }).toArray(); + acls = obj.db + ._query( + "for v, e, p in 2..2 outbound @object acl, outbound member filter is_same_collection('g',p.vertices[1]) and p.vertices[2]._id == @client return p.edges[0]", + { + object: parent._id, + client: a_client_id, + }, + ) + .toArray(); if (acls.length) { for (i in acls) { acl = acls[i]; perm.inherited |= acl.inhgrant; } - if ((a_req_perm & perm.inherited) == a_req_perm) - break; + if ((a_req_perm & perm.inherited) == a_req_perm) break; } } } @@ -2159,7 +2390,7 @@ module.exports = (function() { return perm; }; - obj.getACLOwnersBySubject = function(subject, inc_users, inc_projects) { + obj.getACLOwnersBySubject = function (subject, inc_users, inc_projects) { var results = []; /* Get users and projects that have shared data or collections with subject: @@ -2171,21 +2402,22 @@ module.exports = (function() { if (inc_users || inc_projects) { var ids = new Set(), ignore = new Set(), - owner_id, acl, acls = obj.db.acl.byExample({ - _to: subject + owner_id, + acl, + acls = obj.db.acl.byExample({ + _to: subject, }); // Find direct ACLs (not through a group) while (acls.hasNext()) { acl = acls.next(); owner_id = obj.db.owner.firstExample({ - _from: acl._from + _from: acl._from, })._to; - if (owner_id.charAt(0) == 'p') { + if (owner_id.charAt(0) == "p") { if (inc_projects) { - if (ids.has(owner_id) || ignore.has(owner_id)) - continue; + if (ids.has(owner_id) || ignore.has(owner_id)) continue; if (obj.getProjectRole(subject, owner_id) == obj.PROJ_NO_ROLE) { ids.add(owner_id); @@ -2199,23 +2431,25 @@ module.exports = (function() { } // Find indirect ACLs (through a group) - var mem, members = obj.db.member.byExample({ - _to: subject - }); + var mem, + members = obj.db.member.byExample({ + _to: subject, + }); while (members.hasNext()) { mem = members.next(); // Group must have at least one ACL set; otherwise ignore it - if (obj.db.acl.firstExample({ - _to: mem._from - })) { + if ( + obj.db.acl.firstExample({ + _to: mem._from, + }) + ) { owner_id = obj.db.owner.firstExample({ - _from: mem._from + _from: mem._from, })._to; - if (owner_id.charAt(0) == 'p') { + if (owner_id.charAt(0) == "p") { if (inc_projects) { - if (ids.has(owner_id) || ignore.has(owner_id)) - continue; + if (ids.has(owner_id) || ignore.has(owner_id)) continue; if (obj.getProjectRole(subject, owner_id) == obj.PROJ_NO_ROLE) { ids.add(owner_id); @@ -2231,76 +2465,91 @@ module.exports = (function() { var doc, title; - ids.forEach(function(id) { + ids.forEach(function (id) { doc = obj.db._document(id); - if (doc.title) - title = doc.title; - else - title = doc.name_last + ", " + doc.name_first; + if (doc.title) title = doc.title; + else title = doc.name_last + ", " + doc.name_first; results.push({ id: doc._id, title: title, - owner: doc.owner + owner: doc.owner, }); }); - results.sort(function(a, b) { - if (a.id < b.id) - return -1; - else if (a.id > b.id) - return 1; - else - return 0; + results.sort(function (a, b) { + if (a.id < b.id) return -1; + else if (a.id > b.id) return 1; + else return 0; }); } return results; }; - obj.usersWithClientACLs = function(client_id, id_only) { + obj.usersWithClientACLs = function (client_id, id_only) { var result; if (id_only) { - result = obj.db._query("for x in union_distinct((for v in 2..2 inbound @user acl, outbound owner filter is_same_collection('u',v) return v._id),(for v,e,p in 3..3 inbound @user member, acl, outbound owner filter is_same_collection('g',p.vertices[1]) and is_same_collection('acl',p.edges[1]) and is_same_collection('u',v) return v._id)) return x", { - user: client_id - }).toArray(); + result = obj.db + ._query( + "for x in union_distinct((for v in 2..2 inbound @user acl, outbound owner filter is_same_collection('u',v) return v._id),(for v,e,p in 3..3 inbound @user member, acl, outbound owner filter is_same_collection('g',p.vertices[1]) and is_same_collection('acl',p.edges[1]) and is_same_collection('u',v) return v._id)) return x", + { + user: client_id, + }, + ) + .toArray(); } else { - result = obj.db._query("for x in union_distinct((for v in 2..2 inbound @user acl, outbound owner filter is_same_collection('u',v) return {uid:v._id,name:v.name}),(for v,e,p in 3..3 inbound @user member, acl, outbound owner filter is_same_collection('g',p.vertices[1]) and is_same_collection('acl',p.edges[1]) and is_same_collection('u',v) return {uid:v._id,name:v.name})) sort x.name return x", { - user: client_id - }).toArray(); + result = obj.db + ._query( + "for x in union_distinct((for v in 2..2 inbound @user acl, outbound owner filter is_same_collection('u',v) return {uid:v._id,name:v.name}),(for v,e,p in 3..3 inbound @user member, acl, outbound owner filter is_same_collection('g',p.vertices[1]) and is_same_collection('acl',p.edges[1]) and is_same_collection('u',v) return {uid:v._id,name:v.name})) sort x.name return x", + { + user: client_id, + }, + ) + .toArray(); } //console.log("usersWithACLs:",result); return result; }; - obj.projectsWithClientACLs = function(client_id, id_only) { + obj.projectsWithClientACLs = function (client_id, id_only) { // Get projects that have ACLs set for client AND where client is not owner, admin, or member of project var result; if (id_only) { - result = obj.db._query("for i in minus((for v in 2..2 inbound @user member, acl, outbound owner filter is_same_collection('p',v) return v._id),(for v,e,p in 2..2 inbound @user member, outbound owner filter p.vertices[1].gid == 'members' and is_same_collection('p',v) return v._id)) return i", { - user: client_id - }); + result = obj.db._query( + "for i in minus((for v in 2..2 inbound @user member, acl, outbound owner filter is_same_collection('p',v) return v._id),(for v,e,p in 2..2 inbound @user member, outbound owner filter p.vertices[1].gid == 'members' and is_same_collection('p',v) return v._id)) return i", + { + user: client_id, + }, + ); } else { - result = obj.db._query("for i in minus((for v in 2..2 inbound @user member, acl, outbound owner filter is_same_collection('p',v) return {id:v._id,title:v.title}),(for v,e,p in 2..2 inbound @user member, outbound owner filter p.vertices[1].gid == 'members' and is_same_collection('p',v) return {id:v._id,title:v.title})) return i", { - user: client_id - }); + result = obj.db._query( + "for i in minus((for v in 2..2 inbound @user member, acl, outbound owner filter is_same_collection('p',v) return {id:v._id,title:v.title}),(for v,e,p in 2..2 inbound @user member, outbound owner filter p.vertices[1].gid == 'members' and is_same_collection('p',v) return {id:v._id,title:v.title})) return i", + { + user: client_id, + }, + ); } //console.log("projectsWithACLs:",result); return result.toArray(); }; - obj.checkDependencies = function(id, src, depth) { + obj.checkDependencies = function (id, src, depth) { //console.log("checkdep ",id,src,depth); - var dep, deps = obj.db._query("for v in 1..1 outbound @id dep return v._id", { - id: id - }); + var dep, + deps = obj.db._query("for v in 1..1 outbound @id dep return v._id", { + id: id, + }); if (!depth || depth < 50) { //console.log("checkdep depth ok"); while (deps.hasNext()) { //console.log("has next"); dep = deps.next(); if (dep == src) - throw [obj.ERR_INVALID_PARAM, "Circular dependency detected in references, from " + id]; + throw [ + obj.ERR_INVALID_PARAM, + "Circular dependency detected in references, from " + id, + ]; obj.checkDependencies(dep, src ? src : id, depth + 1); } } @@ -2308,31 +2557,42 @@ module.exports = (function() { // Returns bitmask: CLOSED_BIT (1) | OPEN_TYPE_INH (4) | OPEN_TYPE (4) | ACTIVE_TYPE (4) - //obj.annotationGetMask = function( a_client, a_subj_id, a_admin ){ - obj.getNoteMask = function(a_client, a_subj, a_admin) { + obj.getNoteMask = function (a_client, a_subj, a_admin) { var mask = 0, - res, n, b, id = a_subj.id || a_subj._id; + res, + n, + b, + id = a_subj.id || a_subj._id; if (a_client) { if (a_admin || (a_admin === undefined && obj.hasAdminPermObject(a_client, id))) { // Owner/admin - return notes that are open or active - res = obj.db._query("for n in 1..1 outbound @id note return {type:n.type,state:n.state,parent_id:n.parent_id}", { - id: id - }); + res = obj.db._query( + "for n in 1..1 outbound @id note return {type:n.type,state:n.state,parent_id:n.parent_id}", + { + id: id, + }, + ); } else { // Non-owner - return notes that are active // Creator - return notes that are open or active - res = obj.db._query("for n in 1..1 outbound @id note filter n.state == 2 || n.creator == @client return {type:n.type,state:n.state,parent_id:n.parent_id}", { - id: id, - client: a_client._id - }); + res = obj.db._query( + "for n in 1..1 outbound @id note filter n.state == 2 || n.creator == @client return {type:n.type,state:n.state,parent_id:n.parent_id}", + { + id: id, + client: a_client._id, + }, + ); } } else { // Annonymous - return notes that are active - res = obj.db._query("for n in 1..1 outbound @id note filter n.state == 2 return {type:n.type,state:n.state,parent_id:n.parent_id}", { - id: id - }); + res = obj.db._query( + "for n in 1..1 outbound @id note filter n.state == 2 return {type:n.type,state:n.state,parent_id:n.parent_id}", + { + id: id, + }, + ); } // Shift note type bits based on inherited, open, active state @@ -2343,10 +2603,8 @@ module.exports = (function() { mask |= obj.NOTE_MASK_CLS_ANY; } else { b = 1 << n.type; - if (n.parent_id && n.state == obj.NOTE_OPEN) - b <<= 8; - else if (n.state == obj.NOTE_OPEN) - b <<= 4; + if (n.parent_id && n.state == obj.NOTE_OPEN) b <<= 8; + else if (n.state == obj.NOTE_OPEN) b <<= 4; mask |= b; } @@ -2359,12 +2617,14 @@ module.exports = (function() { return mask; }; - obj.annotationInitDependents = function(a_client, a_parent_note, a_updates) { + obj.annotationInitDependents = function (a_client, a_parent_note, a_updates) { //console.log("annotationInitDependents",a_parent_note._id); var subj = obj.db._document(a_parent_note.subject_id), - note, dep, deps = obj.db._query("for v,e in 1..1 inbound @id dep filter e.type < 2 return v", { - id: subj._id + note, + dep, + deps = obj.db._query("for v,e in 1..1 inbound @id dep filter e.type < 2 return v", { + id: subj._id, }), time = Math.floor(Date.now() / 1000), new_note = { @@ -2375,14 +2635,20 @@ module.exports = (function() { ct: time, ut: time, title: a_parent_note.title, - comments: [{ - user: a_parent_note.creator, - new_type: a_parent_note.type, - new_state: obj.NOTE_OPEN, - time: time, - comment: "Impact assessment needed due to issue on direct ancestor '" + a_parent_note.subject_id + - "'. Original issue description: \"" + a_parent_note.comments[0].comment + "\"" - }] + comments: [ + { + user: a_parent_note.creator, + new_type: a_parent_note.type, + new_state: obj.NOTE_OPEN, + time: time, + comment: + "Impact assessment needed due to issue on direct ancestor '" + + a_parent_note.subject_id + + "'. Original issue description: \"" + + a_parent_note.comments[0].comment + + '"', + }, + ], }; // Create new linked annotation for each dependent @@ -2391,15 +2657,15 @@ module.exports = (function() { //console.log("dep:",dep._id); new_note.subject_id = dep._id; note = obj.db.n.save(new_note, { - returnNew: true + returnNew: true, }); obj.db.note.save({ _from: dep._id, - _to: note.new._id + _to: note.new._id, }); obj.db.note.save({ _from: note.new._id, - _to: a_parent_note._id + _to: a_parent_note._id, }); // Add update listing data if not present @@ -2417,25 +2683,33 @@ module.exports = (function() { children to match. For other types, close all children. For errors and warnings, if state is changed to active, reopen any closed children; otherwise, if open or closed, close all children. For child notes that have already been activated, must recurse to all children as needed. */ - obj.annotationUpdateDependents = function(a_client, a_parent_note, a_prev_type, a_prev_state, a_updates) { - if (a_parent_note.type == a_prev_type && (a_parent_note.state == a_prev_state || (a_parent_note.state != obj.NOTE_ACTIVE && a_prev_state != obj.NOTE_ACTIVE))) + obj.annotationUpdateDependents = function ( + a_client, + a_parent_note, + a_prev_type, + a_prev_state, + a_updates, + ) { + if ( + a_parent_note.type == a_prev_type && + (a_parent_note.state == a_prev_state || + (a_parent_note.state != obj.NOTE_ACTIVE && a_prev_state != obj.NOTE_ACTIVE)) + ) return; var time = Math.floor(Date.now() / 1000), upd = { type: a_parent_note.type, - ut: time + ut: time, }, comment = { user: a_client._id, - time: time + time: time, }; - if (a_parent_note.type != a_prev_type) - comment.new_type = a_parent_note.type; + if (a_parent_note.type != a_prev_type) comment.new_type = a_parent_note.type; - if (a_parent_note.state != a_prev_state) - comment.new_state = a_parent_note.state; + if (a_parent_note.state != a_prev_state) comment.new_state = a_parent_note.state; if (a_parent_note.type >= obj.NOTE_WARN && a_parent_note.state == obj.NOTE_ACTIVE) { upd.state = obj.NOTE_OPEN; @@ -2443,11 +2717,8 @@ module.exports = (function() { if (a_parent_note.type != a_prev_type && a_parent_note.state != a_prev_state) comment.comment += "type and state"; - else if (a_parent_note.state != a_prev_state) - comment.comment += "type"; - else - comment.comment += "state"; - + else if (a_parent_note.state != a_prev_state) comment.comment += "type"; + else comment.comment += "state"; } else { upd.state = obj.NOTE_CLOSED; comment.comment = "Impact assessment invalidated due to change of state"; @@ -2459,20 +2730,29 @@ module.exports = (function() { client: a_client, note_upd: upd, comment: comment, - updates: a_updates + updates: a_updates, }; // Recurse full tree only if type is changing or state is changed from active to open or closed - if (comment.new_type != undefined || (a_parent_note.state != obj.NOTE_ACTIVE && a_prev_state == obj.NOTE_ACTIVE)) + if ( + comment.new_type != undefined || + (a_parent_note.state != obj.NOTE_ACTIVE && a_prev_state == obj.NOTE_ACTIVE) + ) context.recurse = true; obj.annotationUpdateDependents_Recurse(a_parent_note._id, context); }; - obj.annotationUpdateDependents_Recurse = function(a_note_id, a_context, a_close) { - var old_state, note, subj, deps = obj.db._query("for v in 1..1 inbound @id note filter is_same_collection('n',v) return v", { - id: a_note_id - }); + obj.annotationUpdateDependents_Recurse = function (a_note_id, a_context, a_close) { + var old_state, + note, + subj, + deps = obj.db._query( + "for v in 1..1 inbound @id note filter is_same_collection('n',v) return v", + { + id: a_note_id, + }, + ); if (a_close) { old_state = a_context.note_upd.state; @@ -2489,7 +2769,10 @@ module.exports = (function() { // Add/refresh update listing data if (note.subject_id in a_context.updates) { - a_context.updates[note.subject_id].notes = obj.getNoteMask(a_context.client, a_context.updates[note.subject_id]); + a_context.updates[note.subject_id].notes = obj.getNoteMask( + a_context.client, + a_context.updates[note.subject_id], + ); } else { subj = obj.db._document(note.subject_id); subj.notes = obj.getNoteMask(a_context.client, subj); @@ -2508,11 +2791,12 @@ module.exports = (function() { } }; - obj.annotationDelete = function(a_id, a_update_ids) { + obj.annotationDelete = function (a_id, a_update_ids) { //console.log("delete note:",a_id); - var n, notes = obj.db.note.byExample({ - _to: a_id - }); + var n, + notes = obj.db.note.byExample({ + _to: a_id, + }); while (notes.hasNext()) { n = notes.next(); @@ -2522,12 +2806,16 @@ module.exports = (function() { } n = obj.db.n.document(a_id); - if (a_update_ids) - a_update_ids.add(n.subject_id); + if (a_update_ids) a_update_ids.add(n.subject_id); obj.graph.n.remove(a_id); }; - obj.annotationDependenciesUpdated = function(a_data, a_dep_ids_added, a_dep_ids_removed, a_update_ids) { + obj.annotationDependenciesUpdated = function ( + a_data, + a_dep_ids_added, + a_dep_ids_removed, + a_update_ids, + ) { //console.log("annotationDependenciesUpdated",a_data._id); // Called when dependencies are added/removed to/from existing/new data record var res, qry_res; @@ -2538,9 +2826,12 @@ module.exports = (function() { //console.log("deletings notes from:",a_data._id); // Find local annotations linked to upstream dependencies - qry_res = obj.db._query("for v,e,p in 3..3 any @src note filter is_same_collection('d',v) && p.edges[1]._from == p.vertices[1]._id return {src: p.vertices[1], dst: p.vertices[3]}", { - src: a_data._id - }); + qry_res = obj.db._query( + "for v,e,p in 3..3 any @src note filter is_same_collection('d',v) && p.edges[1]._from == p.vertices[1]._id return {src: p.vertices[1], dst: p.vertices[3]}", + { + src: a_data._id, + }, + ); while (qry_res.hasNext()) { res = qry_res.next(); @@ -2558,9 +2849,12 @@ module.exports = (function() { if (a_dep_ids_added) { //console.log("deps added:",Array.from( a_dep_ids_added )); // Get all annotations from new dependencies that may need to be propagated - qry_res = obj.db._query("for i in @src for v in 1..1 outbound i note filter v.type > 1 return v", { - src: Array.from(a_dep_ids_added) - }); + qry_res = obj.db._query( + "for i in @src for v in 1..1 outbound i note filter v.type > 1 return v", + { + src: Array.from(a_dep_ids_added), + }, + ); if (qry_res.hasNext()) { var time = Math.floor(Date.now() / 1000), @@ -2571,9 +2865,14 @@ module.exports = (function() { //console.log("dep:",res); // Only need to propagate if dependents are already present or state is active - if (res.state == obj.NOTE_ACTIVE || obj.db.note.byExample({ - _to: res._id - }).count() > 1) { + if ( + res.state == obj.NOTE_ACTIVE || + obj.db.note + .byExample({ + _to: res._id, + }) + .count() > 1 + ) { //console.log("propagate"); new_note = { state: obj.NOTE_OPEN, @@ -2584,26 +2883,32 @@ module.exports = (function() { ct: time, ut: time, title: res.title, - comments: [{ - user: res.creator, - new_type: res.type, - new_state: obj.NOTE_OPEN, - time: time, - comment: "Impact assessment needed due to issue on direct ancestor '" + res.subject_id + - "'. Original issue description: \"" + res.comments[0].comment + "\"" - }] + comments: [ + { + user: res.creator, + new_type: res.type, + new_state: obj.NOTE_OPEN, + time: time, + comment: + "Impact assessment needed due to issue on direct ancestor '" + + res.subject_id + + "'. Original issue description: \"" + + res.comments[0].comment + + '"', + }, + ], }; new_note = obj.db.n.save(new_note, { - returnNew: true + returnNew: true, }).new; obj.db.note.save({ _from: a_data._id, - _to: new_note._id + _to: new_note._id, }); obj.db.note.save({ _from: new_note._id, - _to: res._id + _to: res._id, }); } } @@ -2611,7 +2916,7 @@ module.exports = (function() { } }; - obj.addTags = function(a_tags) { + obj.addTags = function (a_tags) { //console.log("addTags",a_tags); var id, tag, j, code; @@ -2623,7 +2928,7 @@ module.exports = (function() { //console.log( "update", id ); tag = obj.db.tag.document(id); obj.db._update(id, { - count: tag.count + 1 + count: tag.count + 1, }); } else { //console.log( "save", id ); @@ -2632,21 +2937,24 @@ module.exports = (function() { for (j = 0; j < tag.length; j++) { code = tag.charCodeAt(j); - if (!(code > 47 && code < 58) && // numeric (0-9) + if ( + !(code > 47 && code < 58) && // numeric (0-9) !(code > 96 && code < 123) && // lower alpha (a-z) - code !== 45) // "-" + code !== 45 + ) + // "-" throw [obj.ERR_INVALID_CHAR, "Invalid character(s) in tag."]; } obj.db.tag.save({ _key: tag, - count: 1 + count: 1, }); } } }; - obj.removeTags = function(a_tags) { + obj.removeTags = function (a_tags) { //console.log("removeTags",a_tags); var id, tag; @@ -2657,7 +2965,7 @@ module.exports = (function() { if (tag.count > 1) { //console.log("update",id); obj.db._update(id, { - count: tag.count - 1 + count: tag.count - 1, }); } else { //console.log("remove",id); @@ -2667,18 +2975,16 @@ module.exports = (function() { } }; - obj.saveRecentGlobusPath = function(a_client, a_path, a_mode) { + obj.saveRecentGlobusPath = function (a_client, a_path, a_mode) { var path = a_path, idx = a_path.lastIndexOf("/"); if (a_mode == obj.TT_DATA_PUT) { // For PUT, strip off filename but keep last slash - if (idx > 0) - path = a_path.substr(0, idx + 1); + if (idx > 0) path = a_path.substr(0, idx + 1); } else { // For GET, make sure path ends in a slash - if (idx != a_path.length - 1) - path += "/"; + if (idx != a_path.length - 1) path += "/"; } if (a_client.eps && a_client.eps.length) { @@ -2696,17 +3002,21 @@ module.exports = (function() { } obj.db._update(a_client._id, { - eps: a_client.eps + eps: a_client.eps, }); }; // All col IDs are from same scope (owner), exapnd to include all readable sub-collections // Collections must exist // TODO This would be more efficient as a recursive function - obj.expandSearchCollections2 = function(a_client, a_col_ids) { + obj.expandSearchCollections2 = function (a_client, a_col_ids) { var cols = new Set(a_col_ids), - c, col, cur, next = a_col_ids, - perm, child; + c, + col, + cur, + next = a_col_ids, + perm, + child; while (next) { cur = next; @@ -2716,9 +3026,12 @@ module.exports = (function() { col = obj.db.c.document(cur[c]); if (obj.hasAdminPermObject(a_client, col._id)) { - child = obj.db._query("for i in 1..10 outbound @col item filter is_same_collection('c',i) return i._id", { - col: col._id - }); + child = obj.db._query( + "for i in 1..10 outbound @col item filter is_same_collection('c',i) return i._id", + { + col: col._id, + }, + ); if (!cols.has(col._id)) { cols.add(col._id); @@ -2731,20 +3044,37 @@ module.exports = (function() { } } } else { - perm = obj.getPermissionsLocal(a_client._id, col, true, obj.PERM_RD_REC | obj.PERM_LIST); - - if (perm.grant & (obj.PERM_RD_REC | obj.PERM_LIST) != (obj.PERM_RD_REC | obj.PERM_LIST)) { - throw [obj.ERR_PERM_DENIED, "Permission denied for collection '" + col._id + "'"]; + perm = obj.getPermissionsLocal( + a_client._id, + col, + true, + obj.PERM_RD_REC | obj.PERM_LIST, + ); + + if ( + perm.grant & + ((obj.PERM_RD_REC | obj.PERM_LIST) != (obj.PERM_RD_REC | obj.PERM_LIST)) + ) { + throw [ + obj.ERR_PERM_DENIED, + "Permission denied for collection '" + col._id + "'", + ]; } if (!cols.has(col._id)) { cols.add(col._id); } - if (perm.inhgrant & (obj.PERM_RD_REC | obj.PERM_LIST) == (obj.PERM_RD_REC | obj.PERM_LIST)) { - child = obj.db._query("for i in 1..10 outbound @col item filter is_same_collection('c',i) return i._id", { - col: col._id - }); + if ( + perm.inhgrant & + ((obj.PERM_RD_REC | obj.PERM_LIST) == (obj.PERM_RD_REC | obj.PERM_LIST)) + ) { + child = obj.db._query( + "for i in 1..10 outbound @col item filter is_same_collection('c',i) return i._id", + { + col: col._id, + }, + ); while (child.hasNext()) { col = child.next(); if (!cols.has(col)) { @@ -2752,9 +3082,12 @@ module.exports = (function() { } } } else { - child = obj.db._query("for i in 1..1 outbound @col item filter is_same_collection('c',i) return i._id", { - col: col._id - }); + child = obj.db._query( + "for i in 1..1 outbound @col item filter is_same_collection('c',i) return i._id", + { + col: col._id, + }, + ); while (child.hasNext()) { next.push(child.next()); } @@ -2766,7 +3099,7 @@ module.exports = (function() { return Array.from(cols); }; - obj.expandSearchCollections = function(a_client, a_col_ids) { + obj.expandSearchCollections = function (a_client, a_col_ids) { var cols = new Set(); for (var c in a_col_ids) { obj.expandSearchCollections_recurse(a_client, cols, a_col_ids[c]); @@ -2774,16 +3107,19 @@ module.exports = (function() { return Array.from(cols); }; - obj.expandSearchCollections_recurse = function(a_client, a_cols, a_col_id, a_inh_perm) { + obj.expandSearchCollections_recurse = function (a_client, a_cols, a_col_id, a_inh_perm) { if (!a_cols.has(a_col_id)) { //console.log("expColl",a_col_id,"inh:",a_inh_perm); var col, res; if (obj.hasAdminPermObject(a_client, a_col_id)) { a_cols.add(a_col_id); //console.log("has admin"); - res = obj.db._query("for i in 1..10 outbound @col item filter is_same_collection('c',i) return i._id", { - col: a_col_id - }); + res = obj.db._query( + "for i in 1..10 outbound @col item filter is_same_collection('c',i) return i._id", + { + col: a_col_id, + }, + ); while (res.hasNext()) { col = res.next(); if (!a_cols.has(col)) { @@ -2793,13 +3129,25 @@ module.exports = (function() { } else { col = obj.db.c.document(a_col_id); - var perm = obj.getPermissionsLocal(a_client._id, col, a_inh_perm == undefined ? true : false, obj.PERM_RD_REC | obj.PERM_LIST); + var perm = obj.getPermissionsLocal( + a_client._id, + col, + a_inh_perm == undefined ? true : false, + obj.PERM_RD_REC | obj.PERM_LIST, + ); //console.log("perm",perm); - if (((perm.grant | perm.inherited | a_inh_perm) & (obj.PERM_RD_REC | obj.PERM_LIST)) != (obj.PERM_RD_REC | obj.PERM_LIST)) { + if ( + ((perm.grant | perm.inherited | a_inh_perm) & + (obj.PERM_RD_REC | obj.PERM_LIST)) != + (obj.PERM_RD_REC | obj.PERM_LIST) + ) { if (a_inh_perm == undefined) { // Only throw a PERM_DENIED error if this is one of the user-specified collections (not a child) - throw [obj.ERR_PERM_DENIED, "Permission denied for collection '" + col._id + "'"]; + throw [ + obj.ERR_PERM_DENIED, + "Permission denied for collection '" + col._id + "'", + ]; } else { // Don't have access - skip return; @@ -2810,12 +3158,19 @@ module.exports = (function() { a_cols.add(a_col_id); - if (((perm.inhgrant | perm.inherited | a_inh_perm) & (obj.PERM_RD_REC | obj.PERM_LIST)) == (obj.PERM_RD_REC | obj.PERM_LIST)) { + if ( + ((perm.inhgrant | perm.inherited | a_inh_perm) & + (obj.PERM_RD_REC | obj.PERM_LIST)) == + (obj.PERM_RD_REC | obj.PERM_LIST) + ) { //console.log("have all inh perms"); - res = obj.db._query("for i in 1..10 outbound @col item filter is_same_collection('c',i) return i._id", { - col: a_col_id - }); + res = obj.db._query( + "for i in 1..10 outbound @col item filter is_same_collection('c',i) return i._id", + { + col: a_col_id, + }, + ); while (res.hasNext()) { col = res.next(); if (!a_cols.has(col)) { @@ -2823,10 +3178,13 @@ module.exports = (function() { } } } else { - res = obj.db._query("for i in 1..1 outbound @col item filter is_same_collection('c',i) return i._id", { - col: col._id - }); - perm = (perm.inhgrant | perm.inherited | a_inh_perm); + res = obj.db._query( + "for i in 1..1 outbound @col item filter is_same_collection('c',i) return i._id", + { + col: col._id, + }, + ); + perm = perm.inhgrant | perm.inherited | a_inh_perm; //console.log("not all inh perms", perm); while (res.hasNext()) { @@ -2837,5 +3195,60 @@ module.exports = (function() { } }; + /** + * Parses other_token_data string field and breaks it into pieces + * + * @param {integer} token_type - Type to determine parse logic. + * + * @param {string} other_token_data + * + * String of additional token data, delimited by the '|' character. + * The format is determined by the token type. + * Currently expecting the following formats: + * + * GLOBUS_TRANSFER: "|" + * @returns {{}} Object containing the parsed key/values of the input other_token_data string. + * @throws obj.ERR_INVALAD_PARAM + * + * @example + * // returns { uuid: "1cbaaee5-b938-4a4e-87a8-f1ec4d5d92f9", scopes: "urn:globus:auth:scope:transfer.api.globus.org:all+email" } + * parseOtherTokenData(AccessTokenType.GLOBUS_TRANSFER, "1cbaaee5-b938-4a4e-87a8-f1ec4d5d92f9|urn:globus:auth:scope:transfer.api.globus.org:all+email"); + */ + obj.parseOtherTokenData = (token_type, other_token_data) => { + let return_data = {}; + // TODO: other token types + if (token_type === obj.AccessTokenType.GLOBUS_TRANSFER) { + // TODO: add support for additional type of collection and HA fields + // TODO: callers and jsdocs will need to be updated if changes are made to assumed data + // GLOBUS_TRANSFER parse currently assumes uuid and scopes exist, but this may change + const parsed_data = other_token_data.split("|"); + if (parsed_data.length !== 2) { + throw [obj.ERR_INVALID_PARAM, "Unexpected count of additional token data provided"]; + } + + const parsed_uuid = parsed_data[0]; + if (!obj.isUUID(parsed_uuid)) { + throw [ + obj.ERR_INVALID_PARAM, + "Provided other_token_data does not follow format of '|'", + ]; + } + const parsed_scopes = parsed_data[1]; + if (!parsed_scopes.includes("transfer.api.globus.org")) { + // TODO: does this need validation, and is this validation sufficient? + throw [ + obj.ERR_INVALID_PARAM, + "Scopes included in other_token_data do not refer to transfer resource, but transfer resource was specified", + ]; + } + return_data = { + ...return_data, + uuid: parsed_uuid, + scopes: parsed_scopes, + }; + } + return return_data; + }; + return obj; -}()); +})(); diff --git a/core/database/foxx/api/tag_router.js b/core/database/foxx/api/tag_router.js index c03181321..3dfb28d41 100644 --- a/core/database/foxx/api/tag_router.js +++ b/core/database/foxx/api/tag_router.js @@ -1,18 +1,18 @@ -'use strict'; +"use strict"; -const createRouter = require('@arangodb/foxx/router'); +const createRouter = require("@arangodb/foxx/router"); const router = createRouter(); -const joi = require('joi'); +const joi = require("joi"); -const g_db = require('@arangodb').db; -const g_lib = require('./support'); +const g_db = require("@arangodb").db; +const g_lib = require("./support"); module.exports = router; - //==================== TAG API FUNCTIONS -router.post('/search', function(req, res) { +router + .post("/search", function (req, res) { try { var name = req.queryParams.name.trim(); if (name.length < 3) @@ -20,13 +20,17 @@ router.post('/search', function(req, res) { var off = req.queryParams.offset ? req.queryParams.offset : 0, cnt = req.queryParams.count ? req.queryParams.count : 50, - result = g_db._query("for t in tagview search analyzer(t._key in tokens(@name,'tag_name'), 'tag_name') let s = BM25(t) sort s desc limit @off,@cnt return {name: t._key, count: t.count}", { - name: name, - off: off, - cnt: cnt - }, { - fullCount: true - }), + result = g_db._query( + "for t in tagview search analyzer(t._key in tokens(@name,'tag_name'), 'tag_name') let s = BM25(t) sort s desc limit @off,@cnt return {name: t._key, count: t.count}", + { + name: name, + off: off, + cnt: cnt, + }, + { + fullCount: true, + }, + ), tot = result.getExtra().stats.fullCount; result = result.toArray(); @@ -34,8 +38,8 @@ router.post('/search', function(req, res) { paging: { off: off, cnt: cnt, - tot: tot - } + tot: tot, + }, }); res.send(result); @@ -43,30 +47,33 @@ router.post('/search', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('name', joi.string().required(), "Tag name or part of name to search for") - .queryParam('offset', joi.number().optional(), "Offset") - .queryParam('count', joi.number().optional(), "Count") - .summary('Search for tags') - .description('Search for tags by name'); - - + .queryParam("name", joi.string().required(), "Tag name or part of name to search for") + .queryParam("offset", joi.number().optional(), "Offset") + .queryParam("count", joi.number().optional(), "Count") + .summary("Search for tags") + .description("Search for tags by name"); -router.post('/list/by_count', function(req, res) { +router + .post("/list/by_count", function (req, res) { try { g_db._executeTransaction({ collections: { - read: ["tag"] + read: ["tag"], }, - action: function() { + action: function () { var off = req.queryParams.offset ? req.queryParams.offset : 0, cnt = req.queryParams.count ? req.queryParams.count : 50; - var result = g_db._query("for t in tag sort t.count desc limit @off,@cnt return {name: t._key, count: t.count}", { - off: off, - cnt: cnt - }, { - fullCount: true - }); + var result = g_db._query( + "for t in tag sort t.count desc limit @off,@cnt return {name: t._key, count: t.count}", + { + off: off, + cnt: cnt, + }, + { + fullCount: true, + }, + ); var tot = result.getExtra().stats.fullCount; result = result.toArray(); @@ -74,18 +81,18 @@ router.post('/list/by_count', function(req, res) { paging: { off: off, cnt: cnt, - tot: tot - } + tot: tot, + }, }); res.send(result); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('offset', joi.number().optional(), "Offset") - .queryParam('count', joi.number().optional(), "Count") - .summary('List tags by count') - .description('List tags by count'); \ No newline at end of file + .queryParam("offset", joi.number().optional(), "Offset") + .queryParam("count", joi.number().optional(), "Count") + .summary("List tags by count") + .description("List tags by count"); diff --git a/core/database/foxx/api/task_router.js b/core/database/foxx/api/task_router.js index 872eef6af..e4f96922b 100644 --- a/core/database/foxx/api/task_router.js +++ b/core/database/foxx/api/task_router.js @@ -1,27 +1,30 @@ -'use strict'; +"use strict"; -const createRouter = require('@arangodb/foxx/router'); +const createRouter = require("@arangodb/foxx/router"); const router = createRouter(); -const joi = require('joi'); -const g_db = require('@arangodb').db; -const g_lib = require('./support'); -const g_tasks = require('./tasks'); +const joi = require("joi"); +const g_db = require("@arangodb").db; +const g_lib = require("./support"); +const g_tasks = require("./tasks"); module.exports = router; - //==================== TASK API FUNCTIONS -router.get('/view', function(req, res) { +router + .get("/view", function (req, res) { try { if (!g_db._exists(req.queryParams.task_id)) { // WARNING - do not change this error message it is acted on by the task worker - throw [g_lib.ERR_INVALID_PARAM, "Task " + req.queryParams.task_id + " does not exist."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Task " + req.queryParams.task_id + " does not exist.", + ]; } var task = g_db.task.document(req.queryParams.task_id); var blocks = g_db.block.byExample({ - _from: req.queryParams.task_id + _from: req.queryParams.task_id, }); task.blocked_by = []; while (blocks.hasNext()) { @@ -29,7 +32,7 @@ router.get('/view', function(req, res) { } blocks = g_db.block.byExample({ - _to: req.queryParams.task_id + _to: req.queryParams.task_id, }); task.blocking = []; while (blocks.hasNext()) { @@ -44,12 +47,12 @@ router.get('/view', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('task_id', joi.string().required(), "Task ID") - .summary('View an existing task record') - .description('View an existing task record.'); - + .queryParam("task_id", joi.string().required(), "Task ID") + .summary("View an existing task record") + .description("View an existing task record."); -router.get('/run', function(req, res) { +router + .get("/run", function (req, res) { var task, run_func; //console.log("task/run - trans 1"); @@ -58,13 +61,16 @@ router.get('/run', function(req, res) { g_db._executeTransaction({ collections: { read: [], - write: ["task"] + write: ["task"], }, lockTimeout: 0, waitForSync: true, - action: function() { + action: function () { if (!g_db.task.exists(req.queryParams.task_id)) - throw [g_lib.ERR_INVALID_PARAM, "Task " + req.queryParams.task_id + " does not exist."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Task " + req.queryParams.task_id + " does not exist.", + ]; task = g_db.task.document(req.queryParams.task_id); run_func = g_tasks.taskGetRunFunc(task); @@ -79,23 +85,50 @@ router.get('/run', function(req, res) { g_tasks.taskReady(task._id); } else if (task.status == g_lib.TS_RUNNING) { console.log("task/run: ", task._id, " - step is: ", req.queryParams.step); - if (req.queryParams.step != undefined && req.queryParams.step == task.step) { + if ( + req.queryParams.step != undefined && + req.queryParams.step == task.step + ) { // This confirms previous step was completed, so update step number task.step++; - console.log("task/run: ", task._id, " - step after incrementing is: ", task.step); - g_db.task.update(task._id, { - step: task.step, - ut: Math.floor(Date.now() / 1000) - }, { - waitForSync: true - }); - } else if (req.queryParams.step != undefined && req.queryParams.step >= task.steps) { - throw [g_lib.ERR_INVALID_PARAM, "Called run on task " + task._id + " with invalid step: " + req.queryParams.step]; + console.log( + "task/run: ", + task._id, + " - step after incrementing is: ", + task.step, + ); + g_db.task.update( + task._id, + { + step: task.step, + ut: Math.floor(Date.now() / 1000), + }, + { + waitForSync: true, + }, + ); + } else if ( + req.queryParams.step != undefined && + req.queryParams.step >= task.steps + ) { + throw [ + g_lib.ERR_INVALID_PARAM, + "Called run on task " + + task._id + + " with invalid step: " + + req.queryParams.step, + ]; } } else { - throw [g_lib.ERR_INVALID_PARAM, "Called run on task " + task._id + " with incorrect status: " + task.status]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Called run on task " + + task._id + + " with incorrect status: " + + task.status, + ]; } - } + }, }); //console.log("task/run - call handler" ); @@ -114,14 +147,13 @@ router.get('/run', function(req, res) { //console.log("Task run handler stopped rollback" ); result = { cmd: g_lib.TC_STOP, - params: g_tasks.taskComplete(task._id, false, task.error) + params: g_tasks.taskComplete(task._id, false, task.error), }; } break; } catch (e) { var err = Array.isArray(e) ? e[1] : e; - if (err.errorMessage) - err = err.errorMessage; + if (err.errorMessage) err = err.errorMessage; console.log("Task run handler exception: " + err); @@ -132,19 +164,27 @@ router.get('/run', function(req, res) { // Exception on processing, start roll-back task.step = -task.step; task.error = String(err); - g_db.task.update(task._id, { - step: task.step, - error: task.error, - ut: Math.floor(Date.now() / 1000) - }, { - waitForSync: true - }); + g_db.task.update( + task._id, + { + step: task.step, + error: task.error, + ut: Math.floor(Date.now() / 1000), + }, + { + waitForSync: true, + }, + ); } else { console.log("Exception in rollback"); // Exception on roll-back, abort and return next tasks to process result = { cmd: g_lib.TC_STOP, - params: g_tasks.taskComplete(task._id, false, task.error + " (Rollback failed: " + err + ")") + params: g_tasks.taskComplete( + task._id, + false, + task.error + " (Rollback failed: " + err + ")", + ), }; break; } @@ -155,37 +195,49 @@ router.get('/run', function(req, res) { //console.log("task/run return"); res.send(result); - } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('task_id', joi.string().required(), "Task ID") - .queryParam('step', joi.number().integer().optional(), "Task step") - .queryParam('err_msg', joi.string().optional(), "Error message") - .summary('Run task') - .description('Run an initialized task. Step param confirms last command. Error message indicates external permanent failure.'); - -/** @brief Clean-up a task and remove it from task dependency graph + .queryParam("task_id", joi.string().required(), "Task ID") + .queryParam("step", joi.number().integer().optional(), "Task step") + .queryParam("err_msg", joi.string().optional(), "Error message") + .summary("Run task") + .description( + "Run an initialized task. Step param confirms last command. Error message indicates external permanent failure.", + ); + +/** + * @function + * @description Cleans up a task by removing it from the task dependency graph. + * It removes dependency locks and patches the task dependency graph both upstream and downstream. + * It returns a list of new runnable tasks if available. + * + * @param {object} req - The request object containing the task ID in the query parameters and other relevant data in the body. + * @param {object} res - The response object used to send the result or an error message. + * @returns {void} Sends a list of new runnable tasks to the response. * - * Removes dependency locks and patches task dependency graph (up and down - * stream). Returns list of new runnable tasks if available. + * @throws {Error} Throws an error if the task does not exist or if there's an issue processing the transaction. */ -router.post('/abort', function(req, res) { +router + .post("/abort", function (req, res) { try { var result = []; g_db._executeTransaction({ collections: { read: [], write: ["task"], - exclusive: ["lock", "block"] + exclusive: ["lock", "block"], }, - action: function() { + action: function () { if (!g_db._exists(req.queryParams.task_id)) - throw [g_lib.ERR_INVALID_PARAM, "Task " + req.queryParams.task_id + " does not exist."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Task " + req.queryParams.task_id + " does not exist.", + ]; result = g_tasks.taskComplete(req.queryParams.task_id, false, req.body); - } + }, }); res.send(result); @@ -193,16 +245,19 @@ router.post('/abort', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('task_id', joi.string().required(), "Task ID") - .body(joi.string().required(), 'Parameters') - .summary('Abort a schedule task') - .description('Abort a schedule task and return list of new runnable tasks.'); - + .queryParam("task_id", joi.string().required(), "Task ID") + .body(joi.object().optional(), "Parameters") + .summary("Abort a schedule task") + .description("Abort a schedule task and return list of new runnable tasks."); -router.post('/delete', function(req, res) { +router + .post("/delete", function (req, res) { try { if (!g_db._exists(req.queryParams.task_id)) - throw [g_lib.ERR_INVALID_PARAM, "Task " + req.queryParams.task_id + " does not exist."]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Task " + req.queryParams.task_id + " does not exist.", + ]; var task = g_db.task.document(req.queryParams.task_id); if (task.status < g_lib.TS_SUCCEEDED) @@ -213,22 +268,22 @@ router.post('/delete', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('task_id', joi.string().required(), "Task ID") - .summary('Delete an existing task record') - .description('Delete an existing finalized task record.'); + .queryParam("task_id", joi.string().required(), "Task ID") + .summary("Delete an existing task record") + .description("Delete an existing finalized task record."); - -router.get('/list', function(req, res) { +router + .get("/list", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); var params = { - client: client._id + client: client._id, }; var qry = "for i in task filter i.client == @client"; if (req.queryParams.since) { - qry += " and i.ut >= " + ((Date.now() / 1000) - req.queryParams.since); + qry += " and i.ut >= " + (Date.now() / 1000 - req.queryParams.since); } else { if (req.queryParams.from != undefined) { qry += " and i.ut >= " + req.queryParams.from; @@ -259,29 +314,41 @@ router.get('/list', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('status', joi.array().items(joi.number().integer()).optional(), "List of task states to retrieve.") - .queryParam('since', joi.number().integer().min(0).optional(), "List tasks updated since this many seconds ago.") - .queryParam('from', joi.number().integer().min(0).optional(), "List tasks from this timestamp.") - .queryParam('to', joi.number().integer().min(0).optional(), "List tasks to this timestamp.") - .queryParam('offset', joi.number().integer().min(0).optional(), "Offset") - .queryParam('count', joi.number().integer().min(0).optional(), "Count") - .summary('List task records') - .description('List task records.'); - - -router.get('/reload', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam( + "status", + joi.array().items(joi.number().integer()).optional(), + "List of task states to retrieve.", + ) + .queryParam( + "since", + joi.number().integer().min(0).optional(), + "List tasks updated since this many seconds ago.", + ) + .queryParam("from", joi.number().integer().min(0).optional(), "List tasks from this timestamp.") + .queryParam("to", joi.number().integer().min(0).optional(), "List tasks to this timestamp.") + .queryParam("offset", joi.number().integer().min(0).optional(), "Offset") + .queryParam("count", joi.number().integer().min(0).optional(), "Count") + .summary("List task records") + .description("List task records."); + +router + .get("/reload", function (req, res) { try { var result = []; g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn"], - exclusive: ["task", "lock", "block"] + exclusive: ["task", "lock", "block"], + }, + action: function () { + result = g_db + ._query( + "for i in task filter i.status > 0 and i.status < 3 sort i.status desc return i._id", + ) + .toArray(); }, - action: function() { - result = g_db._query("for i in task filter i.status > 0 and i.status < 3 sort i.status desc return i._id").toArray(); - } }); res.send(result); @@ -289,28 +356,33 @@ router.get('/reload', function(req, res) { g_lib.handleException(e, res); } }) - .summary('Reload ready/running task records') - .description('Reload ready/running task records.'); + .summary("Reload ready/running task records") + .description("Reload ready/running task records."); -router.get('/purge', function(req, res) { +router + .get("/purge", function (req, res) { try { g_db._executeTransaction({ collections: { read: [], - exclusive: ["task", "lock", "block"] + exclusive: ["task", "lock", "block"], }, - action: function() { - var t = (Date.now() / 1000) - req.queryParams.age_sec; + action: function () { + var t = Date.now() / 1000 - req.queryParams.age_sec; // TODO This does NOT remove edges! - g_db._query("for i in task filter i.status >= " + g_lib.TS_SUCCEEDED + " and i.ut < " + t + " remove i in task"); - } + g_db._query( + "for i in task filter i.status >= " + + g_lib.TS_SUCCEEDED + + " and i.ut < " + + t + + " remove i in task", + ); + }, }); - - } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('age_sec', joi.number().integer().min(0).required(), "Purge age (seconds)") - .summary('Purge completed task records') - .description('Purge completed task records.'); \ No newline at end of file + .queryParam("age_sec", joi.number().integer().min(0).required(), "Purge age (seconds)") + .summary("Purge completed task records") + .description("Purge completed task records."); diff --git a/core/database/foxx/api/tasks.js b/core/database/foxx/api/tasks.js index dc35a24b8..0e163b89b 100644 --- a/core/database/foxx/api/tasks.js +++ b/core/database/foxx/api/tasks.js @@ -1,17 +1,26 @@ -'use strict'; +"use strict"; -const g_db = require('@arangodb').db; -const g_lib = require('./support'); -const g_graph = require('@arangodb/general-graph')._graph('sdmsg'); -const g_proc = require('./process'); +// local imports +const g_lib = require("./support"); +const { UserToken } = require("./lib/user_token"); + +const g_db = require("@arangodb").db; +const g_graph = require("@arangodb/general-graph")._graph("sdmsg"); +const g_proc = require("./process"); var g_internal = require("internal"); -var tasks_func = function() { +var tasks_func = (function () { var obj = {}; // ----------------------- ALLOC CREATE ---------------------------- - obj.taskInitAllocCreate = function(a_client, a_repo_id, a_subject_id, a_data_limit, a_rec_limit) { + obj.taskInitAllocCreate = function ( + a_client, + a_repo_id, + a_subject_id, + a_data_limit, + a_rec_limit, + ) { console.log("taskInitAllocCreate"); // Check if repo and subject exist @@ -27,102 +36,125 @@ var tasks_func = function() { // Check if there is already a matching allocation var alloc = g_db.alloc.firstExample({ _from: a_subject_id, - _to: a_repo_id + _to: a_repo_id, }); if (alloc) - throw [g_lib.ERR_INVALID_PARAM, "Subject, '" + a_subject_id + "', already has as allocation on " + a_repo_id]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Subject, '" + a_subject_id + "', already has as allocation on " + a_repo_id, + ]; // Check if there is an existing alloc task to involving the same allocation (repo + subject) - var res = g_db._query("for v, e in 1..1 inbound @repo lock filter e.context == @subj && v.type == @type return v._id", { - repo: a_repo_id, - subj: a_subject_id, - type: g_lib.TT_ALLOC_CREATE - }); + var res = g_db._query( + "for v, e in 1..1 inbound @repo lock filter e.context == @subj && v.type == @type return v._id", + { + repo: a_repo_id, + subj: a_subject_id, + type: g_lib.TT_ALLOC_CREATE, + }, + ); if (res.hasNext()) { throw [g_lib.ERR_IN_USE, "A duplicate allocation create task was found."]; } var repo = g_db.repo.document(a_repo_id); - var path = repo.path + (a_subject_id.charAt(0) == "p" ? "project/" : "user/") + a_subject_id.substr(2) + "/"; + var path = + repo.path + + (a_subject_id.charAt(0) == "p" ? "project/" : "user/") + + a_subject_id.substr(2) + + "/"; var state = { repo_id: a_repo_id, subject: a_subject_id, data_limit: a_data_limit, rec_limit: a_rec_limit, - repo_path: path + repo_path: path, }; var task = obj._createTask(a_client._id, g_lib.TT_ALLOC_CREATE, 2, state); - if (g_proc._lockDepsGeneral(task._id, [{ - id: a_repo_id, - lev: 1, - ctx: a_subject_id - }, { - id: a_subject_id, - lev: 0 - }])) { - task = g_db.task.update(task._id, { - status: g_lib.TS_BLOCKED, - msg: "Queued" - }, { - returnNew: true, - waitForSync: true - }).new; + if ( + g_proc._lockDepsGeneral(task._id, [ + { + id: a_repo_id, + lev: 1, + ctx: a_subject_id, + }, + { + id: a_subject_id, + lev: 0, + }, + ]) + ) { + task = g_db.task.update( + task._id, + { + status: g_lib.TS_BLOCKED, + msg: "Queued", + }, + { + returnNew: true, + waitForSync: true, + }, + ).new; } return { - "task": task + task: task, }; }; - obj.taskRunAllocCreate = function(a_task) { + obj.taskRunAllocCreate = function (a_task) { console.log("taskRunAllocCreate"); - var reply, state = a_task.state; + var reply, + state = a_task.state; // No rollback functionality - if (a_task.step < 0) - return; + if (a_task.step < 0) return; if (a_task.step === 0) { reply = { cmd: g_lib.TC_ALLOC_CREATE, params: { repo_id: state.repo_id, - repo_path: state.repo_path + repo_path: state.repo_path, }, - step: a_task.step + step: a_task.step, }; } else { // Create allocation edge and finish - obj._transact(function() { - //console.log("saving alloc:", state.subject, state.repo_id, state.data_limit, state.rec_limit, 0, 0, state.repo_path ); - - g_db.alloc.save({ - _from: state.subject, - _to: state.repo_id, - data_limit: state.data_limit, - rec_limit: state.rec_limit, - rec_count: 0, - data_size: 0, - path: state.repo_path - }); - reply = { - cmd: g_lib.TC_STOP, - params: obj.taskComplete(a_task._id, true) - }; - }, [], ["task", "alloc"], ["lock", "block"]); + obj._transact( + function () { + //console.log("saving alloc:", state.subject, state.repo_id, state.data_limit, state.rec_limit, 0, 0, state.repo_path ); + + g_db.alloc.save({ + _from: state.subject, + _to: state.repo_id, + data_limit: state.data_limit, + rec_limit: state.rec_limit, + rec_count: 0, + data_size: 0, + path: state.repo_path, + }); + reply = { + cmd: g_lib.TC_STOP, + params: obj.taskComplete(a_task._id, true), + }; + }, + [], + ["task", "alloc"], + ["lock", "block"], + ); } return reply; }; - // ----------------------- ALLOC DELETE ---------------------------- - obj.taskInitAllocDelete = function(a_client, a_repo_id, a_subject_id) { + obj.taskInitAllocDelete = function (a_client, a_repo_id, a_subject_id) { console.log("taskInitAllocDelete"); if (!g_db._exists(a_repo_id)) @@ -137,92 +169,124 @@ var tasks_func = function() { var alloc = g_db.alloc.firstExample({ _from: a_subject_id, - _to: a_repo_id + _to: a_repo_id, }); if (!alloc) - throw [g_lib.ERR_NOT_FOUND, "Subject, '" + a_subject_id + "', has no allocation on " + a_repo_id]; - - var count = g_db._query("return length(for v, e in 1..1 inbound @repo loc filter e.uid == @subj return 1)", { - repo: a_repo_id, - subj: a_subject_id - }).next(); - if (count) - throw [g_lib.ERR_IN_USE, "Cannot delete allocation - records present"]; + throw [ + g_lib.ERR_NOT_FOUND, + "Subject, '" + a_subject_id + "', has no allocation on " + a_repo_id, + ]; + + var count = g_db + ._query( + "return length(for v, e in 1..1 inbound @repo loc filter e.uid == @subj return 1)", + { + repo: a_repo_id, + subj: a_subject_id, + }, + ) + .next(); + if (count) throw [g_lib.ERR_IN_USE, "Cannot delete allocation - records present"]; // Check if there is an existing alloc task to involving the same allocation (repo + subject) - var res = g_db._query("for v, e in 1..1 inbound @repo lock filter e.context == @subj && v.type == @type return v._id", { - repo: a_repo_id, - subj: a_subject_id, - type: g_lib.TT_ALLOC_DEL - }); + var res = g_db._query( + "for v, e in 1..1 inbound @repo lock filter e.context == @subj && v.type == @type return v._id", + { + repo: a_repo_id, + subj: a_subject_id, + type: g_lib.TT_ALLOC_DEL, + }, + ); if (res.hasNext()) { throw [g_lib.ERR_IN_USE, "A duplicate allocation delete task was found."]; } - var path = repo.path + (a_subject_id.charAt(0) == "p" ? "project/" : "user/") + a_subject_id.substr(2) + "/"; + var path = + repo.path + + (a_subject_id.charAt(0) == "p" ? "project/" : "user/") + + a_subject_id.substr(2) + + "/"; var state = { repo_id: a_repo_id, subject: a_subject_id, - repo_path: path + repo_path: path, }; var task = obj._createTask(a_client._id, g_lib.TT_ALLOC_DEL, 2, state); - if (g_proc._lockDepsGeneral(task._id, [{ - id: a_repo_id, - lev: 1, - ctx: a_subject_id - }, { - id: a_subject_id, - lev: 0 - }])) { - task = g_db.task.update(task._id, { - status: g_lib.TS_BLOCKED, - msg: "Queued" - }, { - returnNew: true, - waitForSync: true - }).new; + if ( + g_proc._lockDepsGeneral(task._id, [ + { + id: a_repo_id, + lev: 1, + ctx: a_subject_id, + }, + { + id: a_subject_id, + lev: 0, + }, + ]) + ) { + task = g_db.task.update( + task._id, + { + status: g_lib.TS_BLOCKED, + msg: "Queued", + }, + { + returnNew: true, + waitForSync: true, + }, + ).new; } return { - "task": task + task: task, }; }; - obj.taskRunAllocDelete = function(a_task) { + obj.taskRunAllocDelete = function (a_task) { console.log("taskRunAllocDelete"); - var reply, state = a_task.state; + var reply, + state = a_task.state; // No rollback functionality - if (a_task.step < 0) - return; + if (a_task.step < 0) return; if (a_task.step == 0) { // Delete alloc edge, request repo path delete - obj._transact(function() { - g_db.alloc.removeByExample({ - _from: state.subject, - _to: state.repo_id - }); - reply = { - cmd: g_lib.TC_ALLOC_DELETE, - params: { - repo_id: state.repo_id, - repo_path: state.repo_path - }, - step: a_task.step - }; - }, [], ["alloc"]); + obj._transact( + function () { + g_db.alloc.removeByExample({ + _from: state.subject, + _to: state.repo_id, + }); + reply = { + cmd: g_lib.TC_ALLOC_DELETE, + params: { + repo_id: state.repo_id, + repo_path: state.repo_path, + }, + step: a_task.step, + }; + }, + [], + ["alloc"], + ); } else { // Complete task - obj._transact(function() { - reply = { - cmd: g_lib.TC_STOP, - params: obj.taskComplete(a_task._id, true) - }; - }, [], ["task"], ["lock", "block"]); + obj._transact( + function () { + reply = { + cmd: g_lib.TC_STOP, + params: obj.taskComplete(a_task._id, true), + }; + }, + [], + ["task"], + ["lock", "block"], + ); } return reply; @@ -230,33 +294,53 @@ var tasks_func = function() { // ----------------------- DATA GET ---------------------------- - obj.taskInitDataGet = function(a_client, a_path, a_encrypt, a_res_ids, a_orig_fname, a_check) { + obj.taskInitDataGet = function ( + a_client, + a_path, + a_encrypt, + a_res_ids, + a_orig_fname, + a_check, + is_collection_token_required = false, + collection_info = {}, + ) { console.log("taskInitDataGet"); var result = g_proc.preprocessItems(a_client, null, a_res_ids, g_lib.TT_DATA_GET); - if ((result.glob_data.length + result.ext_data.length) > 0 && !a_check) { + if (result.glob_data.length + result.ext_data.length > 0 && !a_check) { var idx = a_path.indexOf("/"); if (idx == -1) throw [g_lib.ERR_INVALID_PARAM, "Invalid destination path (must include endpoint)"]; // Check for duplicate names if (a_orig_fname) { - var fname, fnames = new Set(); + var fname, + fnames = new Set(); for (i in result.glob_data) { - fname = result.glob_data[i].source.substr(result.glob_data[i].source.lastIndexOf("/") + 1); + fname = result.glob_data[i].source.substr( + result.glob_data[i].source.lastIndexOf("/") + 1, + ); if (fnames.has(fname)) { - throw [g_lib.ERR_XFR_CONFLICT, "Duplicate filename(s) detected in transfer request."]; + throw [ + g_lib.ERR_XFR_CONFLICT, + "Duplicate filename(s) detected in transfer request.", + ]; } fnames.add(fname); } for (i in result.ext_data) { - fname = result.ext_data[i].source.substr(result.ext_data[i].source.lastIndexOf("/") + 1); + fname = result.ext_data[i].source.substr( + result.ext_data[i].source.lastIndexOf("/") + 1, + ); if (fnames.has(fname)) { - throw [g_lib.ERR_XFR_CONFLICT, "Duplicate filename(s) detected in transfer request."]; + throw [ + g_lib.ERR_XFR_CONFLICT, + "Duplicate filename(s) detected in transfer request.", + ]; } fnames.add(fname); @@ -268,26 +352,31 @@ var tasks_func = function() { encrypt: a_encrypt, orig_fname: a_orig_fname, glob_data: result.glob_data, - ext_data: result.ext_data + ext_data: result.ext_data, + is_collection_token_required: is_collection_token_required, + collection_info: collection_info, }, task = obj._createTask(a_client._id, g_lib.TT_DATA_GET, 2, state), - i, dep_ids = []; + i, + dep_ids = []; // Determine if any other tasks use the selected records and queue this task if needed - for (i in result.glob_data) - dep_ids.push(result.glob_data[i]._id); + for (i in result.glob_data) dep_ids.push(result.glob_data[i]._id); - for (i in result.ext_data) - dep_ids.push(result.ext_data[i]._id); + for (i in result.ext_data) dep_ids.push(result.ext_data[i]._id); if (g_proc._processTaskDeps(task._id, dep_ids, 0, 0)) { - task = g_db._update(task._id, { - status: g_lib.TS_BLOCKED, - msg: "Queued" - }, { - returnNew: true - }).new; + task = g_db._update( + task._id, + { + status: g_lib.TS_BLOCKED, + msg: "Queued", + }, + { + returnNew: true, + }, + ).new; } result.task = task; @@ -296,65 +385,92 @@ var tasks_func = function() { return result; }; - obj.taskRunDataGet = function(a_task) { + obj.taskRunDataGet = function (a_task) { console.log("taskRunDataGet"); - var reply, state = a_task.state; + var reply, + state = a_task.state; // No rollback functionality - if (a_task.step < 0) - return; + if (a_task.step < 0) return; if (a_task.step == 0) { //console.log("taskRunDataGet - do setup"); - obj._transact(function() { - // Generate transfer steps - state.xfr = obj._buildTransferDoc(g_lib.TT_DATA_GET, state.glob_data, state.ext_data, state.path, state.orig_fname); - // Update step info - a_task.step = 1; - a_task.steps = state.xfr.length + 2; - // Update task - g_db._update(a_task._id, { - step: a_task.step, - steps: a_task.steps, - state: { - xfr: state.xfr - }, - ut: Math.floor(Date.now() / 1000) - }); - // Fall-through to initiate first transfer - }, ["repo", "loc"], ["task"]); + obj._transact( + function () { + // Generate transfer steps + state.xfr = obj._buildTransferDoc( + g_lib.TT_DATA_GET, + state.glob_data, + state.ext_data, + state.path, + state.orig_fname, + ); + // Update step info + a_task.step = 1; + a_task.steps = state.xfr.length + 2; + // Update task + g_db._update(a_task._id, { + step: a_task.step, + steps: a_task.steps, + state: { + xfr: state.xfr, + }, + ut: Math.floor(Date.now() / 1000), + }); + // Fall-through to initiate first transfer + }, + ["repo", "loc"], + ["task"], + ); } if (a_task.step < a_task.steps - 1) { //console.log("taskRunDataGet - do xfr"); // Transfer data step - var tokens = g_lib.getAccessToken(a_task.client); + const token_doc = new UserToken({ + user_id: a_task.client, + globus_collection_id: state.collection_info.collection_id, + }).get_token(); + var tokens = UserToken.formatUserTokenForTransferTask(token_doc); + const extra_token_format = UserToken.formatUserToken( + state.is_collection_token_required, + token_doc, + false, + ); var params = { uid: a_task.client, type: a_task.type, encrypt: state.encrypt, acc_tok: tokens.acc_tok, ref_tok: tokens.ref_tok, - acc_tok_exp_in: tokens.acc_tok_exp_in + acc_tok_exp_in: tokens.acc_tok_exp_in, + token_type: extra_token_format.token_type, + scopes: extra_token_format.scopes, + collection_id: state.collection_info.collection_id, }; params = Object.assign(params, state.xfr[a_task.step - 1]); reply = { cmd: g_lib.TC_RAW_DATA_TRANSFER, params: params, - step: a_task.step + step: a_task.step, }; } else { //console.log("taskRunDataGet - complete task"); - obj._transact(function() { - // Last step - complete task - reply = { - cmd: g_lib.TC_STOP, - params: obj.taskComplete(a_task._id, true) - }; - }, [], ["task"], ["lock", "block"]); + obj._transact( + function () { + // Last step - complete task + reply = { + cmd: g_lib.TC_STOP, + params: obj.taskComplete(a_task._id, true), + }; + }, + [], + ["task"], + ["lock", "block"], + ); } return reply; @@ -362,7 +478,16 @@ var tasks_func = function() { // ----------------------- DATA PUT ---------------------------- - obj.taskInitDataPut = function(a_client, a_path, a_encrypt, a_ext, a_res_ids, a_check) { + obj.taskInitDataPut = function ( + a_client, + a_path, + a_encrypt, + a_ext, + a_res_ids, + a_check, + is_collection_token_required = false, + collection_info = {}, + ) { console.log("taskInitDataPut"); var result = g_proc.preprocessItems(a_client, null, a_res_ids, g_lib.TT_DATA_PUT); @@ -376,21 +501,26 @@ var tasks_func = function() { path: a_path, encrypt: a_encrypt, ext: a_ext, - glob_data: result.glob_data + glob_data: result.glob_data, + is_collection_token_required: is_collection_token_required, + collection_info: collection_info, }; var task = obj._createTask(a_client._id, g_lib.TT_DATA_PUT, 2, state); var dep_ids = []; - for (var i in result.glob_data) - dep_ids.push(result.glob_data[i].id); + for (var i in result.glob_data) dep_ids.push(result.glob_data[i].id); if (g_proc._processTaskDeps(task._id, dep_ids, 1, 0)) { - task = g_db._update(task._id, { - status: g_lib.TS_BLOCKED, - msg: "Queued" - }, { - returnNew: true - }).new; + task = g_db._update( + task._id, + { + status: g_lib.TS_BLOCKED, + msg: "Queued", + }, + { + returnNew: true, + }, + ).new; } result.task = task; @@ -399,55 +529,79 @@ var tasks_func = function() { return result; }; - obj.taskRunDataPut = function(a_task) { + obj.taskRunDataPut = function (a_task) { console.log("taskRunDataPut"); - var reply, state = a_task.state, - params, xfr, retry; + var reply, + state = a_task.state, + params, + xfr, + retry; // No rollback functionality - if (a_task.step < 0) - return; + if (a_task.step < 0) return; console.log("taskRunDataPut begin Step: ", a_task.step); if (a_task.step == 0) { //console.log("taskRunDataPut - do setup"); - obj._transact(function() { - // Generate transfer steps - state.xfr = obj._buildTransferDoc(g_lib.TT_DATA_PUT, state.glob_data, null, state.path, false); - // Update step info - a_task.step = 1; - a_task.steps = state.xfr.length + 3; - // Update task - g_db._update(a_task._id, { - step: a_task.step, - steps: a_task.steps, - state: { - xfr: state.xfr - }, - ut: Math.floor(Date.now() / 1000) - }); - // Fall-through to initiate first transfer - }, ["repo", "loc"], ["task"]); + obj._transact( + function () { + // Generate transfer steps + state.xfr = obj._buildTransferDoc( + g_lib.TT_DATA_PUT, + state.glob_data, + null, + state.path, + false, + ); + // Update step info + a_task.step = 1; + a_task.steps = state.xfr.length + 3; + // Update task + g_db._update(a_task._id, { + step: a_task.step, + steps: a_task.steps, + state: { + xfr: state.xfr, + }, + ut: Math.floor(Date.now() / 1000), + }); + // Fall-through to initiate first transfer + }, + ["repo", "loc"], + ["task"], + ); } if (a_task.step < a_task.steps - 2) { //console.log("taskRunDataPut - do xfr"); // Transfer data step - var tokens = g_lib.getAccessToken(a_task.client); + const token_doc = new UserToken({ + user_id: a_task.client, + globus_collection_id: state.collection_info.collection_id, + }).get_token(); + var tokens = UserToken.formatUserTokenForTransferTask(token_doc); + const extra_token_format = UserToken.formatUserToken( + state.is_collection_token_required, + token_doc, + false, + ); params = { uid: a_task.client, type: a_task.type, encrypt: state.encrypt, acc_tok: tokens.acc_tok, ref_tok: tokens.ref_tok, - acc_tok_exp_in: tokens.acc_tok_exp_in + acc_tok_exp_in: tokens.acc_tok_exp_in, + token_type: extra_token_format.token_type, + scopes: extra_token_format.scopes, + collection_id: state.collection_info.collection_id, }; params = Object.assign(params, state.xfr[a_task.step - 1]); reply = { cmd: g_lib.TC_RAW_DATA_TRANSFER, params: params, - step: a_task.step + step: a_task.step, }; } else if (a_task.step < a_task.steps - 1) { xfr = state.xfr[a_task.step - 2]; @@ -462,9 +616,7 @@ var tasks_func = function() { upd_rec.ext = state.ext; upd_rec.ext_auto = false; - if (upd_rec.ext.charAt(0) != ".") - upd_rec.ext = "." + upd_rec.ext; - + if (upd_rec.ext.charAt(0) != ".") upd_rec.ext = "." + upd_rec.ext; } else if (rec.ext_auto) { var src = xfr.files[0].from; @@ -482,11 +634,16 @@ var tasks_func = function() { for (;;) { try { - obj._transact(function() { - g_db._update(xfr.files[0].id, upd_rec, { - keepNull: false - }); - }, [], ["d"], []); + obj._transact( + function () { + g_db._update(xfr.files[0].id, upd_rec, { + keepNull: false, + }); + }, + [], + ["d"], + [], + ); break; } catch (e) { if (--retry === 0 || !e.errorNum || e.errorNum != 1200) { @@ -499,7 +656,7 @@ var tasks_func = function() { params = { repo_id: xfr.dst_repo_id, repo_path: xfr.dst_repo_path, - ids: [xfr.files[0].id] + ids: [xfr.files[0].id], }; console.log("Printing params in task update size"); @@ -507,17 +664,22 @@ var tasks_func = function() { reply = { cmd: g_lib.TC_RAW_DATA_UPDATE_SIZE, params: params, - step: a_task.step + step: a_task.step, }; } else { //console.log("taskRunDataPut - complete task"); - obj._transact(function() { - // Last step - complete task - reply = { - cmd: g_lib.TC_STOP, - params: obj.taskComplete(a_task._id, true) - }; - }, [], ["task"], ["lock", "block"]); + obj._transact( + function () { + // Last step - complete task + reply = { + cmd: g_lib.TC_STOP, + params: obj.taskComplete(a_task._id, true), + }; + }, + [], + ["task"], + ["lock", "block"], + ); } console.log("taskRunDataPut final reply"); @@ -532,7 +694,7 @@ var tasks_func = function() { records and the destination repository, and updating the statistics of all involved allocations. Unmanaged records do not use allocations and are ignored. */ - obj.taskInitRecAllocChg = function(a_client, a_proj_id, a_res_ids, a_dst_repo_id, a_check) { + obj.taskInitRecAllocChg = function (a_client, a_proj_id, a_res_ids, a_dst_repo_id, a_check) { console.log("taskInitRecAllocChg"); // Verify that client is owner, or has admin permission to project owner @@ -557,17 +719,24 @@ var tasks_func = function() { // Verify client/owner has an allocation var alloc = g_db.alloc.firstExample({ _from: owner_id, - _to: a_dst_repo_id + _to: a_dst_repo_id, }); - if (!alloc) - throw [g_lib.ERR_INVALID_PARAM, "No allocation on '" + a_dst_repo_id + "'"]; + if (!alloc) throw [g_lib.ERR_INVALID_PARAM, "No allocation on '" + a_dst_repo_id + "'"]; - var result = g_proc.preprocessItems({ - _id: owner_id, - is_admin: false - }, null, a_res_ids, g_lib.TT_REC_ALLOC_CHG); + var result = g_proc.preprocessItems( + { + _id: owner_id, + is_admin: false, + }, + null, + a_res_ids, + g_lib.TT_REC_ALLOC_CHG, + ); - var i, loc, rec, rec_ids = []; + var i, + loc, + rec, + rec_ids = []; result.tot_cnt = result.ext_data.length + result.glob_data.length; result.act_size = 0; @@ -575,7 +744,7 @@ var tasks_func = function() { for (i in result.glob_data) { rec = result.glob_data[i]; loc = g_db.loc.firstExample({ - _from: rec.id + _from: rec.id, }); if (loc && loc._to != a_dst_repo_id) { rec_ids.push(rec.id); @@ -592,24 +761,27 @@ var tasks_func = function() { result.rec_count = alloc.rec_count; // Stop if no record to process, or if this is just a check - if (rec_ids.length === 0 || a_check) - return result; + if (rec_ids.length === 0 || a_check) return result; var state = { encrypt: 1, glob_data: result.glob_data, dst_repo_id: a_dst_repo_id, - owner_id: owner_id + owner_id: owner_id, }; var task = obj._createTask(a_client._id, g_lib.TT_REC_ALLOC_CHG, 2, state); if (g_proc._processTaskDeps(task._id, rec_ids, 1, 0)) { - task = g_db._update(task._id, { - status: g_lib.TS_BLOCKED, - msg: "Queued" - }, { - returnNew: true - }).new; + task = g_db._update( + task._id, + { + status: g_lib.TS_BLOCKED, + msg: "Queued", + }, + { + returnNew: true, + }, + ).new; } result.task = task; @@ -617,11 +789,16 @@ var tasks_func = function() { return result; }; - obj.taskRunRecAllocChg = function(a_task) { + obj.taskRunRecAllocChg = function (a_task) { console.log("taskRunRecAllocChg"); - var reply, state = a_task.state, - params, xfr, alloc, substep, xfrnum; + var reply, + state = a_task.state, + params, + xfr, + alloc, + substep, + xfrnum; // TODO Add rollback functionality if (a_task.step < 0) { @@ -636,17 +813,21 @@ var tasks_func = function() { // Only action is to revert location in DB if transfer failed. if (substep > 0 && substep < 3) { - obj._transact(function() { - //console.log("taskRunRecAllocChg - recMoveRevert" ); - obj.recMoveRevert(xfr.files); - - // Update task step - a_task.step -= substep; - g_db._update(a_task._id, { - step: a_task.step, - ut: Math.floor(Date.now() / 1000) - }); - }, [], ["loc", "task"]); + obj._transact( + function () { + //console.log("taskRunRecAllocChg - recMoveRevert" ); + obj.recMoveRevert(xfr.files); + + // Update task step + a_task.step -= substep; + g_db._update(a_task._id, { + step: a_task.step, + ut: Math.floor(Date.now() / 1000), + }); + }, + [], + ["loc", "task"], + ); } } @@ -655,23 +836,34 @@ var tasks_func = function() { if (a_task.step == 0) { //console.log("taskRunRecAllocChg - do setup"); - obj._transact(function() { - // Generate transfer steps - state.xfr = obj._buildTransferDoc(g_lib.TT_REC_ALLOC_CHG, state.glob_data, null, state.dst_repo_id, false, state.owner_id); - // Recalculate number of steps - a_task.step = 1; - a_task.steps = (state.xfr.length * 4) + 2; - // Update task - g_db._update(a_task._id, { - step: a_task.step, - steps: a_task.steps, - state: { - xfr: state.xfr - }, - ut: Math.floor(Date.now() / 1000) - }); - // Fall-through to initiate first transfer - }, ["repo", "loc"], ["task"]); + obj._transact( + function () { + // Generate transfer steps + state.xfr = obj._buildTransferDoc( + g_lib.TT_REC_ALLOC_CHG, + state.glob_data, + null, + state.dst_repo_id, + false, + state.owner_id, + ); + // Recalculate number of steps + a_task.step = 1; + a_task.steps = state.xfr.length * 4 + 2; + // Update task + g_db._update(a_task._id, { + step: a_task.step, + steps: a_task.steps, + state: { + xfr: state.xfr, + }, + ut: Math.floor(Date.now() / 1000), + }); + // Fall-through to initiate first transfer + }, + ["repo", "loc"], + ["task"], + ); } if (a_task.step > 0 && a_task.step < a_task.steps - 1) { @@ -683,31 +875,42 @@ var tasks_func = function() { switch (substep) { case 0: //console.log("taskRunRecAllocChg - init move"); - obj._transact(function() { - // Ensure allocation has sufficient record and data capacity - alloc = g_db.alloc.firstExample({ - _from: state.owner_id, - _to: state.dst_repo_id - }); - if (alloc.rec_count + xfr.files.length > alloc.rec_limit) - throw [g_lib.ERR_PERM_DENIED, "Allocation record count limit exceeded on " + state.dst_repo_id]; - if (alloc.data_size + xfr.size > alloc.data_limit) - throw [g_lib.ERR_PERM_DENIED, "Allocation data size limit exceeded on " + state.dst_repo_id]; - - // Init record move - obj.recMoveInit(xfr.files, state.dst_repo_id); - - // TEST ONLY - //throw [g_lib.ERR_INTERNAL_FAULT,"TEST ONLY ERROR"]; - - // Update task step - a_task.step += 1; - g_db._update(a_task._id, { - step: a_task.step, - ut: Math.floor(Date.now() / 1000) - }); - }, [], ["loc", "task"]); - /* falls through */ + obj._transact( + function () { + // Ensure allocation has sufficient record and data capacity + alloc = g_db.alloc.firstExample({ + _from: state.owner_id, + _to: state.dst_repo_id, + }); + if (alloc.rec_count + xfr.files.length > alloc.rec_limit) + throw [ + g_lib.ERR_PERM_DENIED, + "Allocation record count limit exceeded on " + + state.dst_repo_id, + ]; + if (alloc.data_size + xfr.size > alloc.data_limit) + throw [ + g_lib.ERR_PERM_DENIED, + "Allocation data size limit exceeded on " + state.dst_repo_id, + ]; + + // Init record move + obj.recMoveInit(xfr.files, state.dst_repo_id); + + // TEST ONLY + //throw [g_lib.ERR_INTERNAL_FAULT,"TEST ONLY ERROR"]; + + // Update task step + a_task.step += 1; + g_db._update(a_task._id, { + step: a_task.step, + ut: Math.floor(Date.now() / 1000), + }); + }, + [], + ["loc", "task"], + ); + /* falls through */ case 1: //console.log("taskRunRecAllocChg - do xfr"); // Transfer data step @@ -719,30 +922,33 @@ var tasks_func = function() { encrypt: state.encrypt, acc_tok: tokens.acc_tok, ref_tok: tokens.ref_tok, - acc_tok_exp_in: tokens.acc_tok_exp_in + acc_tok_exp_in: tokens.acc_tok_exp_in, }; params = Object.assign(params, xfr); reply = { cmd: g_lib.TC_RAW_DATA_TRANSFER, params: params, - step: a_task.step + step: a_task.step, }; break; case 2: //console.log("taskRunRecAllocChg - finalize move"); - obj._transact(function() { - // Init record move - obj.recMoveFini(xfr.files); - - // Update task step - a_task.step += 1; - g_db._update(a_task._id, { - step: a_task.step, - ut: Math.floor(Date.now() / 1000) - }); - - }, [], ["loc", "alloc", "task"]); - /* falls through */ + obj._transact( + function () { + // Init record move + obj.recMoveFini(xfr.files); + + // Update task step + a_task.step += 1; + g_db._update(a_task._id, { + step: a_task.step, + ut: Math.floor(Date.now() / 1000), + }); + }, + [], + ["loc", "alloc", "task"], + ); + /* falls through */ case 3: //console.log("taskRunRecAllocChg - delete old data"); // Request data size update @@ -758,19 +964,24 @@ var tasks_func = function() { reply = { cmd: g_lib.TC_RAW_DATA_DELETE, params: params, - step: a_task.step + step: a_task.step, }; break; } } else { //console.log("taskRunRecAllocChg - complete task"); - obj._transact(function() { - // Last step - complete task - reply = { - cmd: g_lib.TC_STOP, - params: obj.taskComplete(a_task._id, true) - }; - }, [], ["task"], ["lock", "block"]); + obj._transact( + function () { + // Last step - complete task + reply = { + cmd: g_lib.TC_STOP, + params: obj.taskComplete(a_task._id, true), + }; + }, + [], + ["task"], + ["lock", "block"], + ); } return reply; @@ -785,22 +996,33 @@ var tasks_func = function() { do not use allocations, so only ownership is updated. */ - obj.taskInitRecOwnerChg = function(a_client, a_res_ids, a_dst_coll_id, a_dst_repo_id, a_check) { + obj.taskInitRecOwnerChg = function ( + a_client, + a_res_ids, + a_dst_coll_id, + a_dst_repo_id, + a_check, + ) { // Verify destination collection if (!g_db.c.exists(a_dst_coll_id)) throw [g_lib.ERR_INVALID_PARAM, "No such collection '" + a_dst_coll_id + "'"]; var owner_id = g_db.owner.firstExample({ - _from: a_dst_coll_id + _from: a_dst_coll_id, })._to; if (owner_id != a_client._id) { - if ((owner_id.charAt(0) != 'p') || !g_lib.hasManagerPermProj(a_client, owner_id)) { + if (owner_id.charAt(0) != "p" || !g_lib.hasManagerPermProj(a_client, owner_id)) { var coll = g_db.c.document(a_dst_coll_id); if (!g_lib.hasPermissions(a_client, coll, g_lib.PERM_CREATE)) - throw [g_lib.ERR_PERM_DENIED, "Operation requires CREATE permission on destination collection '" + a_dst_coll_id + "'"]; + throw [ + g_lib.ERR_PERM_DENIED, + "Operation requires CREATE permission on destination collection '" + + a_dst_coll_id + + "'", + ]; } } @@ -808,9 +1030,11 @@ var tasks_func = function() { if (a_check) { // Get a list of available repos for client to pick from (there must be at least one) - allocs = g_db.alloc.byExample({ - _from: owner_id - }).toArray(); + allocs = g_db.alloc + .byExample({ + _from: owner_id, + }) + .toArray(); if (!allocs.length) throw [g_lib.ERR_PERM_DENIED, "No allocations available for '" + owner_id + "'"]; @@ -821,20 +1045,28 @@ var tasks_func = function() { throw [g_lib.ERR_INVALID_PARAM, "No such repo '" + a_dst_repo_id + "'"]; // Verify client/owner has an allocation - if (!g_db.alloc.firstExample({ + if ( + !g_db.alloc.firstExample({ _from: owner_id, - _to: a_dst_repo_id - })) + _to: a_dst_repo_id, + }) + ) throw [g_lib.ERR_INVALID_PARAM, "No allocation on '" + a_dst_repo_id + "'"]; } var result = g_proc.preprocessItems(a_client, owner_id, a_res_ids, g_lib.TT_REC_OWNER_CHG); if (result.has_pub) { - throw [g_lib.ERR_PERM_DENIED, "Owner change not allowed - selection contains public data."]; + throw [ + g_lib.ERR_PERM_DENIED, + "Owner change not allowed - selection contains public data.", + ]; } - var i, loc, rec, deps = []; + var i, + loc, + rec, + deps = []; result.tot_cnt = result.ext_data.length + result.glob_data.length; result.act_size = 0; @@ -844,7 +1076,7 @@ var tasks_func = function() { if (rec.owner != owner_id) { deps.push({ id: rec.id, - lev: 1 + lev: 1, }); } } @@ -852,12 +1084,12 @@ var tasks_func = function() { for (i in result.glob_data) { rec = result.glob_data[i]; loc = g_db.loc.firstExample({ - _from: rec.id + _from: rec.id, }); if (loc.uid != owner_id || loc._to != a_dst_repo_id) { deps.push({ id: rec.id, - lev: 1 + lev: 1, }); if (rec.size) { result.act_size += rec.size; @@ -877,22 +1109,21 @@ var tasks_func = function() { } // Stop if no record to process, or if this is just a check - if (deps.length === 0 || a_check) - return result; + if (deps.length === 0 || a_check) return result; // Add additional dependencies for locks deps.push({ id: a_dst_coll_id, - lev: 0 + lev: 0, }); deps.push({ id: owner_id, - lev: 0 + lev: 0, }); deps.push({ id: a_dst_repo_id, lev: 1, - ctx: owner_id + ctx: owner_id, }); var state = { @@ -901,16 +1132,20 @@ var tasks_func = function() { glob_data: result.glob_data, dst_coll_id: a_dst_coll_id, dst_repo_id: a_dst_repo_id, - owner_id: owner_id + owner_id: owner_id, }; var task = obj._createTask(a_client._id, g_lib.TT_REC_OWNER_CHG, 3, state); if (g_proc._lockDepsGeneral(task._id, deps)) { - task = g_db._update(task._id, { - status: g_lib.TS_BLOCKED, - msg: "Queued" - }, { - returnNew: true - }).new; + task = g_db._update( + task._id, + { + status: g_lib.TS_BLOCKED, + msg: "Queued", + }, + { + returnNew: true, + }, + ).new; } result.task = task; @@ -918,11 +1153,16 @@ var tasks_func = function() { return result; }; - obj.taskRunRecOwnerChg = function(a_task) { + obj.taskRunRecOwnerChg = function (a_task) { console.log("taskRunRecOwnerChg"); - var reply, state = a_task.state, - params, xfr, alloc, substep, xfrnum; + var reply, + state = a_task.state, + params, + xfr, + alloc, + substep, + xfrnum; // TODO Add rollback functionality if (a_task.step < 0) { @@ -937,17 +1177,21 @@ var tasks_func = function() { // Only action is to revert location in DB if transfer failed. if (substep > 0 && substep < 3) { - obj._transact(function() { - //console.log("taskRunRecOwnerChg - recMoveRevert" ); - obj.recMoveRevert(xfr.files); - - // Update task step - a_task.step -= substep; - g_db._update(a_task._id, { - step: a_task.step, - ut: Math.floor(Date.now() / 1000) - }); - }, [], ["loc", "task"]); + obj._transact( + function () { + //console.log("taskRunRecOwnerChg - recMoveRevert" ); + obj.recMoveRevert(xfr.files); + + // Update task step + a_task.step -= substep; + g_db._update(a_task._id, { + step: a_task.step, + ut: Math.floor(Date.now() / 1000), + }); + }, + [], + ["loc", "task"], + ); } } @@ -956,40 +1200,55 @@ var tasks_func = function() { if (a_task.step == 0) { //console.log("taskRunRecOwnerChg - do setup"); - obj._transact(function() { - // Generate transfer steps - state.xfr = obj._buildTransferDoc(g_lib.TT_REC_OWNER_CHG, state.glob_data, null, state.dst_repo_id, false, state.owner_id); - // Update step info - a_task.step = 1; - a_task.steps = (state.xfr.length * 4) + 3; - // Update task - g_db._update(a_task._id, { - step: a_task.step, - steps: a_task.steps, - state: { - xfr: state.xfr - }, - ut: Math.floor(Date.now() / 1000) - }); - // Fall-through to initiate first transfer - }, ["repo", "loc"], ["task"]); + obj._transact( + function () { + // Generate transfer steps + state.xfr = obj._buildTransferDoc( + g_lib.TT_REC_OWNER_CHG, + state.glob_data, + null, + state.dst_repo_id, + false, + state.owner_id, + ); + // Update step info + a_task.step = 1; + a_task.steps = state.xfr.length * 4 + 3; + // Update task + g_db._update(a_task._id, { + step: a_task.step, + steps: a_task.steps, + state: { + xfr: state.xfr, + }, + ut: Math.floor(Date.now() / 1000), + }); + // Fall-through to initiate first transfer + }, + ["repo", "loc"], + ["task"], + ); } if (a_task.step === 1) { //console.log("taskRunRecOwnerChg - move unmanaged records"); - obj._transact(function() { - if (state.ext_data.length) { - obj.recMoveExt(state.ext_data, state.owner_id, state.dst_coll_id); - } + obj._transact( + function () { + if (state.ext_data.length) { + obj.recMoveExt(state.ext_data, state.owner_id, state.dst_coll_id); + } - // Update task step - a_task.step = 2; - g_db._update(a_task._id, { - step: a_task.step, - ut: Math.floor(Date.now() / 1000) - }); - // Fall-through to next step - }, ["c"], ["loc", "alloc", "acl", "d", "owner", "item", "task", "a", "alias"]); + // Update task step + a_task.step = 2; + g_db._update(a_task._id, { + step: a_task.step, + ut: Math.floor(Date.now() / 1000), + }); + // Fall-through to next step + }, + ["c"], + ["loc", "alloc", "acl", "d", "owner", "item", "task", "a", "alias"], + ); } if (a_task.step > 1 && a_task.step < a_task.steps - 1) { @@ -1001,28 +1260,44 @@ var tasks_func = function() { switch (substep) { case 0: //console.log("taskRunRecOwnerChg - init move"); - obj._transact(function() { - // Ensure allocation has sufficient record and data capacity - alloc = g_db.alloc.firstExample({ - _from: state.owner_id, - _to: state.dst_repo_id - }); - if (alloc.rec_count + xfr.files.length > alloc.rec_limit) - throw [g_lib.ERR_PERM_DENIED, "Allocation record count limit exceeded on " + state.dst_repo_id]; - if (alloc.data_size + xfr.size > alloc.data_limit) - throw [g_lib.ERR_PERM_DENIED, "Allocation data size limit exceeded on " + state.dst_repo_id]; - - // Init record move - obj.recMoveInit(xfr.files, state.dst_repo_id, state.owner_id, state.dst_coll_id); - - // Update task step - a_task.step += 1; - g_db._update(a_task._id, { - step: a_task.step, - ut: Math.floor(Date.now() / 1000) - }); - }, [], ["loc", "task"]); - /* falls through */ + obj._transact( + function () { + // Ensure allocation has sufficient record and data capacity + alloc = g_db.alloc.firstExample({ + _from: state.owner_id, + _to: state.dst_repo_id, + }); + if (alloc.rec_count + xfr.files.length > alloc.rec_limit) + throw [ + g_lib.ERR_PERM_DENIED, + "Allocation record count limit exceeded on " + + state.dst_repo_id, + ]; + if (alloc.data_size + xfr.size > alloc.data_limit) + throw [ + g_lib.ERR_PERM_DENIED, + "Allocation data size limit exceeded on " + state.dst_repo_id, + ]; + + // Init record move + obj.recMoveInit( + xfr.files, + state.dst_repo_id, + state.owner_id, + state.dst_coll_id, + ); + + // Update task step + a_task.step += 1; + g_db._update(a_task._id, { + step: a_task.step, + ut: Math.floor(Date.now() / 1000), + }); + }, + [], + ["loc", "task"], + ); + /* falls through */ case 1: //console.log("taskRunRecOwnerChg - do xfr"); // Transfer data step @@ -1034,30 +1309,33 @@ var tasks_func = function() { encrypt: state.encrypt, acc_tok: tokens.acc_tok, ref_tok: tokens.ref_tok, - acc_tok_exp_in: tokens.acc_tok_exp_in + acc_tok_exp_in: tokens.acc_tok_exp_in, }; params = Object.assign(params, xfr); reply = { cmd: g_lib.TC_RAW_DATA_TRANSFER, params: params, - step: a_task.step + step: a_task.step, }; break; case 2: //console.log("taskRunRecOwnerChg - finalize move"); - obj._transact(function() { - // Init record move - obj.recMoveFini(xfr.files); - - // Update task step - a_task.step += 1; - g_db._update(a_task._id, { - step: a_task.step, - ut: Math.floor(Date.now() / 1000) - }); - - }, ["c"], ["loc", "alloc", "acl", "d", "owner", "item", "task", "a", "alias"]); - /* falls through */ + obj._transact( + function () { + // Init record move + obj.recMoveFini(xfr.files); + + // Update task step + a_task.step += 1; + g_db._update(a_task._id, { + step: a_task.step, + ut: Math.floor(Date.now() / 1000), + }); + }, + ["c"], + ["loc", "alloc", "acl", "d", "owner", "item", "task", "a", "alias"], + ); + /* falls through */ case 3: //console.log("taskRunRecOwnerChg - delete old data"); // Request data size update @@ -1073,25 +1351,30 @@ var tasks_func = function() { reply = { cmd: g_lib.TC_RAW_DATA_DELETE, params: params, - step: a_task.step + step: a_task.step, }; break; } } else { //console.log("taskRunRecOwnerChg - complete task"); - obj._transact(function() { - // Last step - complete task - reply = { - cmd: g_lib.TC_STOP, - params: obj.taskComplete(a_task._id, true) - }; - }, [], ["task"], ["lock", "block"]); + obj._transact( + function () { + // Last step - complete task + reply = { + cmd: g_lib.TC_STOP, + params: obj.taskComplete(a_task._id, true), + }; + }, + [], + ["task"], + ["lock", "block"], + ); } return reply; }; - obj.taskInitRecCollDelete = function(a_client, a_ids) { + obj.taskInitRecCollDelete = function (a_client, a_ids) { console.log("taskInitRecCollDelete start", Date.now()); var result = g_proc.preprocessItems(a_client, null, a_ids, g_lib.TT_REC_DEL); @@ -1100,7 +1383,8 @@ var tasks_func = function() { throw [g_lib.ERR_PERM_DENIED, "Deletion not allowed - selection contains public data."]; } - var i, rec_ids = []; + var i, + rec_ids = []; //console.log("Extern recs:", result.ext_data.length, ", Globus recs:", result.glob_data.length ); @@ -1108,8 +1392,7 @@ var tasks_func = function() { rec_ids.push(result.ext_data[i].id); } - for (i in result.glob_data) - rec_ids.push(result.glob_data[i].id); + for (i in result.glob_data) rec_ids.push(result.glob_data[i].id); obj._ensureExclusiveAccess(rec_ids); @@ -1126,7 +1409,7 @@ var tasks_func = function() { state.del_coll = result.coll; for (i in result.coll) { g_db.item.removeByExample({ - _to: result.coll[i] + _to: result.coll[i], }); } } @@ -1137,7 +1420,7 @@ var tasks_func = function() { for (i in result.ext_data) { state.del_rec.push(result.ext_data[i].id); g_db.item.removeByExample({ - _to: result.ext_data[i].id + _to: result.ext_data[i].id, }); } } @@ -1148,56 +1431,84 @@ var tasks_func = function() { for (i in result.glob_data) { state.del_rec.push(result.glob_data[i].id); g_db.item.removeByExample({ - _to: result.glob_data[i].id + _to: result.glob_data[i].id, }); } } else { state.del_data = []; } - result.task = obj._createTask(a_client._id, g_lib.TT_REC_DEL, state.del_data.length + 2, state); + result.task = obj._createTask( + a_client._id, + g_lib.TT_REC_DEL, + state.del_data.length + 2, + state, + ); //console.log("taskInitRecCollDelete finished",Date.now()); return result; }; - obj.taskRunRecCollDelete = function(a_task) { + obj.taskRunRecCollDelete = function (a_task) { console.log("taskRunRecCollDelete"); - var i, reply, state = a_task.state, + var i, + reply, + state = a_task.state, retry; // No rollback functionality - if (a_task.step < 0) - return; + if (a_task.step < 0) return; if (a_task.step == 0) { retry = 10; for (;;) { try { - obj._transact(function() { - //console.log("Del collections",Date.now()); + obj._transact( + function () { + //console.log("Del collections",Date.now()); - for (i in state.del_coll) { - // TODO Adjust for collection limit on allocation - obj._deleteCollection(state.del_coll[i]); - } + for (i in state.del_coll) { + // TODO Adjust for collection limit on allocation + obj._deleteCollection(state.del_coll[i]); + } - //console.log("Del records",Date.now()); + //console.log("Del records",Date.now()); - // Delete records with no data - if (state.del_rec.length) { - obj._deleteDataRecords(state.del_rec); - } + // Delete records with no data + if (state.del_rec.length) { + obj._deleteDataRecords(state.del_rec); + } - // Update task step - a_task.step += 1; - g_db._update(a_task._id, { - step: a_task.step, - ut: Math.floor(Date.now() / 1000) - }); - }, [], ["d", "c", "a", "alias", "owner", "item", "acl", "loc", "alloc", "t", "top", "dep", "n", "note", "task", "tag", "sch"]); + // Update task step + a_task.step += 1; + g_db._update(a_task._id, { + step: a_task.step, + ut: Math.floor(Date.now() / 1000), + }); + }, + [], + [ + "d", + "c", + "a", + "alias", + "owner", + "item", + "acl", + "loc", + "alloc", + "t", + "top", + "dep", + "n", + "note", + "task", + "tag", + "sch", + ], + ); break; } catch (e) { if (--retry == 0 || !e.errorNum || e.errorNum != 1200) { @@ -1213,17 +1524,22 @@ var tasks_func = function() { reply = { cmd: g_lib.TC_RAW_DATA_DELETE, params: state.del_data[a_task.step - 1], - step: a_task.step + step: a_task.step, }; } else { //console.log("taskRunRecCollDelete - complete task", Date.now() ); - obj._transact(function() { - // Last step - complete task - reply = { - cmd: g_lib.TC_STOP, - params: obj.taskComplete(a_task._id, true) - }; - }, [], ["task"], ["lock", "block"]); + obj._transact( + function () { + // Last step - complete task + reply = { + cmd: g_lib.TC_STOP, + params: obj.taskComplete(a_task._id, true), + }; + }, + [], + ["task"], + ["lock", "block"], + ); } return reply; @@ -1231,17 +1547,23 @@ var tasks_func = function() { // ----------------------- External Support Functions --------------------- - - /** @brief Delete projects and associated data + /** + * Deletes one or more projects and associated data. If a project has no allocations, it can + * be deleted immediately. If a project has allocations and raw data, a task must be initialized + * to delete the allocations. Deletion is exclusive—if any other tasks are using the project or + * associated data, the operation will be denied. + * + * @param {object} a_client - The client object that contains user details and permissions. + * @param {Array} a_proj_ids - An array of project IDs to be deleted. + * @returns {object} An object containing the task to delete the projects and allocations. + * @throws {Array} Throws an error array containing a code and message if the project does + * not exist or the client lacks permissions. * - * Delete one or more projects. If a project has no allocations, - * it can be deleted immediately. If a project has allocations and - * raw data, the project can be deleted, but a task must be initialized - * to delete the allocations. Deletion is an exclusive operation - if - * any other tasks are using the project or associated data, the delete - * operation will be denied. + * @example + * const result = obj.taskInitProjDelete(client, ['proj_id_1', 'proj_id_2']); + * console.log(result); */ - obj.taskInitProjDelete = function(a_client, a_proj_ids) { + obj.taskInitProjDelete = function (a_client, a_proj_ids) { var i, proj_id; // Verify existence and check permission @@ -1258,7 +1580,7 @@ var tasks_func = function() { var allocs, alloc, gr; var state = { proj_ids: [], - allocs: [] + allocs: [], }; // For each project, determine allocation/raw data status and take appropriate actions @@ -1268,27 +1590,27 @@ var tasks_func = function() { state.proj_ids.push(proj_id); allocs = g_db.alloc.byExample({ - _from: proj_id + _from: proj_id, }); while (allocs.hasNext()) { alloc = allocs.next(); state.allocs.push({ repo_id: alloc._to, - repo_path: alloc.path + repo_path: alloc.path, }); } // Remove owner, admins, members to prevent access g_db.owner.removeByExample({ - _from: proj_id + _from: proj_id, }); g_db.admin.removeByExample({ - _from: proj_id + _from: proj_id, }); gr = g_db.g.byExample({ uid: proj_id, - gid: "members" + gid: "members", }); if (gr.hasNext()) { g_graph.g.remove(gr.next()._id); @@ -1296,16 +1618,17 @@ var tasks_func = function() { } var result = { - task: obj._createTask(a_client._id, g_lib.TT_PROJ_DEL, state.allocs.length + 2, state) + task: obj._createTask(a_client._id, g_lib.TT_PROJ_DEL, state.allocs.length + 2, state), }; return result; }; - obj.taskRunProjDelete = function(a_task) { + obj.taskRunProjDelete = function (a_task) { console.log("taskRunProjDelete"); - var reply, state = a_task.state; + var reply, + state = a_task.state; // No rollback functionality if (a_task.step < 0) { @@ -1313,20 +1636,44 @@ var tasks_func = function() { } if (a_task.step == 0) { - obj._transact(function() { - //console.log("Del projects",Date.now()); + obj._transact( + function () { + //console.log("Del projects",Date.now()); - for (var i in state.proj_ids) { - obj._projectDelete(state.proj_ids[i]); - } + for (var i in state.proj_ids) { + obj._projectDelete(state.proj_ids[i]); + } - // Update task step - a_task.step += 1; - g_db._update(a_task._id, { - step: a_task.step, - ut: Math.floor(Date.now() / 1000) - }); - }, [], ["d", "c", "p", "a", "g", "alias", "owner", "item", "acl", "loc", "alloc", "t", "top", "dep", "n", "note", "task", "tag", "sch"]); + // Update task step + a_task.step += 1; + g_db._update(a_task._id, { + step: a_task.step, + ut: Math.floor(Date.now() / 1000), + }); + }, + [], + [ + "d", + "c", + "p", + "a", + "g", + "alias", + "owner", + "item", + "acl", + "loc", + "alloc", + "t", + "top", + "dep", + "n", + "note", + "task", + "tag", + "sch", + ], + ); // Continue to next step } @@ -1336,16 +1683,21 @@ var tasks_func = function() { reply = { cmd: g_lib.TC_ALLOC_DELETE, params: state.allocs[a_task.step - 1], - step: a_task.step + step: a_task.step, }; } else { // Complete task - obj._transact(function() { - reply = { - cmd: g_lib.TC_STOP, - params: obj.taskComplete(a_task._id, true) - }; - }, [], ["task"], ["lock", "block"]); + obj._transact( + function () { + reply = { + cmd: g_lib.TC_STOP, + params: obj.taskComplete(a_task._id, true), + }; + }, + [], + ["task"], + ["lock", "block"], + ); } return reply; @@ -1353,7 +1705,7 @@ var tasks_func = function() { // ----------------------- External Support Functions --------------------- - obj.taskGetRunFunc = function(a_task) { + obj.taskGetRunFunc = function (a_task) { switch (a_task.type) { case g_lib.TT_DATA_GET: return obj.taskRunDataGet; @@ -1382,22 +1734,28 @@ var tasks_func = function() { // ----------------------- Internal Support Functions --------------------- - obj.taskReady = function(a_task_id) { - g_db._update(a_task_id, { - status: g_lib.TS_RUNNING, - msg: "Running", - ut: Math.floor(Date.now() / 1000) - }, { - returnNew: true, - waitForSync: true - }); + obj.taskReady = function (a_task_id) { + g_db._update( + a_task_id, + { + status: g_lib.TS_RUNNING, + msg: "Running", + ut: Math.floor(Date.now() / 1000), + }, + { + returnNew: true, + waitForSync: true, + }, + ); }; - obj.taskComplete = function(a_task_id, a_success, a_msg) { + obj.taskComplete = function (a_task_id, a_success, a_msg) { console.log("taskComplete 1"); var ready_tasks = [], - dep, dep_blocks, blocks = g_db.block.byExample({ - _to: a_task_id + dep, + dep_blocks, + blocks = g_db.block.byExample({ + _to: a_task_id, }); var time = Math.floor(Date.now() / 1000); @@ -1405,21 +1763,27 @@ var tasks_func = function() { while (blocks.hasNext()) { dep = blocks.next()._from; - dep_blocks = g_db.block.byExample({ - _from: dep - }).toArray(); + dep_blocks = g_db.block + .byExample({ + _from: dep, + }) + .toArray(); // If blocked task has only one block, then it's this task being finalized and will be able to run now if (dep_blocks.length === 1) { ready_tasks.push(dep); //console.log("taskComplete - task", dep, "ready"); - g_db.task.update(dep, { - status: g_lib.TS_READY, - msg: "Pending", - ut: time - }, { - returnNew: true, - waitForSync: true - }); + g_db.task.update( + dep, + { + status: g_lib.TS_READY, + msg: "Pending", + ut: time, + }, + { + returnNew: true, + waitForSync: true, + }, + ); } } console.log("taskComplete 3"); @@ -1428,23 +1792,23 @@ var tasks_func = function() { if (a_success) { doc = { status: g_lib.TS_SUCCEEDED, - msg: "Finished" + msg: "Finished", }; } else { doc = { status: g_lib.TS_FAILED, - msg: a_msg ? a_msg : "Failed (unknown reason)" + msg: a_msg ? a_msg : "Failed (unknown reason)", }; } doc.ut = time; - console.log("taskComplete 4", doc ); + console.log("taskComplete 4", doc); g_db.block.removeByExample({ - _to: a_task_id + _to: a_task_id, }); g_db.lock.removeByExample({ - _from: a_task_id + _from: a_task_id, }); console.log("taskComplete 5"); var delay = 1; @@ -1454,8 +1818,7 @@ var tasks_func = function() { break; } catch (e) { if (e.errorNum === 1200) { - if (delay > 64) - throw e; + if (delay > 64) throw e; //console.log("retry sleep"); g_internal.sleep(0.2 * delay); @@ -1472,20 +1835,20 @@ var tasks_func = function() { return ready_tasks; }; - obj._transact = function(a_func, a_rdc = [], a_wrc = [], a_exc = []) { + obj._transact = function (a_func, a_rdc = [], a_wrc = [], a_exc = []) { g_db._executeTransaction({ collections: { read: a_rdc, write: a_wrc, - exclusive: a_exc + exclusive: a_exc, }, lockTimeout: 0, waitForSync: true, - action: a_func + action: a_func, }); }; - obj._createTask = function(a_client_id, a_type, a_steps, a_state) { + obj._createTask = function (a_client_id, a_type, a_steps, a_state) { var time = Math.floor(Date.now() / 1000); var obj = { type: a_type, @@ -1496,15 +1859,22 @@ var tasks_func = function() { client: a_client_id, step: 0, steps: a_steps, - state: a_state + state: a_state, }; var task = g_db.task.save(obj, { - returnNew: true + returnNew: true, }); return task.new; }; - obj._buildTransferDoc = function(a_mode, a_data, a_ext_data, a_remote, a_orig_fname, a_dst_owner) { + obj._buildTransferDoc = function ( + a_mode, + a_data, + a_ext_data, + a_remote, + a_orig_fname, + a_dst_owner, + ) { /* Output per mode: GET: src_repo_xx - DataFed storage location @@ -1531,7 +1901,15 @@ var tasks_func = function() { console.log("_buildTransferDoc", a_mode, a_remote, a_orig_fname); - var fnames, i, idx, file, rem_ep, rem_fname, rem_path, xfr, repo_map = {}, + var fnames, + i, + idx, + file, + rem_ep, + rem_fname, + rem_path, + xfr, + repo_map = {}, src; if (a_mode == g_lib.TT_DATA_GET || a_mode == g_lib.TT_DATA_PUT) { @@ -1548,8 +1926,7 @@ var tasks_func = function() { //console.log("rem path:",rem_path); if (a_mode == g_lib.TT_DATA_GET) { - if (rem_path.charAt(rem_path.length - 1) != "/") - rem_path += "/"; + if (rem_path.charAt(rem_path.length - 1) != "/") rem_path += "/"; } else if (a_mode == g_lib.TT_DATA_PUT) { idx = rem_path.lastIndexOf("/", rem_path.length - 1); //console.log("new idx:",idx); @@ -1564,7 +1941,11 @@ var tasks_func = function() { var repo = g_db.repo.document(a_remote); rem_ep = repo.endpoint; - rem_path = repo.path + (a_dst_owner.charAt(0) == "u" ? "user/" : "project/") + a_dst_owner.substr(2) + "/"; + rem_path = + repo.path + + (a_dst_owner.charAt(0) == "u" ? "user/" : "project/") + + a_dst_owner.substr(2) + + "/"; } if (a_mode == g_lib.TT_DATA_GET) { @@ -1572,9 +1953,13 @@ var tasks_func = function() { } if (a_data.length) { - var loc, locs = g_db._query("for i in @data for v,e in 1..1 outbound i loc return { d_id: i._id, d_sz: i.size, d_ext: i.ext, d_src: i.source, r_id: v._id, r_ep: v.endpoint, r_path: v.path, uid: e.uid }", { - data: a_data - }); + var loc, + locs = g_db._query( + "for i in @data for v,e in 1..1 outbound i loc return { d_id: i._id, d_sz: i.size, d_ext: i.ext, d_src: i.source, r_id: v._id, r_ep: v.endpoint, r_path: v.path, uid: e.uid }", + { + data: a_data, + }, + ); //console.log("locs hasNext",locs.hasNext()); @@ -1584,7 +1969,7 @@ var tasks_func = function() { file = { id: loc.d_id, - size: loc.d_sz + size: loc.d_sz, }; switch (a_mode) { @@ -1593,7 +1978,10 @@ var tasks_func = function() { if (a_orig_fname) { file.to = loc.d_src.substr(loc.d_src.lastIndexOf("/") + 1); if (fnames.has(file.to)) { - throw [g_lib.ERR_XFR_CONFLICT, "Duplicate filename(s) detected in transfer request."]; + throw [ + g_lib.ERR_XFR_CONFLICT, + "Duplicate filename(s) detected in transfer request.", + ]; } fnames.add(file.to); @@ -1630,8 +2018,12 @@ var tasks_func = function() { repo_map[loc.r_id] = { repo_id: loc.r_id, repo_ep: loc.r_ep, - repo_path: loc.r_path + (loc.uid.charAt(0) == "u" ? "user/" : "project/") + loc.uid.substr(2) + "/", - files: [file] + repo_path: + loc.r_path + + (loc.uid.charAt(0) == "u" ? "user/" : "project/") + + loc.uid.substr(2) + + "/", + files: [file], }; } } @@ -1647,7 +2039,7 @@ var tasks_func = function() { edat = a_ext_data[i]; file = { id: edat.id, - size: edat.size + size: edat.size, }; idx = edat.source.indexOf("/"); @@ -1660,11 +2052,17 @@ var tasks_func = function() { if (a_orig_fname) { idx = src.lastIndexOf("/"); if (idx < 0) { - throw [g_lib.ERR_INVALID_PARAM, "Invalid external source path: " + edat.source]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Invalid external source path: " + edat.source, + ]; } file.to = src.substr(idx + 1); if (fnames.has(file.to)) { - throw [g_lib.ERR_XFR_CONFLICT, "Duplicate filename(s) detected in transfer request."]; + throw [ + g_lib.ERR_XFR_CONFLICT, + "Duplicate filename(s) detected in transfer request.", + ]; } } else { file.to = file.id.substr(2); @@ -1675,7 +2073,7 @@ var tasks_func = function() { } else { repo_map[ep] = { repo_id: 0, // ID 0 indicates external endpoint - files: [file] + files: [file], }; } } @@ -1683,7 +2081,8 @@ var tasks_func = function() { //console.log("repo map len",Object.keys(repo_map).length); - var rm, xfr_docs = []; + var rm, + xfr_docs = []; if (a_mode == g_lib.TT_REC_ALLOC_CHG || a_mode == g_lib.TT_REC_OWNER_CHG) { var j, k, chunks, chunk_sz, files, sz; @@ -1694,7 +2093,7 @@ var tasks_func = function() { // Pack roughly equal transfer sizes into each transfer chunk/step // Sort files from largest to smallest - rm.files.sort(function(a, b) { + rm.files.sort(function (a, b) { return b.size - a.size; }); @@ -1721,7 +2120,7 @@ var tasks_func = function() { files = [file]; //console.log("rec",file.id,"first in xfr, sz:",file.size); - for (k = j + 1; k < rm.files.length;) { + for (k = j + 1; k < rm.files.length; ) { file = rm.files[k]; if (sz + file.size <= g_lib.GLOB_MAX_XFR_SIZE) { //console.log("rec",file.id,"added to xfr, sz:",file.size); @@ -1739,7 +2138,6 @@ var tasks_func = function() { } for (j in chunks) { - xfr = { src_repo_id: rm.repo_id, src_repo_ep: rm.repo_ep, @@ -1747,7 +2145,7 @@ var tasks_func = function() { dst_repo_id: a_remote, dst_repo_ep: rem_ep, dst_repo_path: rem_path, - size: chunk_sz[j] + size: chunk_sz[j], }; xfr.files = chunks[j]; @@ -1765,7 +2163,7 @@ var tasks_func = function() { src_repo_ep: i, src_repo_path: "", dst_repo_ep: rem_ep, - dst_repo_path: rem_path + dst_repo_path: rem_path, }; } else { xfr = { @@ -1773,7 +2171,7 @@ var tasks_func = function() { src_repo_ep: rm.repo_ep, src_repo_path: rm.repo_path, dst_repo_ep: rem_ep, - dst_repo_path: rem_path + dst_repo_path: rem_path, }; } } else { @@ -1782,7 +2180,7 @@ var tasks_func = function() { src_repo_path: rem_path, dst_repo_id: rm.repo_id, dst_repo_ep: rm.repo_ep, - dst_repo_path: rm.repo_path + dst_repo_path: rm.repo_path, }; } @@ -1794,14 +2192,18 @@ var tasks_func = function() { return xfr_docs; }; - - obj._buildDeleteDoc = function(a_data) { - var loc, locs, doc = [], + obj._buildDeleteDoc = function (a_data) { + var loc, + locs, + doc = [], repo_map = {}; - locs = g_db._query("for i in @data for v,e in 1..1 outbound i loc return { d_id: i._id, r_id: v._id, r_path: v.path, uid: e.uid }", { - data: a_data - }); + locs = g_db._query( + "for i in @data for v,e in 1..1 outbound i loc return { d_id: i._id, r_id: v._id, r_path: v.path, uid: e.uid }", + { + data: a_data, + }, + ); //console.log("locs hasNext",locs.hasNext()); @@ -1815,8 +2217,12 @@ var tasks_func = function() { } else { repo_map[loc.r_id] = { repo_id: loc.r_id, - repo_path: loc.r_path + (loc.uid.charAt(0) == "u" ? "user/" : "project/") + loc.uid.substr(2) + "/", - ids: [loc.d_id] + repo_path: + loc.r_path + + (loc.uid.charAt(0) == "u" ? "user/" : "project/") + + loc.uid.substr(2) + + "/", + ids: [loc.d_id], }; } } @@ -1828,16 +2234,21 @@ var tasks_func = function() { return doc; }; - /** @brief Deletes a collection record + /** + * Deletes a collection record. This function should not be called directly and is used + * only by task or process code. The function does not recursively delete contained items. * - * NOTE: DO NOT CALL THIS DIRECTLY - USED ONLY BY TASK/PROCESS CODE + * @param {string} a_id - The ID of the collection to delete. + * @throws {Error} Throws an error if the collection or associated graph objects cannot be deleted. * - * Does not recursively delete contained items. + * This function will delete aliases, notes, topics, and tags associated with the collection, + * but it will not recursively delete contained items. + * Use this function only within tasks or process code. */ - obj._deleteCollection = function(a_id) { + obj._deleteCollection = function (a_id) { // Delete alias var tmp = g_db.alias.firstExample({ - _from: a_id + _from: a_id, }); if (tmp) { g_graph.a.remove(tmp._to); @@ -1845,7 +2256,7 @@ var tasks_func = function() { // Delete notes tmp = g_db.note.byExample({ - _from: a_id + _from: a_id, }); while (tmp.hasNext()) { g_graph.n.remove(tmp.next()._to); @@ -1853,33 +2264,35 @@ var tasks_func = function() { // Unlink/delete topic tmp = g_db.top.firstExample({ - _from: a_id + _from: a_id, }); - if (tmp) - g_lib.topicUnlink(a_id); + if (tmp) g_lib.topicUnlink(a_id); // Remove tags var doc = g_db.c.document(a_id); - if (doc.tags && doc.tags.length) - g_lib.removeTags(doc.tags); + if (doc.tags && doc.tags.length) g_lib.removeTags(doc.tags); // Delete collection g_graph.c.remove(a_id); }; - - /** @brief Deletes data records + /** + * Deletes a data record and its associated graph objects. This function does not delete raw + * data but adjusts the allocation accordingly. + * + * @param {string} a_id - The ID of the data record to delete. + * @throws {Error} Throws an error if the data record or associated graph objects cannot be deleted. * - * Deletes record and associated graph objects. Does not delete raw data - * but does adjust allocation. + * This function will delete aliases, notes, tags, and update schema counts and allocations. + * It will not delete raw data, but it will adjust the allocation associated with the data record. */ - obj._deleteDataRecord = function(a_id) { + obj._deleteDataRecord = function (a_id) { //console.log( "delete rec", a_id ); var doc = g_db.d.document(a_id); // Delete alias var tmp = g_db.alias.firstExample({ - _from: a_id + _from: a_id, }); if (tmp) { g_graph.a.remove(tmp._to); @@ -1887,37 +2300,36 @@ var tasks_func = function() { // Delete notes and all inherted notes tmp = g_db.note.byExample({ - _from: a_id + _from: a_id, }); while (tmp.hasNext()) { g_lib.annotationDelete(tmp.next()._to); } // Remove tags - if (doc.tags && doc.tags.length) - g_lib.removeTags(doc.tags); + if (doc.tags && doc.tags.length) g_lib.removeTags(doc.tags); // Update schema count if (doc.sch_id && g_db.sch.exists(doc.sch_id)) { var sch = g_db.sch.document(doc.sch_id); g_db._update(sch._id, { - cnt: sch.cnt - 1 + cnt: sch.cnt - 1, }); } // Update allocation var loc = g_db.loc.firstExample({ - _from: a_id + _from: a_id, }); if (loc) { var alloc = g_db.alloc.firstExample({ _from: doc.owner, - _to: loc._to + _to: loc._to, }); if (alloc) { g_db.alloc.update(alloc._id, { data_size: alloc.data_size - doc.size, - rec_count: alloc.rec_count - 1 + rec_count: alloc.rec_count - 1, }); } } @@ -1926,10 +2338,16 @@ var tasks_func = function() { g_graph.d.remove(a_id); }; - - obj._deleteDataRecords = function(a_ids) { + obj._deleteDataRecords = function (a_ids) { //console.log( "deleting records", Date.now() ); - var i, j, id, doc, tmp, loc, alloc, allocs = {}; + var i, + j, + id, + doc, + tmp, + loc, + alloc, + allocs = {}; for (i in a_ids) { id = a_ids[i]; @@ -1937,7 +2355,7 @@ var tasks_func = function() { // Delete alias tmp = g_db.alias.firstExample({ - _from: id + _from: id, }); if (tmp) { g_graph.a.remove(tmp._to); @@ -1945,7 +2363,7 @@ var tasks_func = function() { // Delete notes and all inherted notes tmp = g_db.note.byExample({ - _from: id + _from: id, }); while (tmp.hasNext()) { g_lib.annotationDelete(tmp.next()._to); @@ -1960,13 +2378,13 @@ var tasks_func = function() { if (doc.sch_id && g_db.sch.exists(doc.sch_id)) { var sch = g_db.sch.document(doc.sch_id); g_db._update(sch._id, { - cnt: sch.cnt - 1 + cnt: sch.cnt - 1, }); } // Update allocation loc = g_db.loc.firstExample({ - _from: id + _from: id, }); if (loc) { if (!(doc.owner in allocs)) { @@ -1978,7 +2396,7 @@ var tasks_func = function() { if (!tmp) { allocs[doc.owner][loc._to] = { ct: 1, - sz: doc.size + sz: doc.size, }; } else { tmp.ct++; @@ -1998,13 +2416,13 @@ var tasks_func = function() { for (j in tmp) { alloc = g_db.alloc.firstExample({ _from: i, - _to: j + _to: j, }); if (alloc) { doc = tmp[j]; g_db.alloc.update(alloc._id, { data_size: alloc.data_size - doc.sz, - rec_count: alloc.rec_count - doc.ct + rec_count: alloc.rec_count - doc.ct, }); } } @@ -2013,24 +2431,35 @@ var tasks_func = function() { //console.log( "deleting records finished", Date.now() ); }; - - /** @brief Deletes project immediately + /** + * Deletes a project and all associated graph objects immediately. + * + * This function deletes allocations, owned records (e.g., data, collections, groups), + * and the project itself. It performs a direct deletion of the project and its related + * items, and should **NOT** be used on projects containing raw data. * - * Deletes projects and associated graph objects. + * @param {string} a_proj_id - The ID of the project to delete. + * @throws {Error} Throws an error if the project or associated items cannot be deleted. * - * DO NOT USE ON PROJECTS WITH RAW DATA!!!! + * Use this function with caution, as it will permanently delete allocations, data, + * collections, groups, and the project. It should not be used for projects that + * contain raw data. */ - obj._projectDelete = function(a_proj_id) { + obj._projectDelete = function (a_proj_id) { console.log("_projectDelete", a_proj_id); // Delete allocations g_db.alloc.removeByExample({ - _from: a_proj_id + _from: a_proj_id, }); // Delete all owned records (data, collections, groups, etc.) - var id, rec_ids = g_db._query("for v in 1..1 inbound @proj owner filter !is_same_collection('a',v) return v._id", { - proj: a_proj_id - }); + var id, + rec_ids = g_db._query( + "for v in 1..1 inbound @proj owner filter !is_same_collection('a',v) return v._id", + { + proj: a_proj_id, + }, + ); while (rec_ids.hasNext()) { id = rec_ids.next(); @@ -2050,29 +2479,26 @@ var tasks_func = function() { g_graph.p.remove(a_proj_id); }; - - obj.recMoveInit = function(a_data, a_new_repo_id, a_new_owner_id, a_new_coll_id) { + obj.recMoveInit = function (a_data, a_new_repo_id, a_new_owner_id, a_new_coll_id) { var loc; //console.log("recMoveInit", a_new_repo_id, a_new_owner_id, a_new_coll_id ); for (var i in a_data) { loc = g_db.loc.firstExample({ - _from: a_data[i].id + _from: a_data[i].id, }); var obj = {}; // Skip records that are already on new allocation - if (!a_new_owner_id && loc._to == a_new_repo_id) - continue; + if (!a_new_owner_id && loc._to == a_new_repo_id) continue; obj.new_repo = a_new_repo_id; if (a_new_owner_id) { // Skip records that are have already been move to new owner - if (loc.uid == a_new_owner_id) - continue; + if (loc.uid == a_new_owner_id) continue; obj.new_owner = a_new_owner_id; obj.new_coll = a_new_coll_id; @@ -2082,8 +2508,7 @@ var tasks_func = function() { } }; - - obj.recMoveRevert = function(a_data) { + obj.recMoveRevert = function (a_data) { var id, loc; for (var i in a_data) { @@ -2091,20 +2516,23 @@ var tasks_func = function() { //console.log("recMoveRevert", id ); loc = g_db.loc.firstExample({ - _from: id - }); - g_db._update(loc._id, { - new_repo: null, - new_owner: null, - new_coll: null - }, { - keepNull: false + _from: id, }); + g_db._update( + loc._id, + { + new_repo: null, + new_owner: null, + new_coll: null, + }, + { + keepNull: false, + }, + ); } }; - - obj.recMoveFini = function(a_data) { + obj.recMoveFini = function (a_data) { var data, loc, new_loc, alloc, coll, alias, alias_pref, a, key; //console.log("recMoveFini" ); @@ -2113,13 +2541,12 @@ var tasks_func = function() { data = a_data[i]; loc = g_db.loc.firstExample({ - _from: data.id + _from: data.id, }); //console.log("recMoveFini, id:", data.id, "loc:", loc ); - if (!loc.new_owner && !loc.new_repo) - continue; + if (!loc.new_owner && !loc.new_repo) continue; if (loc.new_owner) { // Changing owner and repo @@ -2130,47 +2557,64 @@ var tasks_func = function() { // DEV-ONLY SANITY CHECKS: if (!loc.new_coll) - throw [g_lib.ERR_INTERNAL_FAULT, "Record '" + data.id + "' missing destination collection!"]; + throw [ + g_lib.ERR_INTERNAL_FAULT, + "Record '" + data.id + "' missing destination collection!", + ]; if (!g_db.c.exists(loc.new_coll)) - throw [g_lib.ERR_INTERNAL_FAULT, "Record '" + data.id + "' destination collection '" + loc.new_coll + "' does not exist!"]; + throw [ + g_lib.ERR_INTERNAL_FAULT, + "Record '" + + data.id + + "' destination collection '" + + loc.new_coll + + "' does not exist!", + ]; coll = g_db.c.document(loc.new_coll); if (coll.owner != loc.new_owner) - throw [g_lib.ERR_INTERNAL_FAULT, "Record '" + data.id + "' destination collection '" + loc.new_coll + "' not owner by new owner!"]; + throw [ + g_lib.ERR_INTERNAL_FAULT, + "Record '" + + data.id + + "' destination collection '" + + loc.new_coll + + "' not owner by new owner!", + ]; // Clear all record ACLs g_db.acl.removeByExample({ - _from: data.id + _from: data.id, }); // Update record to new owner g_db._update(data.id, { - owner: loc.new_owner + owner: loc.new_owner, }); // Move ownership edge g_db.owner.removeByExample({ - _from: data.id + _from: data.id, }); g_db.owner.save({ _from: data.id, - _to: loc.new_owner + _to: loc.new_owner, }); // Move to new collection g_db.item.removeByExample({ - _to: data.id + _to: data.id, }); g_db.item.save({ _from: loc.new_coll, - _to: data.id + _to: data.id, }); // Move owner edge of alias if alias present alias = g_db.alias.firstExample({ - _from: data.id + _from: data.id, }); if (alias) { // remove old alias and all edges @@ -2178,14 +2622,16 @@ var tasks_func = function() { // Create new alias (add suffix if collides with existing alias) alias = alias_pref + alias._to.substr(alias._to.lastIndexOf(":") + 1); - for (a = 0;; a++) { + for (a = 0; ; a++) { key = alias + (a > 0 ? "-" + a : ""); - if (!g_db.a.exists({ - _key: key - })) { + if ( + !g_db.a.exists({ + _key: key, + }) + ) { //console.log("try alias:",key); g_db.a.save({ - _key: key + _key: key, }); break; } @@ -2193,17 +2639,17 @@ var tasks_func = function() { // If alias suffix, update record if (a > 0) { g_db.d.update(data.id, { - alias: key + alias: key, }); } g_db.alias.save({ _from: data.id, - _to: "a/" + key + _to: "a/" + key, }); g_db.owner.save({ _from: "a/" + key, - _to: loc.new_owner + _to: loc.new_owner, }); } } @@ -2213,17 +2659,20 @@ var tasks_func = function() { // Update old allocation stats alloc = g_db.alloc.firstExample({ _from: loc.uid, - _to: loc._to + _to: loc._to, }); if (!alloc) - throw [g_lib.ERR_INTERNAL_FAULT, "Record '" + data.id + "' has mismatched allocation/location (cur)!"]; + throw [ + g_lib.ERR_INTERNAL_FAULT, + "Record '" + data.id + "' has mismatched allocation/location (cur)!", + ]; //console.log("alloc:", alloc ); //console.log("recMoveFini, adj src alloc to:", alloc.rec_count - 1, alloc.data_size - data.size ); g_db._update(alloc._id, { rec_count: alloc.rec_count - 1, - data_size: alloc.data_size - data.size + data_size: alloc.data_size - data.size, }); //console.log("update alloc:", alloc ); @@ -2231,75 +2680,87 @@ var tasks_func = function() { // Update new allocation stats alloc = g_db.alloc.firstExample({ _from: loc.new_owner ? loc.new_owner : loc.uid, - _to: loc.new_repo + _to: loc.new_repo, }); if (!alloc) - throw [g_lib.ERR_INTERNAL_FAULT, "Record '" + data.id + "' has mismatched allocation/location (new)!"]; + throw [ + g_lib.ERR_INTERNAL_FAULT, + "Record '" + data.id + "' has mismatched allocation/location (new)!", + ]; //console.log("recMoveFini, adj dest alloc to:", alloc.rec_count + 1, alloc.data_size + data.size ); g_db._update(alloc._id, { rec_count: alloc.rec_count + 1, - data_size: alloc.data_size + data.size + data_size: alloc.data_size + data.size, }); // Create new edge to new owner/repo, delete old new_loc = { _from: loc._from, _to: loc.new_repo, - uid: loc.new_owner ? loc.new_owner : loc.uid + uid: loc.new_owner ? loc.new_owner : loc.uid, }; g_db.loc.save(new_loc); g_db.loc.remove(loc); } }; - obj.recMoveExt = function(a_data, a_dst_owner_id, a_dst_coll_id) { + obj.recMoveExt = function (a_data, a_dst_owner_id, a_dst_coll_id) { if (!g_db.c.exists(a_dst_coll_id)) { - throw [g_lib.ERR_INTERNAL_FAULT, "Destination collection '" + a_dst_coll_id + "' does not exist!"]; + throw [ + g_lib.ERR_INTERNAL_FAULT, + "Destination collection '" + a_dst_coll_id + "' does not exist!", + ]; } - var data, alias, a, key, + var data, + alias, + a, + key, alias_pref = a_dst_owner_id.charAt(0) + ":" + a_dst_owner_id.substr(2) + ":", coll = g_db.c.document(a_dst_coll_id); if (coll.owner != a_dst_owner_id) - throw [g_lib.ERR_INTERNAL_FAULT, "Destination collection '" + a_dst_coll_id + "' not owned by new owner!"]; + throw [ + g_lib.ERR_INTERNAL_FAULT, + "Destination collection '" + a_dst_coll_id + "' not owned by new owner!", + ]; for (var i in a_data) { data = a_data[i]; // Clear all record ACLs g_db.acl.removeByExample({ - _from: data.id + _from: data.id, }); // Update record to new owner g_db._update(data.id, { - owner: a_dst_owner_id + owner: a_dst_owner_id, }); // Move ownership edge g_db.owner.removeByExample({ - _from: data.id + _from: data.id, }); g_db.owner.save({ _from: data.id, - _to: a_dst_owner_id + _to: a_dst_owner_id, }); // Move to new collection g_db.item.removeByExample({ - _to: data.id + _to: data.id, }); g_db.item.save({ _from: a_dst_coll_id, - _to: data.id + _to: data.id, }); // Move owner edge of alias if alias present alias = g_db.alias.firstExample({ - _from: data.id + _from: data.id, }); if (alias) { // remove old alias and all edges @@ -2307,14 +2768,16 @@ var tasks_func = function() { // Create new alias (add suffix if collides with existing alias) alias = alias_pref + alias._to.substr(alias._to.lastIndexOf(":") + 1); - for (a = 0;; a++) { + for (a = 0; ; a++) { key = alias + (a > 0 ? "-" + a : ""); - if (!g_db.a.exists({ - _key: key - })) { + if ( + !g_db.a.exists({ + _key: key, + }) + ) { //console.log("try alias:",key); g_db.a.save({ - _key: key + _key: key, }); break; } @@ -2322,30 +2785,30 @@ var tasks_func = function() { // If alias suffix, update record if (a > 0) { g_db.d.update(data.id, { - alias: key + alias: key, }); } g_db.alias.save({ _from: data.id, - _to: "a/" + key + _to: "a/" + key, }); g_db.owner.save({ _from: "a/" + key, - _to: a_dst_owner_id + _to: a_dst_owner_id, }); } } }; - obj._ensureExclusiveAccess = function(a_ids) { + obj._ensureExclusiveAccess = function (a_ids) { //console.log("_ensureExclusiveAccess start", Date.now()); var i, id, lock; for (i in a_ids) { id = a_ids[i]; //console.log("_ensureExclusiveAccess",id); lock = g_db.lock.firstExample({ - _to: id + _to: id, }); if (lock) throw [g_lib.ERR_PERM_DENIED, "Operation not permitted - '" + id + "' in use."]; @@ -2354,6 +2817,6 @@ var tasks_func = function() { }; return obj; -}(); +})(); module.exports = tasks_func; diff --git a/core/database/foxx/api/topic_router.js b/core/database/foxx/api/topic_router.js index 3daa1ea38..ceca18a07 100644 --- a/core/database/foxx/api/topic_router.js +++ b/core/database/foxx/api/topic_router.js @@ -1,48 +1,59 @@ -'use strict'; +"use strict"; -const createRouter = require('@arangodb/foxx/router'); +const createRouter = require("@arangodb/foxx/router"); const router = createRouter(); -const joi = require('joi'); +const joi = require("joi"); -const g_db = require('@arangodb').db; -const g_lib = require('./support'); +const g_db = require("@arangodb").db; +const g_lib = require("./support"); module.exports = router; - //==================== TOPIC API FUNCTIONS -router.get('/list/topics', function(req, res) { +router + .get("/list/topics", function (req, res) { try { - var qry, par = {}, - result, off = 0, + var qry, + par = {}, + result, + off = 0, cnt = 50; - if (req.queryParams.offset != undefined) - off = req.queryParams.offset; + if (req.queryParams.offset != undefined) off = req.queryParams.offset; if (req.queryParams.count != undefined && req.queryParams.count <= 100) cnt = req.queryParams.count; if (req.queryParams.id) { - qry = "for i in 1..1 inbound @par top filter is_same_collection('t',i)", - par.par = req.queryParams.id; + (qry = "for i in 1..1 inbound @par top filter is_same_collection('t',i)"), + (par.par = req.queryParams.id); } else { qry = "for i in t filter i.top == true"; } - qry += " sort i.title limit " + off + "," + cnt + " return {_id:i._id, title: i.title, admin: i.admin, coll_cnt: i.coll_cnt}"; - result = g_db._query(qry, par, {}, { - fullCount: true - }); + qry += + " sort i.title limit " + + off + + "," + + cnt + + " return {_id:i._id, title: i.title, admin: i.admin, coll_cnt: i.coll_cnt}"; + result = g_db._query( + qry, + par, + {}, + { + fullCount: true, + }, + ); var tot = result.getExtra().stats.fullCount; result = result.toArray(); result.push({ paging: { off: off, cnt: cnt, - tot: tot - } + tot: tot, + }, }); res.send(result); @@ -50,15 +61,15 @@ router.get('/list/topics', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().optional(), "Client ID") - .queryParam('id', joi.string().optional(), "ID of topic to list (omit for top-level)") - .queryParam('offset', joi.number().integer().min(0).optional(), "Offset") - .queryParam('count', joi.number().integer().min(1).optional(), "Count") - .summary('List topics') - .description('List topics under specified topic ID. If ID is omitted, lists top-level topics.'); - - -router.get('/view', function(req, res) { + .queryParam("client", joi.string().optional(), "Client ID") + .queryParam("id", joi.string().optional(), "ID of topic to list (omit for top-level)") + .queryParam("offset", joi.number().integer().min(0).optional(), "Offset") + .queryParam("count", joi.number().integer().min(1).optional(), "Count") + .summary("List topics") + .description("List topics under specified topic ID. If ID is omitted, lists top-level topics."); + +router + .get("/view", function (req, res) { try { if (!g_db.t.exists(req.queryParams.id)) throw [g_lib.ERR_NOT_FOUND, "Topic, " + req.queryParams.id + ", not found"]; @@ -70,21 +81,28 @@ router.get('/view', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().optional(), "Client ID") - .queryParam('id', joi.string().optional(), "ID of topic to view") - .summary('View topic') - .description('View a topic.'); + .queryParam("client", joi.string().optional(), "Client ID") + .queryParam("id", joi.string().optional(), "ID of topic to view") + .summary("View topic") + .description("View a topic."); -router.get('/search', function(req, res) { +router + .get("/search", function (req, res) { try { var tokens = req.queryParams.phrase.match(/(?:[^\s"]+|"[^"]*")+/g), qry = "for i in topicview search analyzer((", params = {}, - i, p, qry_res, result = [], - item, it, topic, path, op = false; - - if (tokens.length == 0) - throw [g_lib.ERR_INVALID_PARAM, "Invalid topic search phrase."]; + i, + p, + qry_res, + result = [], + item, + it, + topic, + path, + op = false; + + if (tokens.length == 0) throw [g_lib.ERR_INVALID_PARAM, "Invalid topic search phrase."]; it = 0; for (i in tokens) { @@ -105,19 +123,23 @@ router.get('/search', function(req, res) { item = qry_res.next(); it = item; topic = item.title; - path = [{ - _id: item._id, - title: item.title - }]; - - while ((item = g_db.top.firstExample({ - _from: item._id - }))) { + path = [ + { + _id: item._id, + title: item.title, + }, + ]; + + while ( + (item = g_db.top.firstExample({ + _from: item._id, + })) + ) { item = g_db.t.document(item._to); topic = item.title + "." + topic; path.unshift({ _id: item._id, - title: item.title + title: item.title, }); } @@ -126,7 +148,7 @@ router.get('/search', function(req, res) { title: topic, path: path, admin: it.admin, - coll_cnt: it.coll_cnt + coll_cnt: it.coll_cnt, }); } @@ -135,7 +157,7 @@ router.get('/search', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().optional(), "Client ID") - .queryParam('phrase', joi.string().required(), "Search words or phrase") - .summary('Search topics') - .description('Search topics by keyword or phrase'); \ No newline at end of file + .queryParam("client", joi.string().optional(), "Client ID") + .queryParam("phrase", joi.string().required(), "Search words or phrase") + .summary("Search topics") + .description("Search topics by keyword or phrase"); diff --git a/core/database/foxx/api/user_router.js b/core/database/foxx/api/user_router.js index 111e379a4..041e13dfd 100644 --- a/core/database/foxx/api/user_router.js +++ b/core/database/foxx/api/user_router.js @@ -1,76 +1,85 @@ -'use strict'; +"use strict"; -const createRouter = require('@arangodb/foxx/router'); +const createRouter = require("@arangodb/foxx/router"); const router = createRouter(); -const joi = require('joi'); -const createAuth = require('@arangodb/foxx/auth'); +const joi = require("joi"); +const createAuth = require("@arangodb/foxx/auth"); const auth = createAuth("pbkdf2"); -const g_db = require('@arangodb').db; -const g_graph = require('@arangodb/general-graph')._graph('sdmsg'); -const g_lib = require('./support'); +const g_db = require("@arangodb").db; +const g_graph = require("@arangodb/general-graph")._graph("sdmsg"); +const g_lib = require("./support"); +const { UserToken } = require("./lib/user_token"); +const { UserModel } = require("./models/user"); module.exports = router; //==================== USER API FUNCTIONS -router.get('/authn/password', function(req, res) { - console.log("Running /authn/password"); +router + .get("/authn/password", function (req, res) { + console.log("Running /authn/password"); try { const client = g_lib.getUserFromClientID(req.queryParams.client); const is_verified = auth.verify(client.password, req.queryParams.pw); if (is_verified === false) { throw g_lib.ERR_AUTHN_FAILED; - } + } //if ( client.password != req.queryParams.pw ) // throw g_lib.ERR_AUTHN_FAILED; res.send({ - "uid": client._id, - "authorized": true + uid: client._id, + authorized: true, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client SDMS UID") - .queryParam('pw', joi.string().required(), "SDMS account password") - .summary('Authenticate user') - .description('Authenticate user using password'); + .queryParam("client", joi.string().required(), "Client SDMS UID") + .queryParam("pw", joi.string().required(), "SDMS account password") + .summary("Authenticate user") + .description("Authenticate user using password"); -router.get('/authn/token', function(req, res) { +router + .get("/authn/token", function (req, res) { try { var user = g_db._query("for i in u filter i.access == @tok return i", { - tok: req.queryParams.token + tok: req.queryParams.token, }); - if (!user.hasNext()) - throw g_lib.ERR_AUTHN_FAILED; + if (!user.hasNext()) throw g_lib.ERR_AUTHN_FAILED; res.send({ - "uid": user.next()._id, - "authorized": true + uid: user.next()._id, + authorized: true, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('token', joi.string().required(), "Client access token") - .summary('Authenticate user') - .description('Authenticate user using access token'); + .queryParam("token", joi.string().required(), "Client access token") + .summary("Authenticate user") + .description("Authenticate user using access token"); -router.get('/create', function(req, res) { +router + .get("/create", function (req, res) { try { var result; g_db._executeTransaction({ collections: { read: ["u"], - write: ["u", "c", "a", "g", "acl", "owner", "ident", "uuid", "alias", "admin"] + write: ["u", "c", "a", "g", "acl", "owner", "ident", "uuid", "alias", "admin"], }, - action: function() { + action: function () { var cfg = g_db.config.document("config/system"); if (req.queryParams.secret != cfg.secret) { - console.log("ERROR: user create called with incorrect system secret. uid:", req.queryParams.uid, ", name:", req.queryParams.name); + console.log( + "ERROR: user create called with incorrect system secret. uid:", + req.queryParams.uid, + ", name:", + req.queryParams.name, + ); throw [g_lib.ERR_AUTHN_FAILED, "Invalid system credentials"]; } @@ -80,7 +89,10 @@ router.get('/create', function(req, res) { idx = name.lastIndexOf(" "); if (idx < 1) - throw [g_lib.ERR_INVALID_PARAM, "ERROR: invalid user name (no first/last name) " + name]; + throw [ + g_lib.ERR_INVALID_PARAM, + "ERROR: invalid user name (no first/last name) " + name, + ]; var lname = name.substr(idx + 1), fname = name.substr(0, idx).trim(); @@ -89,8 +101,8 @@ router.get('/create', function(req, res) { // It is assumed that if this is the first user to ever log // into the database they are by default made the admin. // This will simplify the setup process. - if ( g_db.u.count() === 0 ) { - is_admin = true; + if (g_db.u.count() === 0) { + is_admin = true; } var user_data = { @@ -103,7 +115,7 @@ router.get('/create', function(req, res) { max_proj: g_lib.DEF_MAX_PROJ, max_sav_qry: g_lib.DEF_MAX_SAV_QRY, ct: time, - ut: time + ut: time, }; if (req.queryParams.password) { @@ -120,61 +132,79 @@ router.get('/create', function(req, res) { } var user = g_db.u.save(user_data, { - returnNew: true - }); - var root = g_db.c.save({ - _key: "u_" + req.queryParams.uid + "_root", - is_root: true, - owner: user._id, - title: "Root Collection", - desc: "Root collection for user " + req.queryParams.name + " (" + req.queryParams.uid + ")", - alias: "root" - }, { - returnNew: true - }); - - var alias = g_db.a.save({ - _key: "u:" + req.queryParams.uid + ":root" - }, { - returnNew: true + returnNew: true, }); + var root = g_db.c.save( + { + _key: "u_" + req.queryParams.uid + "_root", + is_root: true, + owner: user._id, + title: "Root Collection", + desc: + "Root collection for user " + + req.queryParams.name + + " (" + + req.queryParams.uid + + ")", + alias: "root", + }, + { + returnNew: true, + }, + ); + + var alias = g_db.a.save( + { + _key: "u:" + req.queryParams.uid + ":root", + }, + { + returnNew: true, + }, + ); g_db.owner.save({ _from: alias._id, - _to: user._id + _to: user._id, }); g_db.alias.save({ _from: root._id, - _to: alias._id + _to: alias._id, }); g_db.owner.save({ _from: root._id, - _to: user._id + _to: user._id, }); var uuid; for (i in req.queryParams.uuids) { uuid = "uuid/" + req.queryParams.uuids[i]; - if (g_db._exists({ - _id: uuid - })) - throw [g_lib.ERR_IN_USE, "ERROR: linked identity value, " + uuid + ", already in use"]; - - g_db.uuid.save({ - _key: req.queryParams.uuids[i] - }, { - returnNew: true - }); + if ( + g_db._exists({ + _id: uuid, + }) + ) + throw [ + g_lib.ERR_IN_USE, + "ERROR: linked identity value, " + uuid + ", already in use", + ]; + + g_db.uuid.save( + { + _key: req.queryParams.uuids[i], + }, + { + returnNew: true, + }, + ); g_db.ident.save({ _from: user._id, - _to: uuid + _to: uuid, }); } user.new.uid = user.new._id; - if (req.queryParams.admins) - user.new.admins = req.queryParams.admins; + if (req.queryParams.admins) user.new.admins = req.queryParams.admins; delete user.new._id; delete user.new._key; @@ -182,7 +212,7 @@ router.get('/create', function(req, res) { delete user.new.name; result = [user.new]; - } + }, }); res.send(result); @@ -190,28 +220,32 @@ router.get('/create', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('secret', joi.string().required(), "System secret required to authorize this action") - .queryParam('uid', joi.string().required(), "SDMS user ID (globus) for new user") - .queryParam('password', joi.string().optional().allow(""), "New CLI password") - .queryParam('name', joi.string().required(), "Name") - .queryParam('email', joi.string().optional(), "Email") - .queryParam('options', joi.string().optional(), "Application options (JSON string)") - .queryParam('uuids', joi.array().items(joi.string()).required(), "Globus identities (UUIDs)") - .queryParam('is_admin', joi.boolean().optional(), "New account is a system administrator") - .summary('Create new user entry') - .description('Create new user entry.'); - - -router.get('/update', function(req, res) { + .queryParam( + "secret", + joi.string().required(), + "System secret required to authorize this action", + ) + .queryParam("uid", joi.string().required(), "SDMS user ID (globus) for new user") + .queryParam("password", joi.string().optional().allow(""), "New CLI password") + .queryParam("name", joi.string().required(), "Name") + .queryParam("email", joi.string().optional(), "Email") + .queryParam("options", joi.string().optional(), "Application options (JSON string)") + .queryParam("uuids", joi.array().items(joi.string()).required(), "Globus identities (UUIDs)") + .queryParam("is_admin", joi.boolean().optional(), "New account is a system administrator") + .summary("Create new user entry") + .description("Create new user entry."); + +router + .get("/update", function (req, res) { try { var result; g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn"], - write: ["u", "admin"] + write: ["u", "admin"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var user_id; @@ -236,28 +270,28 @@ router.get('/update', function(req, res) { var idx = name.lastIndexOf(" "); if (idx < 1) { - throw [g_lib.ERR_INVALID_PARAM, "Invalid user name (no first/last name) " + req.queryParams.name]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Invalid user name (no first/last name) " + req.queryParams.name, + ]; } - obj.name_first = name.substr(0, idx).trim(), - obj.name_last = name.substr(idx + 1); + (obj.name_first = name.substr(0, idx).trim()), + (obj.name_last = name.substr(idx + 1)); obj.name = name.toLowerCase() + " " + user_id.substr(2); } - if (req.queryParams.email) - obj.email = req.queryParams.email; + if (req.queryParams.email) obj.email = req.queryParams.email; - if (req.queryParams.options) - obj.options = req.queryParams.options; + if (req.queryParams.options) obj.options = req.queryParams.options; if (client.is_admin) { - if (req.queryParams.is_admin) - obj.is_admin = req.queryParams.is_admin; + if (req.queryParams.is_admin) obj.is_admin = req.queryParams.is_admin; } var user = g_db._update(user_id, obj, { keepNull: false, - returnNew: true + returnNew: true, }); user.new.uid = user.new._id; @@ -272,7 +306,7 @@ router.get('/update', function(req, res) { delete user.new.refresh; result = [user.new]; - } + }, }); res.send(result); @@ -280,18 +314,18 @@ router.get('/update', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client uid") - .queryParam('subject', joi.string().optional(), "UID of subject user (optional)") - .queryParam('password', joi.string().optional(), "New CLI password") - .queryParam('name', joi.string().optional(), "New name") - .queryParam('email', joi.string().optional(), "New email") - .queryParam('options', joi.string().optional(), "Application options (JSON string)") - .queryParam('is_admin', joi.boolean().optional(), "New system administrator flag value") - .summary('Update user information') - .description('Update user information'); - - -router.get('/find/by_uuids', function(req, res) { + .queryParam("client", joi.string().required(), "Client uid") + .queryParam("subject", joi.string().optional(), "UID of subject user (optional)") + .queryParam("password", joi.string().optional(), "New CLI password") + .queryParam("name", joi.string().optional(), "New name") + .queryParam("email", joi.string().optional(), "New email") + .queryParam("options", joi.string().optional(), "Application options (JSON string)") + .queryParam("is_admin", joi.boolean().optional(), "New system administrator flag value") + .summary("Update user information") + .description("Update user information"); + +router + .get("/find/by_uuids", function (req, res) { try { // Convert UUIDs to DB _ids var uuids = []; @@ -301,9 +335,11 @@ router.get('/find/by_uuids', function(req, res) { var user = g_lib.findUserFromUUIDs(uuids); - var idents = g_db._query("for v in 1..1 outbound @user ident return v._key", { - user: user._id - }).toArray(); + var idents = g_db + ._query("for v in 1..1 outbound @user ident return v._key", { + user: user._id, + }) + .toArray(); if (idents.length) { user.idents = idents; } @@ -320,30 +356,33 @@ router.get('/find/by_uuids', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('uuids', joi.array().items(joi.string()).required(), "User UUID List") - .summary('Find a user from list of UUIDs') - .description('Find a user from list of UUIDs'); - + .queryParam("uuids", joi.array().items(joi.string()).required(), "User UUID List") + .summary("Find a user from list of UUIDs") + .description("Find a user from list of UUIDs"); -router.get('/find/by_name_uid', function(req, res) { +router + .get("/find/by_name_uid", function (req, res) { try { var name = req.queryParams.name_uid.trim(); if (name.length < 2) throw [g_lib.ERR_INVALID_PARAM, "Input is too short for name/uid search."]; - else if (name.length < 3) - name = " " + name + " "; // Pad to allow matches for very short first/last names (i.e. Bo, Li, Xi) + else if (name.length < 3) name = " " + name + " "; // Pad to allow matches for very short first/last names (i.e. Bo, Li, Xi) var off = req.queryParams.offset ? req.queryParams.offset : 0, cnt = req.queryParams.count ? req.queryParams.count : 20; - var result = g_db._query("for u in userview search analyzer(u.name in tokens(@name,'user_name'), 'user_name')" + - " let s = BM25(u) filter s > 0 sort s desc limit @off,@cnt return {uid:u._id,name_last:u.name_last,name_first:u.name_first}", { + var result = g_db._query( + "for u in userview search analyzer(u.name in tokens(@name,'user_name'), 'user_name')" + + " let s = BM25(u) filter s > 0 sort s desc limit @off,@cnt return {uid:u._id,name_last:u.name_last,name_first:u.name_first}", + { name: name, off: off, - cnt: cnt - }, { - fullCount: true - }); + cnt: cnt, + }, + { + fullCount: true, + }, + ); var tot = result.getExtra().stats.fullCount; result = result.toArray(); @@ -351,8 +390,8 @@ router.get('/find/by_name_uid', function(req, res) { paging: { off: off, cnt: cnt, - tot: tot - } + tot: tot, + }, }); res.send(result); @@ -360,21 +399,21 @@ router.get('/find/by_name_uid', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('name_uid', joi.string().required(), "User name and/or uid (partial)") - .queryParam('offset', joi.number().optional(), "Offset") - .queryParam('count', joi.number().optional(), "Count") - .summary('Find users matching partial name and/or uid') - .description('Find users matching partial name and/or uid'); - - -router.get('/keys/set', function(req, res) { + .queryParam("name_uid", joi.string().required(), "User name and/or uid (partial)") + .queryParam("offset", joi.number().optional(), "Offset") + .queryParam("count", joi.number().optional(), "Count") + .summary("Find users matching partial name and/or uid") + .description("Find users matching partial name and/or uid"); + +router + .get("/keys/set", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn"], - write: ["u"] + write: ["u"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var user_id; @@ -389,32 +428,33 @@ router.get('/keys/set', function(req, res) { var obj = { pub_key: req.queryParams.pub_key, - priv_key: req.queryParams.priv_key + priv_key: req.queryParams.priv_key, }; g_db._update(user_id, obj, { - keepNull: false + keepNull: false, }); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().optional(), "UID of subject user") - .queryParam('pub_key', joi.string().required(), "User public key") - .queryParam('priv_key', joi.string().required(), "User private key") - .summary('Set user public and private keys') - .description('Set user public and private keys'); - -router.get('/keys/clear', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().optional(), "UID of subject user") + .queryParam("pub_key", joi.string().required(), "User public key") + .queryParam("priv_key", joi.string().required(), "User private key") + .summary("Set user public and private keys") + .description("Set user public and private keys"); + +router + .get("/keys/clear", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "uuid", "accn"], - write: ["u"] + write: ["u"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var user_id; @@ -429,57 +469,66 @@ router.get('/keys/clear', function(req, res) { var obj = { pub_key: null, - priv_key: null + priv_key: null, }; g_db._update(user_id, obj, { - keepNull: false + keepNull: false, }); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().optional(), "UID of subject user") - .summary('Clear user public and private keys') - .description('Clear user public and private keys'); + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().optional(), "UID of subject user") + .summary("Clear user public and private keys") + .description("Clear user public and private keys"); -router.get('/keys/get', function(req, res) { +router + .get("/keys/get", function (req, res) { try { var user; if (req.queryParams.subject) { if (!g_db.u.exists(req.queryParams.subject)) - throw [g_lib.ERR_INVALID_PARAM, "No such user '" + req.queryParams.subject + "'"]; + throw [ + g_lib.ERR_INVALID_PARAM, + "No such user '" + req.queryParams.subject + "'", + ]; user = g_db.u.document({ - _id: req.queryParams.subject + _id: req.queryParams.subject, }); } else { user = g_lib.getUserFromClientID(req.queryParams.client); } if (!user.pub_key || !user.priv_key) - res.send([{ - uid: user._id - }]); + res.send([ + { + uid: user._id, + }, + ]); else - res.send([{ - uid: user._id, - pub_key: user.pub_key, - priv_key: user.priv_key - }]); + res.send([ + { + uid: user._id, + pub_key: user.pub_key, + priv_key: user.priv_key, + }, + ]); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().optional(), "UID of subject user") - .summary('Get user public and private keys') - .description('Get user public and private keys'); + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().optional(), "UID of subject user") + .summary("Get user public and private keys") + .description("Get user public and private keys"); -router.get('/find/by_pub_key', function(req, res) { +router + .get("/find/by_pub_key", function (req, res) { try { var uid = g_lib.uidFromPubKey(req.queryParams.pub_key); res.send(uid); @@ -487,166 +536,315 @@ router.get('/find/by_pub_key', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('pub_key', joi.string().required(), "User public key") - .summary('Find a user by public key') - .description('Find a user by public key'); + .queryParam("pub_key", joi.string().required(), "User public key") + .summary("Find a user by public key") + .description("Find a user by public key"); -router.get('/token/set', function(req, res) { +router + .get("/token/set", function (req, res) { try { g_db._executeTransaction({ collections: { - read: ["u", "uuid", "accn"], - write: ["u"] + read: ["u", "uuid", "accn", "globus_coll"], + write: ["u", "globus_coll", "globus_token"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var user_id; + let user_doc; + + const { type: token_type, other_token_data } = req.queryParams; + // validate optional query params + if ( + Boolean(other_token_data) && + token_type === g_lib.AccessTokenType.GLOBUS_DEFAULT + ) { + throw [ + g_lib.ERR_INVALID_PARAM, + "Invalid parameters passed, the default action cannot process other_token_data.", + ]; + } else if ( + !other_token_data && + token_type !== g_lib.AccessTokenType.GLOBUS_DEFAULT + ) { + throw [ + g_lib.ERR_INVALID_PARAM, + "Invalid parameters passed, type and other_token_data depend on one another.", + ]; + } if (req.queryParams.subject) { user_id = req.queryParams.subject; if (!g_db.u.exists(user_id)) throw [g_lib.ERR_INVALID_PARAM, "No such user '" + user_id + "'"]; g_lib.ensureAdminPermUser(client, user_id); + user_doc = g_db.u.document(user_id); } else { user_id = client._id; + user_doc = client; } - console.log("updating tokens for", user_id, "acc:", req.queryParams.access, "exp:", req.queryParams.expires_in); + console.log( + "updating tokens for", + user_id, + "acc:", + req.queryParams.access, + "exp:", + req.queryParams.expires_in, + ); var obj = { access: req.queryParams.access, refresh: req.queryParams.refresh, - expiration: Math.floor(Date.now() / 1000) + req.queryParams.expires_in + expiration: Math.floor(Date.now() / 1000) + req.queryParams.expires_in, }; - g_db._update(user_id, obj, { - keepNull: false - }); - } + + switch (token_type) { + // TODO: update logic for various AccessTokenType instances as they are defined. + case g_lib.AccessTokenType.GENERIC: { + break; + } + case g_lib.AccessTokenType.GLOBUS: { + break; + } + case g_lib.AccessTokenType.GLOBUS_AUTH: { + break; + } + case g_lib.AccessTokenType.GLOBUS_TRANSFER: { + // find or insert collection + const { uuid: collection_search_key, scopes } = + g_lib.parseOtherTokenData( + g_lib.AccessTokenType.GLOBUS_TRANSFER, + other_token_data, + ); // TODO: the call site and function and docs will need to be updated if changes are made to assumed data + // GLOBUS_TRANSFER parse currently assumes uuid and scopes exist + let globus_collection = g_db.globus_coll.exists({ + _key: collection_search_key, + }); + if (!globus_collection) { + globus_collection = g_db.globus_coll.save({ + _key: collection_search_key, + name: "Newly Inserted Collection", + description: "The collection description", + required_scopes: scopes, // string - Is this always the minimum required set? + owner: "", // Should this be looked up on Globus? + ct: Math.floor(Date.now() / 1000), + ut: Math.floor(Date.now() / 1000), + type: "mapped", // mapped/guest TODO: to be pulled from token data on follow-up ticket + ha_enabled: false, // boolean - TODO: to be pulled from token data on follow-up ticket + }); + } + + const token_key = + globus_collection._key + "_" + token_type + "_" + user_doc._key; + const token_doc = { + _key: token_key, + _from: user_id, // the uid field + _to: globus_collection._id, + type: token_type, + dependent_scopes: scopes, + request_time: Math.floor(Date.now() / 1000), + last_used: Math.floor(Date.now() / 1000), + status: + obj.expiration > Math.floor(Date.now() / 1000) + ? "active" + : "inactive", + ...obj, + }; + + console.log("writing to edge ", token_doc); + const token_doc_upsert = g_db.globus_token.insert(token_doc, { + overwriteMode: "replace", // TODO: perhaps use 'update' and specify values for true upsert. + }); + break; + } + case g_lib.AccessTokenType.GLOBUS_DEFAULT: { + // Existing logic, default actions + g_db._update(user_id, obj, { + keepNull: false, + }); + break; + } + } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().optional(), "UID of subject user") - .queryParam('access', joi.string().required(), "User access token") - .queryParam('refresh', joi.string().required(), "User refresh token") - .queryParam('expires_in', joi.number().integer().required(), "Access token expiration timestamp") - .summary('Set user tokens') - .description('Set user tokens'); - -router.get('/token/get', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().optional(), "UID of subject user") + .queryParam("access", joi.string().required(), "User access token") + .queryParam("refresh", joi.string().required(), "User refresh token") + .queryParam( + "expires_in", + joi.number().integer().required(), + "Access token expiration timestamp", + ) + .queryParam( + "type", + joi + .number() + .valid(...Object.values(g_lib.AccessTokenType)) + .optional() + .default(g_lib.AccessTokenType.GLOBUS_DEFAULT), + "Type of token being stored", + ) + .queryParam( + "other_token_data", + joi.string().optional(), + "Other data associated with token, currently only supported as Globus Collection UUID e.g. other_token_data=1cbaaee5-b938-4a4e-87a8-f1ec4d5d92f9", + ) + .summary("Set user tokens") + .description("Set user tokens"); + +router + .get("/token/get", function (req, res) { try { + const collection_token = UserToken.validateRequestParams(req.queryParams); + // TODO: collection type determines logic when mapped vs HA + const { collection_id, collection_type } = req.queryParams; + var user; if (req.queryParams.subject) { if (!g_db.u.exists(req.queryParams.subject)) - throw [g_lib.ERR_INVALID_PARAM, "No such user '" + req.queryParams.subject + "'"]; + throw [ + g_lib.ERR_INVALID_PARAM, + "No such user '" + req.queryParams.subject + "'", + ]; user = g_db.u.document({ - _id: req.queryParams.subject + _id: req.queryParams.subject, }); } else { user = g_lib.getUserFromClientID(req.queryParams.client); } - var result = {}; - if (user.access != undefined) - result.access = user.access; - if (user.refresh != undefined) - result.refresh = user.refresh; - if (user.expiration) { - var exp = user.expiration - Math.floor(Date.now() / 1000); - console.log("tok/get", Math.floor(Date.now() / 1000), user.expiration, exp); - result.expires_in = (exp > 0 ? exp : 0); - } else { - console.log("tok/get - no expiration"); - result.expires_in = 0; + const user_token = new UserToken({ + user_id: user._id, + globus_collection_id: collection_id, + }); + let needs_consent = false; + + const token_document = user_token.get_token(); + if (!user_token.exists()) { + needs_consent = true; } + const result = UserToken.formatUserToken( + collection_token, + token_document, + needs_consent, + ); res.send(result); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().optional(), "UID of subject user") - .summary('Get user tokens') - .description('Get user tokens'); - -router.get('/token/get/access', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().optional(), "UID of subject user") + .queryParam( + "collection_id", + joi.string().optional().guid(), + "ID of collection with which token is associated", + ) // https://joi.dev/api/?v=17.13.3#stringguid---aliases-uuid + .queryParam( + "collection_type", + joi.string().optional().valid("mapped"), + "Type of collection with which token is associated", + ) + .summary("Get user tokens") + .description("Get user tokens"); + +router + .get("/token/get/access", function (req, res) { try { var user; if (req.queryParams.subject) { if (!g_db.u.exists(req.queryParams.subject)) - throw [g_lib.ERR_INVALID_PARAM, "No such user '" + req.queryParams.subject + "'"]; + throw [ + g_lib.ERR_INVALID_PARAM, + "No such user '" + req.queryParams.subject + "'", + ]; user = g_db.u.document({ - _id: req.queryParams.subject + _id: req.queryParams.subject, }); } else { user = g_lib.getUserFromClientID(req.queryParams.client); } - if (!user.access) - throw [g_lib.ERR_NOT_FOUND, "No access token found"]; + if (!user.access) throw [g_lib.ERR_NOT_FOUND, "No access token found"]; res.send(user.access); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().optional(), "UID of subject user") - .summary('Get user access token') - .description('Get user access token'); + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().optional(), "UID of subject user") + .summary("Get user access token") + .description("Get user access token"); - -router.get('/token/get/expiring', function(req, res) { +router + .get("/token/get/expiring", function (req, res) { try { //console.log("exp:",(Date.now()/1000) + req.queryParams.expires_in); - var results = g_db._query("for i in u filter i.expiration != Null && i.expiration < @exp return {id:i._id,access:i.access,refresh:i.refresh,expiration:i.expiration}", { - exp: Math.floor(Date.now() / 1000) + req.queryParams.expires_in - }); + var results = g_db._query( + "for i in u filter i.expiration != Null && i.expiration < @exp return {id:i._id,access:i.access,refresh:i.refresh,expiration:i.expiration}", + { + exp: Math.floor(Date.now() / 1000) + req.queryParams.expires_in, + }, + ); res.send(results); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('expires_in', joi.number().integer().required(), "Expires in (sec)") - .summary('Get expiring user access tokens') - .description('Get expiring user access token'); - + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("expires_in", joi.number().integer().required(), "Expires in (sec)") + .summary("Get expiring user access tokens") + .description("Get expiring user access token"); -router.get('/view', function(req, res) { +router + .get("/view", function (req, res) { try { var client = g_lib.getUserFromClientID_noexcept(req.queryParams.client); - var user, det_ok = false; + var user, + det_ok = false; if (req.queryParams.subject) { if (!g_db.u.exists(req.queryParams.subject)) - throw [g_lib.ERR_INVALID_PARAM, "No such user '" + req.queryParams.subject + "'"]; + throw [ + g_lib.ERR_INVALID_PARAM, + "No such user '" + req.queryParams.subject + "'", + ]; user = g_db.u.document({ - _id: req.queryParams.subject + _id: req.queryParams.subject, }); - if (client && (client._id == user._id || client.is_admin)) - det_ok = true; + if (client && (client._id == user._id || client.is_admin)) det_ok = true; } else { user = client; det_ok = true; } if (det_ok) { - var repos = g_db._query("for v in 1..1 inbound @user admin filter is_same_collection('repo',v) limit 1 return v._key", { - user: user._id - }).toArray(); - if (repos.length) - user.is_repo_admin = true; - - user.allocs = g_db.alloc.byExample({ - _from: user._id - }).toArray(); + var repos = g_db + ._query( + "for v in 1..1 inbound @user admin filter is_same_collection('repo',v) limit 1 return v._key", + { + user: user._id, + }, + ) + .toArray(); + if (repos.length) user.is_repo_admin = true; + + user.allocs = g_db.alloc + .byExample({ + _from: user._id, + }) + .toArray(); if (user.allocs.length) { var alloc; @@ -662,9 +860,11 @@ router.get('/view', function(req, res) { } if (req.queryParams.details) { - var idents = g_db._query("for v in 1..1 outbound @user ident return v._key", { - user: user._id - }).toArray(); + var idents = g_db + ._query("for v in 1..1 outbound @user ident return v._key", { + user: user._id, + }) + .toArray(); if (idents.length) { user.idents = idents; } @@ -694,30 +894,40 @@ router.get('/view', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().optional(), "UID of subject user to view") - .queryParam('details', joi.boolean().optional(), "Show additional user details") - .summary('View user information') - .description('View user information'); - - -router.get('/list/all', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().optional(), "UID of subject user to view") + .queryParam("details", joi.boolean().optional(), "Show additional user details") + .summary("View user information") + .description("View user information"); + +router + .get("/list/all", function (req, res) { var qry = "for i in u sort i.name_last, i.name_first"; var result; if (req.queryParams.offset != undefined && req.queryParams.count != undefined) { - qry += " limit " + req.queryParams.offset + ", " + req.queryParams.count + " return { uid: i._id, name_last: i.name_last, name_first: i.name_first }"; - result = g_db._query(qry, {}, {}, { - fullCount: true - }); + qry += + " limit " + + req.queryParams.offset + + ", " + + req.queryParams.count + + " return { uid: i._id, name_last: i.name_last, name_first: i.name_first }"; + result = g_db._query( + qry, + {}, + {}, + { + fullCount: true, + }, + ); var tot = result.getExtra().stats.fullCount; result = result.toArray(); result.push({ paging: { off: req.queryParams.offset, cnt: req.queryParams.count, - tot: tot - } + tot: tot, + }, }); } else { qry += " return { uid: i._id, name_last: i.name_last, name_first: i.name_first }"; @@ -726,14 +936,17 @@ router.get('/list/all', function(req, res) { res.send(result); }) - .queryParam('offset', joi.number().optional(), "Offset") - .queryParam('count', joi.number().optional(), "Count") - .summary('List all users') - .description('List all users'); - -router.get('/list/collab', function(req, res) { - var result, client = g_lib.getUserFromClientID(req.queryParams.client); - var qry = "for x in union_distinct((for v in 2..2 any @user owner, member, acl filter is_same_collection('u',v) return" + + .queryParam("offset", joi.number().optional(), "Offset") + .queryParam("count", joi.number().optional(), "Count") + .summary("List all users") + .description("List all users"); + +router + .get("/list/collab", function (req, res) { + var result, + client = g_lib.getUserFromClientID(req.queryParams.client); + var qry = + "for x in union_distinct((for v in 2..2 any @user owner, member, acl filter is_same_collection('u',v) return" + " distinct { uid: v._id, name_last: v.name_last, name_first: v.name_first }),(for v in 3..3 inbound @user member, outbound owner, outbound admin" + " filter is_same_collection('u',v) return distinct { uid: v._id, name_last: v.name_last, name_first: v.name_first }),(for v in 2..2 inbound @user" + " owner, outbound admin filter is_same_collection('u',v) return distinct { uid: v._id, name_last: v.name_last, name_first: v.name_first })) sort x.name_last, x.name_first"; @@ -745,48 +958,72 @@ router.get('/list/collab', function(req, res) { // Owner and admins of member projects (members gathered by group members above) if (req.queryParams.offset != undefined && req.queryParams.count != undefined) { qry += " limit " + req.queryParams.offset + ", " + req.queryParams.count + " return x"; - result = g_db._query(qry, { - user: client._id - }, {}, { - fullCount: true - }); + result = g_db._query( + qry, + { + user: client._id, + }, + {}, + { + fullCount: true, + }, + ); var tot = result.getExtra().stats.fullCount; result = result.toArray(); result.push({ paging: { off: req.queryParams.offset, cnt: req.queryParams.count, - tot: tot - } + tot: tot, + }, }); } else { qry += " return x"; result = g_db._query(qry, { - user: client._id + user: client._id, }); } res.send(result); //res.send( g_db._query( "for x in union_distinct((for v in 2..2 any @user owner, member, acl filter is_same_collection('u',v) return distinct { uid: v._id, name: v.name }),(for v in 3..3 inbound @user member, outbound owner, outbound admin filter is_same_collection('u',v) return distinct { uid: v._id, name: v.name }),(for v in 2..2 inbound @user owner, outbound admin filter is_same_collection('u',v) return distinct { uid: v._id, name: v.name })) return x", { user: client._id })); }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('offset', joi.number().optional(), "Offset") - .queryParam('count', joi.number().optional(), "Count") - .summary('List collaborators of client') - .description('List collaborators of client (from groups, projects, and ACLs)'); + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("offset", joi.number().optional(), "Offset") + .queryParam("count", joi.number().optional(), "Count") + .summary("List collaborators of client") + .description("List collaborators of client (from groups, projects, and ACLs)"); /* Remove a user account from the system. Note: must delete ALL data records and projects owned by the user being deleted before deleting the user. */ -router.get('/delete', function(req, res) { +router + .get("/delete", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "admin"], - write: ["u", "p", "g", "uuid", "accn", "c", "d", "a", "acl", "owner", "ident", "alias", "admin", "member", "item", "alloc", "loc"] + write: [ + "u", + "p", + "g", + "uuid", + "accn", + "c", + "d", + "a", + "acl", + "owner", + "ident", + "alias", + "admin", + "member", + "item", + "alloc", + "loc", + ], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var user_id; @@ -803,9 +1040,11 @@ router.get('/delete', function(req, res) { var objects, subobjects, obj, subobj, i, j; // Delete linked accounts - objects = g_db._query("for v in 1..1 outbound @user ident return v._id", { - user: user_id - }).toArray(); + objects = g_db + ._query("for v in 1..1 outbound @user ident return v._id", { + user: user_id, + }) + .toArray(); for (i in objects) { obj = objects[i]; //console.log( "del ident", obj ); @@ -813,15 +1052,22 @@ router.get('/delete', function(req, res) { } // Delete owned projects - objects = g_db._query("for v in 1..1 inbound @user owner filter is_same_collection('p',v) return v._id", { - user: user_id - }).toArray(); + objects = g_db + ._query( + "for v in 1..1 inbound @user owner filter is_same_collection('p',v) return v._id", + { + user: user_id, + }, + ) + .toArray(); for (i in objects) { obj = objects[i]; //console.log( "del proj", obj ); - subobjects = g_db._query("for v in 1..1 inbound @proj owner return v._id", { - proj: obj - }).toArray(); + subobjects = g_db + ._query("for v in 1..1 inbound @proj owner return v._id", { + proj: obj, + }) + .toArray(); for (j in subobjects) { subobj = subobjects[j]; //console.log("del subobj",subobj); @@ -832,9 +1078,11 @@ router.get('/delete', function(req, res) { } // Delete collections, data, groups, notes - objects = g_db._query("for v in 1..1 inbound @user owner return v._id", { - user: user_id - }).toArray(); + objects = g_db + ._query("for v in 1..1 inbound @user owner return v._id", { + user: user_id, + }) + .toArray(); for (i in objects) { obj = objects[i]; //console.log( "del owned", obj ); @@ -842,134 +1090,159 @@ router.get('/delete', function(req, res) { } g_graph.u.remove(user_id); - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().optional(), "UID of subject user (optional)") - .summary('Remove existing user entry') - .description('Remove existing user entry. Requires admin permissions.'); - + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().optional(), "UID of subject user (optional)") + .summary("Remove existing user entry") + .description("Remove existing user entry. Requires admin permissions."); -router.get('/ident/list', function(req, res) { +router + .get("/ident/list", function (req, res) { try { var client = g_lib.getUserFromClientID(req.queryParams.client); if (req.queryParams.subject) { if (!g_db.u.exists(req.queryParams.subject)) - throw [g_lib.ERR_INVALID_PARAM, "No such user '" + req.queryParams.subject + "'"]; + throw [ + g_lib.ERR_INVALID_PARAM, + "No such user '" + req.queryParams.subject + "'", + ]; const subject = g_db.u.document(req.queryParams.subject); g_lib.ensureAdminPermUser(client, subject._id); - res.send(g_db._query("for v in 1..1 outbound @client ident return v._key", { - client: subject._id - })); + res.send( + g_db._query("for v in 1..1 outbound @client ident return v._key", { + client: subject._id, + }), + ); } else { - res.send(g_db._query("for v in 1..1 outbound @client ident return v._key", { - client: client._id - })); + res.send( + g_db._query("for v in 1..1 outbound @client ident return v._key", { + client: client._id, + }), + ); } } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().optional(), "UID of subject user (optional)") - .summary('List user linked UIDs'); - + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().optional(), "UID of subject user (optional)") + .summary("List user linked UIDs"); -router.get('/ident/add', function(req, res) { +router + .get("/ident/add", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "admin"], - write: ["uuid", "accn", "ident"] + write: ["uuid", "accn", "ident"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); var id; if (g_lib.isUUID(req.queryParams.ident)) { - if (g_db._exists({ - _id: "uuid/" + req.queryParams.ident - })) + if ( + g_db._exists({ + _id: "uuid/" + req.queryParams.ident, + }) + ) return; - id = g_db.uuid.save({ - _key: req.queryParams.ident - }, { - returnNew: true - }); + id = g_db.uuid.save( + { + _key: req.queryParams.ident, + }, + { + returnNew: true, + }, + ); } else if (g_lib.isDomainAccount(req.queryParams.ident)) { - if (g_db._exists({ - _id: "accn/" + req.queryParams.ident - })) { + if ( + g_db._exists({ + _id: "accn/" + req.queryParams.ident, + }) + ) { if (req.queryParams.pub_key && req.queryParams.priv_key) { // Update existing accn with new keys - g_db.accn.update({ - _id: "accn/" + req.queryParams.ident - }, { - pub_key: req.queryParams.pub_key, - priv_key: req.queryParams.priv_key - }); + g_db.accn.update( + { + _id: "accn/" + req.queryParams.ident, + }, + { + pub_key: req.queryParams.pub_key, + priv_key: req.queryParams.priv_key, + }, + ); } return; } else { var accn = { - _key: req.queryParams.ident + _key: req.queryParams.ident, }; if (req.queryParams.pub_key && req.queryParams.priv_key) { accn.pub_key = req.queryParams.pub_key; accn.priv_key = req.queryParams.priv_key; } id = g_db.accn.save(accn, { - returnNew: true + returnNew: true, }); } } else - throw [g_lib.ERR_INVALID_PARAM, "Invalid identity value: " + req.queryParams.ident]; + throw [ + g_lib.ERR_INVALID_PARAM, + "Invalid identity value: " + req.queryParams.ident, + ]; if (req.queryParams.subject) { if (!g_db.u.exists(req.queryParams.subject)) - throw [g_lib.ERR_INVALID_PARAM, "No such user '" + req.queryParams.subject + "'"]; + throw [ + g_lib.ERR_INVALID_PARAM, + "No such user '" + req.queryParams.subject + "'", + ]; const user = g_db.u.document(req.queryParams.subject); g_lib.ensureAdminPermUser(client, user._id); g_db.ident.save({ _from: user._id, - _to: id._id + _to: id._id, }); } else { g_db.ident.save({ _from: client._id, - _to: id._id + _to: id._id, }); } - } + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('subject', joi.string().optional(), "UID of subject user (optional)") - .queryParam('ident', joi.string().required(), "Identity to add") - .queryParam('pub_key', joi.string().optional(), "Optional public key (domain accounts only)") - .queryParam('priv_key', joi.string().optional(), "Optional private key (domain accounts only)") - .summary('Add new linked identity') - .description('Add new linked identity to user account. Identities can be UUIDs or domain accounts.'); - - -router.get('/ident/remove', function(req, res) { + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("subject", joi.string().optional(), "UID of subject user (optional)") + .queryParam("ident", joi.string().required(), "Identity to add") + .queryParam("pub_key", joi.string().optional(), "Optional public key (domain accounts only)") + .queryParam("priv_key", joi.string().optional(), "Optional private key (domain accounts only)") + .summary("Add new linked identity") + .description( + "Add new linked identity to user account. Identities can be UUIDs or domain accounts.", + ); + +router + .get("/ident/remove", function (req, res) { try { g_db._executeTransaction({ collections: { read: ["u", "admin"], - write: ["uuid", "accn", "ident"] + write: ["uuid", "accn", "ident"], }, - action: function() { + action: function () { const client = g_lib.getUserFromClientID(req.queryParams.client); const owner = g_lib.getUserFromClientID(req.queryParams.ident); @@ -980,20 +1253,23 @@ router.get('/ident/remove', function(req, res) { } else if (g_lib.isDomainAccount(req.queryParams.ident)) { g_graph.accn.remove("accn/" + req.queryParams.ident); } else - throw [g_lib.ERR_INVALID_PARAM, "Invalid identity value: " + req.queryParams.ident]; - } + throw [ + g_lib.ERR_INVALID_PARAM, + "Invalid identity value: " + req.queryParams.ident, + ]; + }, }); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('ident', joi.string().required(), "Certificate to delete") - .summary('Remove linked identity from user account') - .description('Remove linked identity from user account'); - + .queryParam("client", joi.string().required(), "Client ID") + .queryParam("ident", joi.string().required(), "Certificate to delete") + .summary("Remove linked identity from user account") + .description("Remove linked identity from user account"); -router.get('/ep/get', function(req, res) { +router + .get("/ep/get", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); res.send(client.eps ? client.eps : []); @@ -1001,23 +1277,32 @@ router.get('/ep/get', function(req, res) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .summary('Get recent end-points') - .description('Get recent end-points'); + .queryParam("client", joi.string().required(), "Client ID") + .summary("Get recent end-points") + .description("Get recent end-points"); -router.get('/ep/set', function(req, res) { +router + .get("/ep/set", function (req, res) { try { const client = g_lib.getUserFromClientID(req.queryParams.client); - g_db._update(client._id, { - eps: req.queryParams.eps - }, { - keepNull: false - }); + g_db._update( + client._id, + { + eps: req.queryParams.eps, + }, + { + keepNull: false, + }, + ); } catch (e) { g_lib.handleException(e, res); } }) - .queryParam('client', joi.string().required(), "Client ID") - .queryParam('eps', joi.array().items(joi.string()).required(), "End-points (UUIDs or legacy names)") - .summary('Set recent end-points') - .description('Set recent end-points'); + .queryParam("client", joi.string().required(), "Client ID") + .queryParam( + "eps", + joi.array().items(joi.string()).required(), + "End-points (UUIDs or legacy names)", + ) + .summary("Set recent end-points") + .description("Set recent end-points"); diff --git a/core/database/foxx/db_clear.js b/core/database/foxx/db_clear.js index 7fb91aa38..7df5ca5ab 100644 --- a/core/database/foxx/db_clear.js +++ b/core/database/foxx/db_clear.js @@ -1,4 +1,4 @@ -db._useDatabase('sdms'); +db._useDatabase("sdms"); db._truncate("u"); db._truncate("accn"); db._truncate("uuid"); diff --git a/core/database/foxx/db_create.js b/core/database/foxx/db_create.js index 0b5af4bcf..118d80bdb 100644 --- a/core/database/foxx/db_create.js +++ b/core/database/foxx/db_create.js @@ -1,7 +1,7 @@ // Creates SDMS database schema for ArangoDB -db._createDatabase('sdms'); -db._useDatabase('sdms'); +db._createDatabase("sdms"); +db._useDatabase("sdms"); var graph_module = require("@arangodb/general-graph"); var graph = graph_module._create("sdmsg"); @@ -78,7 +78,6 @@ graph._extendEdgeDefinitions(sch_dep); var sch_ver = graph_module._relation("sch_ver", ["sch"], ["sch"]); graph._extendEdgeDefinitions(sch_ver); - //db._query("for doc in userview2 search analyzer(doc.name in tokens('Joe Samson','na2'), 'na2') let s = BM25(doc) filter s > 2 sort s desc return {id: doc._id,name:doc.name,score:s}"); //db._query("for doc in userview search analyzer(doc.name in tokens('x st','user_name'), 'user_name') let s = BM25(doc,1.2,.5) sort s desc return {id:doc._id,name:doc.name,score:s}"); @@ -87,229 +86,261 @@ var analyzers = require("@arangodb/analyzers"); // ---------- User name indexing (view) ---------- -var user_name = analyzers.save("user_name", "ngram", { - "min": 3, - "max": 5, - "streamType": "utf8", - "preserveOriginal": true -}, ["frequency", "norm", "position"]); - -userview.properties({ - links: { - "u": { - fields: { - "name": { - analyzers: ["user_name"] - } +var user_name = analyzers.save( + "user_name", + "ngram", + { + min: 3, + max: 5, + streamType: "utf8", + preserveOriginal: true, + }, + ["frequency", "norm", "position"], +); + +userview.properties( + { + links: { + u: { + fields: { + name: { + analyzers: ["user_name"], + }, + }, + includeAllFields: false, }, - includeAllFields: false - } - } -}, true); + }, + }, + true, +); // ---------- Tag name indexing (view) ---------- -var tag_name = analyzers.save("tag_name", "ngram", { - "min": 3, - "max": 5, - "streamType": "utf8", - "preserveOriginal": true -}, ["frequency", "norm", "position"]); +var tag_name = analyzers.save( + "tag_name", + "ngram", + { + min: 3, + max: 5, + streamType: "utf8", + preserveOriginal: true, + }, + ["frequency", "norm", "position"], +); var tagview = db._createView("tagview", "arangosearch", {}); -tagview.properties({ - links: { - "tag": { - fields: { - "_key": { - analyzers: ["tag_name"] - } +tagview.properties( + { + links: { + tag: { + fields: { + _key: { + analyzers: ["tag_name"], + }, + }, + includeAllFields: false, }, - includeAllFields: false - } - } -}, true); + }, + }, + true, +); // ---------- Schema indexing (view) ---------- -var sch_id = analyzers.save("sch_id", "ngram", { - "min": 3, - "max": 5, - "streamType": "utf8", - "preserveOriginal": true -}, ["frequency", "norm", "position"]); +var sch_id = analyzers.save( + "sch_id", + "ngram", + { + min: 3, + max: 5, + streamType: "utf8", + preserveOriginal: true, + }, + ["frequency", "norm", "position"], +); var schemaview = db._createView("schemaview", "arangosearch", {}); -schemaview.properties({ - links: { - "sch": { - fields: { - "pub": { - analyzers: ["identity"] - }, - "id": { - analyzers: ["sch_id", "identity"] - }, - "desc": { - analyzers: ["text_en"] - }, - "own_id": { - analyzers: ["identity"] +schemaview.properties( + { + links: { + sch: { + fields: { + pub: { + analyzers: ["identity"], + }, + id: { + analyzers: ["sch_id", "identity"], + }, + desc: { + analyzers: ["text_en"], + }, + own_id: { + analyzers: ["identity"], + }, + own_nm: { + analyzers: ["user_name", "identity"], + }, }, - "own_nm": { - analyzers: ["user_name", "identity"] - } + includeAllFields: false, }, - includeAllFields: false - } - } -}, true); + }, + }, + true, +); // ---------- Data indexing (view) ---------- var view = db._createView("dataview", "arangosearch", {}); -view.properties({ +view.properties( + { links: { - "d": { + d: { fields: { - "public": { - analyzers: ["identity"] + public: { + analyzers: ["identity"], + }, + cat_tags: { + analyzers: ["identity"], }, - "cat_tags": { - analyzers: ["identity"] + tags: { + analyzers: ["identity"], }, - "tags": { - analyzers: ["identity"] + title: { + analyzers: ["text_en"], }, - "title": { - analyzers: ["text_en"] + desc: { + analyzers: ["text_en"], }, - "desc": { - analyzers: ["text_en"] + sch_id: { + analyzers: ["identity"], }, - "sch_id": { - analyzers: ["identity"] + md_err: { + analyzers: ["identity"], }, - "md_err": { - analyzers: ["identity"] + owner: { + analyzers: ["identity"], }, - "owner": { - analyzers: ["identity"] + creator: { + analyzers: ["identity"], }, - "creator": { - analyzers: ["identity"] + ut: { + analyzers: ["identity"], }, - "ut": { - analyzers: ["identity"] + alias: { + analyzers: ["identity"], }, - "alias": { - analyzers: ["identity"] + _id: { + analyzers: ["identity"], }, - "_id": { - analyzers: ["identity"] - } }, - includeAllFields: false - } + includeAllFields: false, + }, }, - primarySort: [{ - field: "title", - direction: "asc" - }] + primarySort: [ + { + field: "title", + direction: "asc", + }, + ], }, - true + true, ); // ---------- Collection indexing (view) ---------- view = db._createView("collview", "arangosearch", {}); -view.properties({ +view.properties( + { links: { - "c": { + c: { fields: { - "public": { - analyzers: ["identity"] + public: { + analyzers: ["identity"], + }, + cat_tags: { + analyzers: ["identity"], }, - "cat_tags": { - analyzers: ["identity"] + tags: { + analyzers: ["identity"], }, - "tags": { - analyzers: ["identity"] + title: { + analyzers: ["text_en"], }, - "title": { - analyzers: ["text_en"] + desc: { + analyzers: ["text_en"], }, - "desc": { - analyzers: ["text_en"] + owner: { + analyzers: ["identity"], }, - "owner": { - analyzers: ["identity"] + creator: { + analyzers: ["identity"], }, - "creator": { - analyzers: ["identity"] + ut: { + analyzers: ["identity"], }, - "ut": { - analyzers: ["identity"] + alias: { + analyzers: ["identity"], }, - "alias": { - analyzers: ["identity"] + _id: { + analyzers: ["identity"], }, - "_id": { - analyzers: ["identity"] - } }, - includeAllFields: false - } + includeAllFields: false, + }, }, - primarySort: [{ - field: "title", - direction: "asc" - }] + primarySort: [ + { + field: "title", + direction: "asc", + }, + ], }, - true + true, ); // ---------- Project indexing (view) ---------- view = db._createView("projview", "arangosearch", {}); -view.properties({ +view.properties( + { links: { - "p": { + p: { fields: { - "title": { - analyzers: ["text_en"] + title: { + analyzers: ["text_en"], + }, + desc: { + analyzers: ["text_en"], }, - "desc": { - analyzers: ["text_en"] - } }, - includeAllFields: false - } - } + includeAllFields: false, + }, + }, }, - true + true, ); view = db._createView("topicview", "arangosearch", {}); -view.properties({ +view.properties( + { links: { - "t": { + t: { fields: { - "title": { - analyzers: ["text_en"] - } + title: { + analyzers: ["text_en"], + }, }, - includeAllFields: false - } - } + includeAllFields: false, + }, + }, }, - true + true, ); // ---------- Individual field indexing ---------- @@ -321,19 +352,19 @@ db.task.ensureIndex({ type: "hash", unique: false, fields: ["client"], - sparse: true + sparse: true, }); db.task.ensureIndex({ type: "skiplist", unique: false, fields: ["status"], - sparse: true + sparse: true, }); db.task.ensureIndex({ type: "hash", unique: false, fields: ["servers[*]"], - sparse: true + sparse: true, }); /*db.d.ensureIndex({ type: "hash", unique: false, fields: [ "public" ], sparse: true });*/ @@ -341,68 +372,68 @@ db.d.ensureIndex({ type: "hash", unique: false, fields: ["doi"], - sparse: true + sparse: true, }); db.d.ensureIndex({ type: "persistent", unique: false, - fields: ["tags[*]"] + fields: ["tags[*]"], }); db.c.ensureIndex({ type: "persistent", unique: false, fields: ["public"], - sparse: true + sparse: true, }); db.c.ensureIndex({ type: "persistent", unique: false, - fields: ["tags[*]"] + fields: ["tags[*]"], }); db.u.ensureIndex({ type: "hash", unique: true, fields: ["pub_key"], - sparse: true + sparse: true, }); db.u.ensureIndex({ type: "hash", unique: true, fields: ["access"], - sparse: true + sparse: true, }); db.g.ensureIndex({ type: "hash", unique: true, - fields: ["uid", "gid"] + fields: ["uid", "gid"], }); db.loc.ensureIndex({ type: "hash", unique: false, fields: ["uid"], - sparse: true + sparse: true, }); db.dep.ensureIndex({ type: "hash", unique: false, fields: ["type"], - sparse: true + sparse: true, }); db.tag.ensureIndex({ type: "persistent", unique: false, fields: ["count"], - sparse: true + sparse: true, }); db.t.ensureIndex({ type: "persistent", unique: false, fields: ["top"], - sparse: true + sparse: true, }); //db.sch.ensureIndex({ type: "hash", unique: true, fields: [ "id" ], sparse: false }); @@ -410,12 +441,12 @@ db.sch.ensureIndex({ type: "hash", unique: true, fields: ["id", "ver"], - sparse: false + sparse: false, }); db.metrics.ensureIndex({ type: "persistent", unique: false, fields: ["timestamp", "type", "uid"], - sparse: true + sparse: true, }); diff --git a/core/database/foxx/db_migrate_0_10.js b/core/database/foxx/db_migrate_0_10.js index 35bf3cbe2..216b24c18 100644 --- a/core/database/foxx/db_migrate_0_10.js +++ b/core/database/foxx/db_migrate_0_10.js @@ -1,4 +1,8 @@ -db._useDatabase('sdms'); +db._useDatabase("sdms"); -db._query("for i in alloc update i with { data_limit: i.max_size, data_size: i.tot_size, rec_limit: i.max_count, rec_count: i.tot_count } in alloc"); -db._query("for i in alloc update i with { max_count: null, max_size: null, tot_size: null, tot_count: null } in alloc options { keepNull:false }"); \ No newline at end of file +db._query( + "for i in alloc update i with { data_limit: i.max_size, data_size: i.tot_size, rec_limit: i.max_count, rec_count: i.tot_count } in alloc", +); +db._query( + "for i in alloc update i with { max_count: null, max_size: null, tot_size: null, tot_count: null } in alloc options { keepNull:false }", +); diff --git a/core/database/foxx/index.js b/core/database/foxx/index.js index 1bfe3bb57..38c8b794e 100644 --- a/core/database/foxx/index.js +++ b/core/database/foxx/index.js @@ -1,29 +1,29 @@ -'use strict'; +"use strict"; require("@arangodb/aql/cache").properties({ - mode: "demand" + mode: "demand", }); -const createRouter = require('@arangodb/foxx/router'); +const createRouter = require("@arangodb/foxx/router"); const router = createRouter(); -router.use("/usr", require('./api/user_router')); -router.use("/prj", require('./api/proj_router')); -router.use("/grp", require('./api/group_router')); -router.use("/dat", require('./api/data_router')); -router.use("/col", require('./api/coll_router')); -router.use("/acl", require('./api/acl_router')); -router.use("/qry", require('./api/query_router')); -router.use("/topic", require('./api/topic_router')); -router.use("/tag", require('./api/tag_router')); -router.use("/note", require('./api/note_router')); -router.use("/authz", require('./api/authz_router')); -router.use("/repo", require('./api/repo_router')); -router.use("/task", require('./api/task_router')); -router.use("/schema", require('./api/schema_router')); -router.use("/config", require('./api/config_router')); -router.use("/metrics", require('./api/metrics_router')); -router.use("/admin", require('./api/admin_router')); -router.use("/", require('./api/version_router')); +router.use("/usr", require("./api/user_router")); +router.use("/prj", require("./api/proj_router")); +router.use("/grp", require("./api/group_router")); +router.use("/dat", require("./api/data_router")); +router.use("/col", require("./api/coll_router")); +router.use("/acl", require("./api/acl_router")); +router.use("/qry", require("./api/query_router")); +router.use("/topic", require("./api/topic_router")); +router.use("/tag", require("./api/tag_router")); +router.use("/note", require("./api/note_router")); +router.use("/authz", require("./api/authz_router")); +router.use("/repo", require("./api/repo_router")); +router.use("/task", require("./api/task_router")); +router.use("/schema", require("./api/schema_router")); +router.use("/config", require("./api/config_router")); +router.use("/metrics", require("./api/metrics_router")); +router.use("/admin", require("./api/admin_router")); +router.use("/", require("./api/version_router")); -module.context.use(router); \ No newline at end of file +module.context.use(router); diff --git a/core/database/foxx/manifest.json.in b/core/database/foxx/manifest.json.in index cd9956eeb..8b7c3bef3 100644 --- a/core/database/foxx/manifest.json.in +++ b/core/database/foxx/manifest.json.in @@ -6,5 +6,10 @@ "name": "DataFed", "description": "DataFed ArangoDB Microservices API", "version": "@DATAFED_FOXX_API_MAJOR@.@DATAFED_FOXX_API_MINOR@.@DATAFED_FOXX_API_PATCH@", - "tests": "tests/**/*.js" + "tests": "tests/**/*.js", + "scripts": { + "user-fixture": "tests/user_fixture.js", + "collection-fixture": "tests/globus_collection_fixture.js", + "globus-token-fixture": "tests/globus_token_fixture.js" + } } diff --git a/core/database/foxx/tests/authz.test.js b/core/database/foxx/tests/authz.test.js new file mode 100644 index 000000000..d9976a2c9 --- /dev/null +++ b/core/database/foxx/tests/authz.test.js @@ -0,0 +1,361 @@ +"use strict"; +const chai = require("chai"); +const expect = chai.expect; +const authzModule = require("../api/authz"); +const g_db = require("@arangodb").db; +const g_lib = require("../api/support"); +const arangodb = require("@arangodb"); + +describe("Authz functions", () => { + beforeEach(() => { + g_db.d.truncate(); + g_db.alloc.truncate(); + g_db.loc.truncate(); + g_db.repo.truncate(); + g_db.u.truncate(); + g_db.owner.truncate(); + g_db.p.truncate(); + g_db.admin.truncate(); + }); + + describe("unit_authz: if a user is an admin 'bob' they should have authorization on not_bob's record", () => { + it("unit_authz: should return true", () => { + let data_key = "big_data_obj"; + let data_id = "d/" + data_key; + + g_db.d.save({ + _key: data_key, + _id: data_id, + creator: "u/george", + }); + + let owner_id = "u/not_bob"; + g_db.u.save({ + _key: "not_bob", + _id: owner_id, + is_admin: false, + }); + + let client = { + _key: "bob", + _id: "u/bob", + is_admin: true, + }; + + g_db.u.save(client); + + g_db.owner.save({ + _from: data_id, + _to: owner_id, + }); + + let req_perm = g_lib.PERM_CREATE; + + expect(authzModule.isRecordActionAuthorized(client, data_key, req_perm)).to.be.true; + }); + }); + + describe("unit_authz: if a record is part of George's user allocation a non owning regular user 'bob' should not have access to the record", () => { + it("unit_authz: should thrown an error if bob tries to run a create request on the record.", () => { + let data_key = "data_key"; + let data_id = "d/" + data_key; + + g_db.d.save({ + _key: data_key, + _id: data_id, + creator: "u/george", + }); + + let client = { + _key: "bob", + _id: "u/bob", + is_admin: false, + }; + + g_db.u.save(client); + + let req_perm = g_lib.PERM_CREATE; + + expect(() => + authzModule.isRecordActionAuthorized(client, data_key, req_perm), + ).to.throw(); + }); + }); + + describe("unit_authz: a user 'george' who is an owner of a record should have authorization on the record.", () => { + it("unit_authz: should return true.", () => { + let data_key = "data_key"; + let data_id = "d/" + data_key; + + g_db.d.save({ + _key: data_key, + _id: data_id, + creator: "u/george", + }); + + let client = { + _key: "george", + _id: "u/george", + is_admin: false, + }; + + g_db.u.save(client); + + g_db.owner.save({ + _from: data_id, + _to: "u/george", + }); + + let req_perm = g_lib.PERM_CREATE; + + expect(authzModule.isRecordActionAuthorized(client, data_key, req_perm)).to.be.true; + }); + }); + + describe("unit_authz: a user 'bob' who is an admin of a project should have authorization on a record in the project.", () => { + it("unit_authz: should return true", () => { + let data_key = "project_data_obj"; + let data_id = "d/" + data_key; + + g_db.d.save({ + _key: data_key, + _id: data_id, + creator: "u/george", + }); + + let project_id = "p/project_1"; + g_db.p.save({ + _key: "project_1", + _id: project_id, + name: "Project One", + }); + + let bob_id = "u/bob"; + + let bob = { + _key: "bob", + _id: bob_id, + is_admin: false, + }; + + let george = { + _key: "george", + _id: "u/george", + is_admin: false, + }; + + g_db.u.save(bob); + g_db.u.save(george); + + g_db.owner.save({ + _from: data_id, + _to: project_id, + }); + + g_db.admin.save({ + _from: project_id, + _to: bob_id, + }); + let req_perm = g_lib.PERM_CREATE; + + expect(authzModule.isRecordActionAuthorized(bob, data_key, req_perm)).to.be.true; + }); + }); + + describe("unit_authz: non-owner 'bob' should be denied access to another user's 'george' record.", () => { + it("unit_authz: should return false", () => { + let data_key = "bananas"; + let data_id = "d/" + data_key; + + g_db.d.save( + { + _key: data_key, + _id: data_id, + creator: "u/george", + }, + { waitForSync: true }, + ); + + let bob = { + _key: "bob", + _id: "u/bob", + is_admin: false, + }; + + let george = { + _key: "george", + _id: "u/george", + is_admin: false, + }; + + g_db.u.save(bob, { waitForSync: true }); + g_db.u.save(george, { waitForSync: true }); + + g_db.owner.save( + { + _from: data_id, + _to: "u/george", + }, + { waitForSync: true }, + ); + let req_perm = g_lib.PERM_CREATE; + + expect(authzModule.isRecordActionAuthorized(bob, data_key, req_perm)).to.be.false; + }); + }); + + describe("unit_authz: 'Jack' is a creator of the an 'apples' document in the 'fruity' project, 'Mandy' is the admin of the 'condiments' project, 'Mandy' should not have access to the 'apples' document.", () => { + it("unit_authz: should return false.", () => { + let data_key = "apples"; + let data_id = "d/" + data_key; + + g_db.d.save( + { + _key: data_key, + _id: data_id, + creator: "u/jack", + }, + { waitForSync: true }, + ); + + let jack = { + _key: "jack", + _id: "u/jack", + is_admin: false, + }; + + g_db.u.save(jack, { waitForSync: true }); + + let fruity_project_id = "p/fruity"; + g_db.p.save( + { + _key: "fruity", + _id: fruity_project_id, + name: "Project Fruity", + }, + { waitForSync: true }, + ); + + let condiments_project_id = "p/condiments"; + g_db.p.save( + { + _key: "condiments", + _id: condiments_project_id, + name: "Project Condiments", + }, + { waitForSync: true }, + ); + + let mandy_admin_id = "u/mandy"; + let mandy = { + _key: "mandy", + _id: mandy_admin_id, + is_admin: false, + }; + g_db.u.save(mandy, { waitForSync: true }); + + let amy_admin_id = "u/amy"; + g_db.u.save( + { + _key: "amy", + _id: amy_admin_id, + is_admin: false, + }, + { waitForSync: true }, + ); + + g_db.owner.save( + { + _from: data_id, + _to: fruity_project_id, + }, + { waitForSync: true }, + ); + + g_db.admin.save( + { + _from: fruity_project_id, + _to: amy_admin_id, + }, + { waitForSync: true }, + ); + + g_db.admin.save( + { + _from: condiments_project_id, + _to: mandy_admin_id, + }, + { waitForSync: true }, + ); + let req_perm = g_lib.PERM_CREATE; + + // Non-project admin should not have permission + expect(authzModule.isRecordActionAuthorized(mandy, data_key, req_perm)).to.be.false; + }); + }); + + describe("unit_authz: 'Tim' is the creator of a record 'cherry', but the 'cherry' record has been moved to a different project 'red_fruit' that 'Tim' does not have access to.", () => { + it("unit_authz: should return false.", () => { + let data_key = "cherry"; + let data_id = "d/" + data_key; + + g_db.d.save( + { + _key: data_key, + _id: data_id, + creator: "tim", + }, + { waitForSync: true }, + ); + + let tim = { + _key: "tim", + _id: "u/tim", + is_admin: false, + }; + + // A project is the owner + let project_id = "p/red_fruit"; + g_db.p.save( + { + _key: "red_fruit", + _id: project_id, + name: "Project Red Fruit", + }, + { waitForSync: true }, + ); + + let bob_id = "u/bob"; + + let bob = { + _key: "bob", + _id: bob_id, + is_admin: false, + }; + + g_db.u.save(bob, { waitForSync: true }); + + g_db.owner.save( + { + _from: data_id, + _to: project_id, + }, + { waitForSync: true }, + ); + + g_db.admin.save( + { + _from: project_id, + _to: bob_id, + }, + { waitForSync: true }, + ); + + g_db.u.save(tim, { waitForSync: true }); + + let req_perm = g_lib.PERM_READ; + + expect(authzModule.isRecordActionAuthorized(tim, data_key, req_perm)).to.be.false; + }); + }); +}); diff --git a/core/database/foxx/tests/authz_router.test.js b/core/database/foxx/tests/authz_router.test.js new file mode 100644 index 000000000..53ec97d26 --- /dev/null +++ b/core/database/foxx/tests/authz_router.test.js @@ -0,0 +1,338 @@ +"use strict"; + +// Integration test of API +const { expect } = require("chai"); +const request = require("@arangodb/request"); +const { baseUrl } = module.context; +const g_db = require("@arangodb").db; +const g_lib = require("../api/support"); + +// Constants used throughout test file +// The base URL for the authz foxx route +const authz_base_url = `${baseUrl}/authz`; +// Current time used for updating documents in the database +const current_time = Math.floor(Date.now() / 1000); +// Test user information +const james_uuid = "XXXXYYYY-XXXX-YYYY-XXXX-YYYYXXXXYYYY"; +const james_uuid_id = "uuid/" + james_uuid; +const james_key = "jamesw"; +const james_id = "u/" + james_key; +const base_user_data = { + _key: james_key, + _id: james_id, + name_first: "james", + name_last: "whiticker", + is_admin: true, + max_coll: g_lib.DEF_MAX_COLL, + max_proj: g_lib.DEF_MAX_PROJ, + max_sav_qry: g_lib.DEF_MAX_SAV_QRY, + ct: current_time, + ut: current_time, +}; + +// Test record information +const valid_key = "1120"; +const record_id = "d/" + valid_key; + +// Test repo information +const repo_key = "datafed-at-hot-potato"; +const repo_id = "repo/" + repo_key; +const repo_path = "/mnt/repo_name"; +const file_path = repo_path + "/user/" + james_key + "/" + valid_key; + +// Test Project information +const project_key = "physics"; +const project_id = "p/" + project_key; +const project_file_path = repo_path + "/project/" + project_key + "/" + valid_key; + +/** + * This method sets up the database with the documents for a user with a data record + * + * Creates a user, creates a repository and adds an allocation that connects the user + * to the repository. A record is also created and is connected to the repository + * via a location connection. + **/ +function defaultWorkingSetup() { + g_db.uuid.save({ + _id: james_uuid_id, + }); + + g_db.ident.save({ + _from: james_id, + _to: james_uuid_id, + }); + + const repo_data = { + _key: repo_key, + path: repo_path, + }; + // Create nodes + //recordRepoAndUserSetup(valid_key, base_user_data, repo_data); + + g_db.d.save({ + _key: valid_key, + owner: james_id, + }); + g_db.repo.save(repo_data, { waitForSync: true }); + + g_db.u.save(base_user_data); + + // Create edges + g_db.loc.save({ + _from: record_id, + _to: repo_id, + uid: james_id, + new_repo: null, + }); + + g_db.alloc.save({ + _from: james_id, + _to: repo_id, + }); +} + +/** + * This method sets up the database with the documents for a project owned data record + * + * The following items are needed for this. + * A user + * A record + * A project + * A group + * A collection + * A owner + * A repo + * + * These different documents are connected through edges. + * record <-> item <-> collection + * record <-> owner <-> project + * record <-> loc <-> repo + * uuid <-> ident <-> user + * group <-> acl <-> collection + * user <-> member <-> group + * project <-> alloc <-> repo + * project <-> owner <-> group + **/ +function defaultWorkingSetupProject() { + // Create nodes + g_db.uuid.save({ + _id: james_uuid_id, + }); + + g_db.u.save(base_user_data); + + g_db.p.save({ + _key: project_key, + }); + + const root = g_db.c.save( + { + _key: "p_" + project_key + "_root", + is_root: true, + owner: project_id, + acls: 2, + }, + { + returnNew: true, + }, + ); + + const mem_grp = g_db.g.save( + { + uid: "p/" + project_key, + gid: "members", + }, + { + returnNew: true, + }, + ); + + g_db.d.save({ + _key: valid_key, + owner: project_id, + }); + + const repo_data = { + _key: repo_key, + path: repo_path, + }; + g_db.repo.save(repo_data, { waitForSync: true }); + + // Create edges + g_db.item.save({ + _from: root._id, + _to: record_id, + }); + + g_db.acl.save({ + _from: root._id, + _to: mem_grp._id, + grant: g_lib.PERM_MEMBER, + inhgrant: g_lib.PERM_MEMBER, + }); + + g_db.loc.save({ + _from: record_id, + _to: repo_id, + uid: project_id, + new_repo: null, + }); + + g_db.alloc.save({ + _from: project_id, + _to: repo_id, + }); + + g_db.member.save({ + _from: mem_grp._id, + _to: james_id, + }); + + g_db.ident.save({ + _from: james_id, + _to: james_uuid_id, + }); + + g_db.owner.save({ + _from: record_id, + _to: project_id, + }); +} + +// NOTE: describe block strings are compared against test specification during test call, not file name +describe("unit_authz_router: the Foxx microservice authz_router", () => { + beforeEach(() => { + g_db.u.truncate(); + g_db.ident.truncate(); + g_db.uuid.truncate(); + g_db.acl.truncate(); + g_db.item.truncate(); + g_db.c.truncate(); + g_db.g.truncate(); + g_db.p.truncate(); + g_db.owner.truncate(); + g_db.member.truncate(); + g_db.d.truncate(); + g_db.alloc.truncate(); + g_db.loc.truncate(); + g_db.repo.truncate(); + }); + + it("unit_authz_router: gridftp create action with user record and valid file path.", () => { + defaultWorkingSetup(); + const request_string = + `${authz_base_url}/gridftp?client=` + + james_uuid + + `&repo=` + + encodeURIComponent(repo_id) + + `&file=` + + encodeURIComponent(file_path) + + `&act=create`; + + // act + const response = request.get(request_string); + + // assert + expect(response.status).to.equal(204); + }); + + it("unit_authz_router: gridftp create action with user record and invalid file path.", () => { + defaultWorkingSetup(); + + // This is invalid because bobby does not exist as a user and the record "valid_key" they are not the owner of or have a membership too. + const bad_file_path = repo_path + "/user/bobby/" + valid_key; + const request_string = + `${authz_base_url}/gridftp?client=` + + james_uuid + + `&repo=` + + encodeURIComponent(repo_id) + + `&file=` + + encodeURIComponent(bad_file_path) + + `&act=create`; + + // act + const response = request.get(request_string); + + // assert + expect(response.status).to.equal(400); + }); + + it("unit_authz_router: gridftp create action with invalid repo and valid file path.", () => { + defaultWorkingSetup(); + const bad_repo_id = "repo/not_exist"; + const request_string = + `${authz_base_url}/gridftp?client=` + + james_uuid + + `&repo=` + + encodeURIComponent(bad_repo_id) + + `&file=` + + encodeURIComponent(file_path) + + `&act=create`; + + // act + const response = request.get(request_string); + + // assert + expect(response.status).to.equal(400); + }); + + it("unit_authz_router: gridftp create action with invalid client and valid file path.", () => { + // Here we are creating a valid user but they simply do not have access to the provided file + // path. + const bad_user_data = { + _key: "george", + _id: "u/george", + name_first: "george", + name_last: "Brown", + is_admin: false, + }; + const george_uuid = "ZZZZYYYY-ZZZZ-ZZZZ-ZZZZ-ZZZZTTTTZZZZ"; + const george_uuid_id = "uuid/" + george_uuid; + g_db.u.save(bad_user_data); + + g_db.uuid.save({ + _id: george_uuid_id, + }); + + g_db.ident.save({ + _from: "u/george", + _to: george_uuid_id, + }); + + defaultWorkingSetup(); + const bad_repo_id = "repo/not_exist"; + const request_string = + `${authz_base_url}/gridftp?client=` + + george_uuid + + `&repo=` + + encodeURIComponent(repo_id) + + `&file=` + + encodeURIComponent(file_path) + + `&act=create`; + + // act + const response = request.get(request_string); + + // assert + expect(response.status).to.equal(400); + }); + + it("unit_authz_router: gridftp create action with valid repo and valid file path in project.", () => { + defaultWorkingSetupProject(); + const bad_repo_id = "repo/not_exist"; + const request_string = + `${authz_base_url}/gridftp?client=` + + james_uuid + + `&repo=` + + encodeURIComponent(repo_id) + + `&file=` + + encodeURIComponent(project_file_path) + + `&act=create`; + + // act + const response = request.get(request_string); + + // assert + expect(response.status).to.equal(204); + }); +}); diff --git a/core/database/foxx/tests/globus_collection_fixture.js b/core/database/foxx/tests/globus_collection_fixture.js new file mode 100644 index 000000000..f5ce9b92e --- /dev/null +++ b/core/database/foxx/tests/globus_collection_fixture.js @@ -0,0 +1,39 @@ +"use strict"; + +const { db } = require("@arangodb"); + +const current_time = Math.floor(Date.now() / 1000); +const collection_no_token_uuid = "94445318-2097-4ed8-8550-f73cd292b11f"; +const get_globus_token_model_collection = "a1067823-2598-4481-be95-712794ddd9e8"; +const globus_collection_token_collection = "126a23d4-45ed-49fb-bde2-76b5f44d20d1"; +const collection_key_list = [ + collection_no_token_uuid, + get_globus_token_model_collection, + globus_collection_token_collection, +]; +const end_collection_key = collection_key_list.at(-1); +const base_globus_collection_data = { + name: "Test fixture collection", + description: "Test fixture collection description", + required_scopes: "test::globus::transfer::scopes", + owner: "", + ct: current_time, + ut: current_time, + type: "mapped", + ha_enabled: false, +}; + +if (!db._collection("globus_coll")) { + throw "This collection - globus_coll - does not exist"; +} else if (!db.globus_coll.exists(end_collection_key)) { + collection_key_list.map((collection_key, idx) => { + if (!db.globus_coll.exists(collection_key)) { + const globus_collection_data = { + _key: collection_key, + ...base_globus_collection_data, + }; + + db.globus_coll.save(globus_collection_data); + } + }); +} diff --git a/core/database/foxx/tests/globus_collection_model.test.js b/core/database/foxx/tests/globus_collection_model.test.js new file mode 100644 index 000000000..4c185fa54 --- /dev/null +++ b/core/database/foxx/tests/globus_collection_model.test.js @@ -0,0 +1,71 @@ +"use strict"; + +const { GlobusCollectionModel, GlobusCollection } = require("../api/models/globus_collection"); + +const { expect } = require("chai"); +const { db } = require("@arangodb"); + +const collection_no_token_uuid = "94445318-2097-4ed8-8550-f73cd292b11f"; // fake collection UUID from fixture file +const fake_uuid = "d5a58070-33e2-4841-80c5-7722a749f8e2"; // some fake uuid + +describe("unit_globus_collection_model: calling constructor", () => { + it("should create a collection model object when passed a collection id", () => { + const globus_collection_model = new GlobusCollectionModel(collection_no_token_uuid); + expect(globus_collection_model).to.be.instanceOf(GlobusCollectionModel); + }); + it("should throw an error when not passed a collection id", () => { + expect(() => new GlobusCollectionModel()).to.throw( + "A Globus Collection ID must be provided", + ); + }); +}); + +describe("unit_globus_collection_model: calling exists", () => { + it("should return true when collection exists on DB", () => { + const globus_collection_exists = new GlobusCollectionModel( + collection_no_token_uuid, + ).exists(); + expect(globus_collection_exists).to.be.true; + }); + it("should return false when collection does not exist on DB", () => { + const globus_collection_exists = new GlobusCollectionModel(fake_uuid).exists(); + expect(globus_collection_exists).to.be.false; + }); +}); + +describe("unit_globus_collection_model: calling get", () => { + let globus_collection_db; + before(() => { + // TODO: abstract DB calls + globus_collection_db = Object.freeze( + db.globus_coll.document({ _key: collection_no_token_uuid }), + ); + }); + it("should return a read only globus collection object when the collection exists", () => { + const globus_collection = new GlobusCollectionModel(collection_no_token_uuid).get(); + + expect(globus_collection).to.be.instanceOf(GlobusCollection); + expect(globus_collection).to.be.frozen; + expect(globus_collection).to.include({ + id: globus_collection_db._id, + key: globus_collection_db._key, + name: globus_collection_db.name, + description: globus_collection_db.description, + required_scopes: globus_collection_db.required_scopes, + owner: globus_collection_db.owner, + creation_time: globus_collection_db.ct, + update_time: globus_collection_db.ut, + type: globus_collection_db.type, + ha_enabled: globus_collection_db.ha_enabled, + }); + }); + it("should return a read only empty globus collection object with all fields undefined when the collection does not exist", () => { + const globus_collection = new GlobusCollectionModel(fake_uuid).get(); + + expect(globus_collection).to.be.instanceOf(GlobusCollection); + expect(globus_collection).to.be.frozen; + Object.keys(GlobusCollection).map((key) => { + expect(globus_collection).to.have.property(key, undefined); + }); + }); +}); diff --git a/core/database/foxx/tests/globus_token_fixture.js b/core/database/foxx/tests/globus_token_fixture.js new file mode 100644 index 000000000..bb7fc4d33 --- /dev/null +++ b/core/database/foxx/tests/globus_token_fixture.js @@ -0,0 +1,64 @@ +const g_lib = require("../api/support"); + +const { db } = require("@arangodb"); + +// from user fixture file +const get_globus_token_model_user = "getGlobusTokenModelUser"; +const get_globus_token_model_user_id = "u/" + get_globus_token_model_user; +const user_collection_token_user = "userCollectionTokenUser"; + +// from globus collection fixture file +const get_globus_token_model_collection = "a1067823-2598-4481-be95-712794ddd9e8"; +const get_globus_token_model_collection_id = "globus_coll/" + get_globus_token_model_collection; +const globus_collection_token_collection = "126a23d4-45ed-49fb-bde2-76b5f44d20d1"; + +const current_time = Math.floor(Date.now() / 1000); +const globus_token_list = [ + { + user_id: get_globus_token_model_user_id, + collection_id: get_globus_token_model_collection_id, + key: + get_globus_token_model_collection + + "_" + + g_lib.AccessTokenType.GLOBUS_TRANSFER + + "_" + + get_globus_token_model_user, + }, + { + user_id: "u/" + user_collection_token_user, + collection_id: "globus_coll/" + globus_collection_token_collection, + key: + globus_collection_token_collection + + "_" + + g_lib.AccessTokenType.GLOBUS_TRANSFER + + "_" + + user_collection_token_user, + }, +]; +const end_globus_token_key = globus_token_list.at(-1).key; +const base_globus_token_data = { + type: g_lib.AccessTokenType.GLOBUS_TRANSFER, + dependent_scopes: "some fake scopes", + request_time: current_time, + last_used: current_time, + status: "active", + expiration: current_time + 123456789, +}; +if (!db._collection("globus_token")) { + throw "This collection - globus_token - does not exist"; +} else if (!db.globus_token.exists(end_globus_token_key)) { + globus_token_list.map((globus_token_info, idx) => { + if (!db.globus_token.exists(globus_token_info.key)) { + const globus_token_data = { + _key: globus_token_info.key, + _from: globus_token_info.user_id, + _to: globus_token_info.collection_id, + ...base_globus_token_data, + access: "globus token access for " + globus_token_info.key, + refresh: "globus token refresh for " + globus_token_info.key, + }; + + db.globus_token.save(globus_token_data); + } + }); +} diff --git a/core/database/foxx/tests/globus_token_model.test.js b/core/database/foxx/tests/globus_token_model.test.js new file mode 100644 index 000000000..d2e18d985 --- /dev/null +++ b/core/database/foxx/tests/globus_token_model.test.js @@ -0,0 +1,110 @@ +"use strict"; + +const { GlobusTokenModel, GlobusToken } = require("../api/models/globus_token"); + +const { expect } = require("chai"); +const { db } = require("@arangodb"); +const { DataFedOAuthToken } = require("../api/models/DataFedOAuthToken"); + +// from fixture +const get_globus_token_model_user = "getGlobusTokenModelUser"; +const get_globus_token_model_user_id = "u/" + get_globus_token_model_user; +const get_globus_token_model_collection = "a1067823-2598-4481-be95-712794ddd9e8"; +const get_globus_token_model_collection_id = "globus_coll/" + get_globus_token_model_collection; + +describe("unit_globus_token_model: Calling constructor", () => { + it("should succeed when provided a user ID and Globus collection ID", () => { + const globus_token_model = new GlobusTokenModel( + get_globus_token_model_user_id, + get_globus_token_model_collection_id, + ); + expect(globus_token_model).to.be.instanceOf(GlobusTokenModel); + }); + it("should throw an error when a user ID is not provided", () => { + expect(() => new GlobusTokenModel(null, get_globus_token_model_collection_id)).to.throw( + "User ID and Collection ID are required for Globus Tokens", + ); + }); + it("should throw an error when a collection ID is not provided", () => { + expect(() => new GlobusTokenModel(get_globus_token_model_user_id, null)).to.throw( + "User ID and Collection ID are required for Globus Tokens", + ); + }); + it("should throw an error when neither a user ID nor a collection ID are provided", () => { + expect(() => new GlobusTokenModel(null, null)).to.throw( + "User ID and Collection ID are required for Globus Tokens", + ); + }); +}); + +describe("unit_globus_token_model: Calling get", () => { + it("should return a read only globus token object when the globus token exists", () => { + const globus_token = new GlobusTokenModel( + get_globus_token_model_user_id, + get_globus_token_model_collection_id, + ).get(); + + // TODO: abstract DB layer + const globus_token_db = db.globus_token.document({ _key: globus_token.key }); + + expect(globus_token).to.be.instanceOf(GlobusToken); + expect(globus_token).to.be.frozen; + expect(globus_token).to.include({ + id: globus_token_db._id, + key: globus_token_db._key, + user_id: globus_token_db._from, + globus_collection_id: globus_token_db._to, + type: globus_token_db.type, + dependent_scopes: globus_token_db.dependent_scopes, + request_time: globus_token_db.request_time, + last_used_time: globus_token_db.last_used, + status: globus_token_db.status, + access: globus_token_db.access, + refresh: globus_token_db.refresh, + expiration: globus_token_db.expiration, + }); + }); + it("should return a read only empty globus token object with all fields undefined when the globus token does not exist", () => { + const globus_token = new GlobusTokenModel("u/user_dne", "globus_coll/coll_dne").get(); + + expect(globus_token).to.be.instanceOf(GlobusToken); + expect(globus_token).to.be.frozen; + Object.keys(GlobusToken).map((key) => { + expect(globus_token).to.have.property(key, undefined); + }); + }); +}); + +describe("unit_globus_token_model: Calling get_oauth_token", () => { + it("should return a read only DataFed OAuth token object when the globus token exists", () => { + const globus_oauth_token = new GlobusTokenModel( + get_globus_token_model_user_id, + get_globus_token_model_collection_id, + ).get_oauth_token(); + + const globus_token = new GlobusTokenModel( + get_globus_token_model_user_id, + get_globus_token_model_collection_id, + ).get(); + // TODO: abstract DB layer + const globus_token_db = db.globus_token.document({ _key: globus_token.key }); + + expect(globus_oauth_token).to.be.instanceOf(DataFedOAuthToken); + expect(globus_oauth_token).to.be.frozen; + Object.keys(DataFedOAuthToken).map((key) => { + expect(globus_oauth_token).to.have.property(key, globus_token_db[key]); + }); + }); + it("should return an empty read only DataFed OAuth token with all fields undefined object when the globus token does not exist", () => { + const globus_oauth_token = new GlobusTokenModel( + "u/user_dne", + "globus_coll/coll_dne", + ).get_oauth_token(); + + expect(globus_oauth_token).to.be.instanceOf(DataFedOAuthToken); + expect(globus_oauth_token).to.be.frozen; + Object.keys(DataFedOAuthToken).map((key) => { + expect(globus_oauth_token).to.have.property(key, undefined); + }); + }); +}); diff --git a/core/database/foxx/tests/path.test.js b/core/database/foxx/tests/path.test.js new file mode 100644 index 000000000..34633a8b1 --- /dev/null +++ b/core/database/foxx/tests/path.test.js @@ -0,0 +1,37 @@ +"use strict"; + +const chai = require("chai"); +const expect = chai.expect; +const pathModule = require("../api/posix_path"); // Replace with the actual file name + +describe("splitPOSIXPath", function () { + it("unit_path: splitPOSIXPath should split a simple POSIX path into components", function () { + const result = pathModule.splitPOSIXPath("/usr/local/bin/node"); + expect(result).to.deep.equal(["usr", "local", "bin", "node"]); + }); + + it("unit_path: splitPOSIXPath should handle root path and return an empty array", function () { + const result = pathModule.splitPOSIXPath("/"); + expect(result).to.deep.equal([]); + }); + + it("unit_path: splitPOSIXPath should handle paths with trailing slashes correctly", function () { + const result = pathModule.splitPOSIXPath("/usr/local/bin/"); + expect(result).to.deep.equal(["usr", "local", "bin"]); + }); + + it("unit_path: splitPOSIXPath should handle empty paths and throw an error", function () { + expect(() => pathModule.splitPOSIXPath("")).to.throw("Invalid POSIX path"); + }); + + it("unit_path: splitPOSIXPath should handle null or undefined paths and throw an error", function () { + expect(() => pathModule.splitPOSIXPath(null)).to.throw("Invalid POSIX path"); + expect(() => pathModule.splitPOSIXPath(undefined)).to.throw("Invalid POSIX path"); + }); + + it("unit_path: splitPOSIXPath should handle non-string inputs and throw an error", function () { + expect(() => pathModule.splitPOSIXPath(123)).to.throw("Invalid POSIX path"); + expect(() => pathModule.splitPOSIXPath({})).to.throw("Invalid POSIX path"); + expect(() => pathModule.splitPOSIXPath([])).to.throw("Invalid POSIX path"); + }); +}); diff --git a/core/database/foxx/tests/record.test.js b/core/database/foxx/tests/record.test.js new file mode 100644 index 000000000..ef88ee9c8 --- /dev/null +++ b/core/database/foxx/tests/record.test.js @@ -0,0 +1,318 @@ +"use strict"; + +const chai = require("chai"); +const expect = chai.expect; +const Record = require("../api/record"); +const g_db = require("@arangodb").db; +const g_lib = require("../api/support"); +const arangodb = require("@arangodb"); + +function recordRepoAndUserSetup(record_key, user_id, repo_data) { + const record_id = "d/" + record_key; + if (!g_db._exists(record_id)) { + g_db.d.save({ + _key: record_key, + _id: record_id, + }); + } + g_db.repo.save(repo_data); + + if (!g_db._exists(user_id)) { + g_db.u.save({ + _id: user_id, + }); + } +} + +describe("Record Class", () => { + beforeEach(() => { + g_db.d.truncate(); + g_db.alloc.truncate(); + g_db.loc.truncate(); + g_db.repo.truncate(); + }); + + it("unit_record: should initialize correctly and check record existence is invalid", () => { + const record = new Record("invalidKey"); + expect(record.exists()).to.be.false; + expect(record.key()).to.equal("invalidKey"); + expect(record.error()).to.equal(g_lib.ERR_NOT_FOUND); + expect(record.errorMessage()).to.equal("Invalid key: (invalidKey). No record found."); + }); + + it("unit_record: should initialize correctly and check record existence is valid", () => { + const valid_key = "1120"; + const key_id = "d/" + valid_key; + const owner_id = "u/bob"; + const repo_id = "repo/datafed-at-com"; + const repo_data = { + _key: "datafed-at-com", + }; + // Create nodes + recordRepoAndUserSetup(valid_key, owner_id, repo_data); + + // Create edges + g_db.loc.save({ + _from: key_id, + _to: repo_id, + uid: owner_id, + }); + g_db.alloc.save({ + _from: owner_id, + _to: repo_id, + }); + const record = new Record(valid_key); + expect(record.exists()).to.be.true; + expect(record.key()).to.equal(valid_key); + expect(record.error()).to.be.null; + expect(record.errorMessage()).to.be.null; + }); + + it("unit_record: isManaged should initialize correctly, but show a record as not managed.", () => { + const valid_key = "1121"; + const key_id = "d/" + valid_key; + const owner_id = "u/jim"; + const repo_id = "repo/datafed-at-org"; + // Create nodes + const repo_data = { + _key: "datafed-at-org", + }; + recordRepoAndUserSetup(valid_key, owner_id, repo_data); + + const record = new Record(valid_key); + expect(record.isManaged()).to.be.false; + expect(record.exists()).to.be.true; + expect(record.key()).to.equal(valid_key); + expect(record.error()).to.equal(g_lib.ERR_PERM_DENIED); + const pattern = /^Permission denied data is not managed by DataFed/; + expect(record.errorMessage()).to.match(pattern); + }); + + it("unit_record: isManaged should initialize correctly, but without an allocation so should return false", () => { + const valid_key = "1122"; + const key_id = "d/" + valid_key; + const owner_id = "u/tom"; + const repo_id = "repo/datafed-banana-com"; + // Create nodes + const repo_data = { + _key: "datafed-banana-com", + }; + recordRepoAndUserSetup(valid_key, owner_id, repo_data); + + // Create edges + g_db.loc.save({ + _from: key_id, + _to: repo_id, + uid: owner_id, + }); + + const record = new Record(valid_key); + expect(record.isManaged()).to.be.false; + expect(record.exists()).to.be.true; + expect(record.key()).to.equal(valid_key); + expect(record.error()).to.be.null; + }); + + it("unit_record: isManaged should initialize correctly, and with allocation show that record is managed.", () => { + const valid_key = "1123"; + const key_id = "d/" + valid_key; + const owner_id = "u/drake"; + const repo_id = "repo/datafed-best-com"; + // Create nodes + const repo_data = { + _key: "datafed-best-com", + }; + recordRepoAndUserSetup(valid_key, owner_id, repo_data); + + // Create edges + g_db.loc.save({ + _from: key_id, + _to: repo_id, + uid: owner_id, + }); + g_db.alloc.save({ + _from: owner_id, + _to: repo_id, + }); + + const record = new Record(valid_key); + expect(record.isManaged()).to.be.true; + expect(record.exists()).to.be.true; + expect(record.key()).to.equal(valid_key); + expect(record.error()).to.be.null; + }); + + it("unit_record: isPathConsistent should return false because it is not managed.", () => { + const valid_key = "1124"; + const key_id = "d/" + valid_key; + const owner_id = "u/carl"; + const repo_id = "repo/datafed-at-super"; + const repo_data = { + _id: repo_id, + _key: "datafed-at-super", + path: "/correct/file/path", + }; + // Create nodes + recordRepoAndUserSetup(valid_key, owner_id, repo_data); + + // Create edges + g_db.loc.save({ + _from: key_id, + _to: repo_id, + uid: owner_id, + }); + g_db.alloc.save({ + _from: owner_id, + _to: repo_id, + }); + + const record = new Record(valid_key); + expect(record.isPathConsistent("file/path/" + valid_key)).to.be.false; + }); + + it("unit_record: isPathConsistent should return false paths are not consistent.", () => { + const valid_key = "1125"; + const key_id = "d/" + valid_key; + const owner_id = "u/red"; + const repo_id = "repo/datafed-fine-com"; + // Create nodes + const repo_data = { + _key: "datafed-fine-com", + path: "/correct/file/path", + }; + recordRepoAndUserSetup(valid_key, owner_id, repo_data); + + // Create edges + g_db.loc.save({ + _from: key_id, + _to: repo_id, + uid: owner_id, + }); + g_db.alloc.save({ + _from: owner_id, + _to: repo_id, + }); + + const record = new Record(valid_key); + expect(record.isPathConsistent("/incorrect/file/path/" + valid_key)).to.be.false; + expect(record.error()).to.equal(g_lib.ERR_PERM_DENIED); + const pattern = /^Record path is not consistent/; + expect(record.errorMessage()).to.match(pattern); + }); + + it("unit_record: isPathConsistent should return true paths are consistent.", () => { + const valid_key = "1126"; + const key_id = "d/" + valid_key; + const owner_name = "karen"; + const owner_id = "u/" + owner_name; + const repo_id = "repo/datafed-cool-com"; + // Create nodes + const repo_data = { + _key: "datafed-cool-com", + path: "/correct/file/path", + }; + recordRepoAndUserSetup(valid_key, owner_id, repo_data); + + // Create edges + g_db.loc.save({ + _from: key_id, + _to: repo_id, + uid: owner_id, + }); + g_db.alloc.save({ + _from: owner_id, + _to: repo_id, + path: "/correct/file/path", + }); + + const record = new Record(valid_key); + expect(record.isPathConsistent("/correct/file/path/user/" + owner_name + "/" + valid_key)) + .to.be.true; + expect(record.error()).to.be.null; + expect(record.errorMessage()).to.be.null; + }); + + it("unit_record: isPathConsistent should return true, paths are inconsistent, but new path in new repo is valid.", () => { + const valid_key = "1127"; + const key_id = "d/" + valid_key; + const owner_id = "u/john"; + const repo_id = "repo/orange-at-com"; + const new_repo_id = "repo/watermelon-at-org"; + + // Create nodes + + const repo_data = { + _key: "orange-at-org", + path: "/old/file/path", + }; + const repo_data_new = { + _key: "watermelon-at-org", + path: "/correct/file/path", + }; + recordRepoAndUserSetup(valid_key, owner_id, repo_data); + recordRepoAndUserSetup(valid_key, owner_id, repo_data_new); + + // Create edges + g_db.loc.save({ + _from: key_id, + _to: repo_id, + uid: owner_id, + new_repo: new_repo_id, + }); + g_db.alloc.save({ + _from: owner_id, + _to: repo_id, + }); + g_db.alloc.save({ + _from: owner_id, + _to: new_repo_id, + }); + + const record = new Record(valid_key); + expect(record.isPathConsistent("/correct/file/path/user/john/" + valid_key)).to.be.true; + expect(record.error()).to.be.null; + expect(record.errorMessage()).to.be.null; + }); + + it("unit_record: isPathConsistent should return false paths are inconsistent in new and old repo.", () => { + const valid_key = "1128"; + const key_id = "d/" + valid_key; + const owner_id = "u/sherry"; + const repo_id = "repo/passionfruit"; + const new_repo_id = "repo/hamburger"; + // Create nodes + const repo_data = { + _key: "passionfruit", + path: "/old/file/path", + }; + const repo_data_new = { + _key: "hamburger", + path: "/new/file/path", + }; + recordRepoAndUserSetup(valid_key, owner_id, repo_data); + recordRepoAndUserSetup(valid_key, owner_id, repo_data_new); + + // Create edges + g_db.loc.save({ + _from: key_id, + _to: repo_id, + uid: owner_id, + new_repo: new_repo_id, + }); + g_db.alloc.save({ + _from: owner_id, + _to: repo_id, + }); + g_db.alloc.save({ + _from: owner_id, + _to: new_repo_id, + }); + + const record = new Record(valid_key); + expect(record.isPathConsistent("/incorrect/file/path/user/sherry/" + valid_key)).to.be + .false; + expect(record.error()).to.equal(g_lib.ERR_PERM_DENIED); + const pattern = /^Record path is not consistent/; + expect(record.errorMessage()).to.match(pattern); + }); +}); diff --git a/core/database/foxx/tests/repo.test.js b/core/database/foxx/tests/repo.test.js new file mode 100644 index 000000000..017f3aaa3 --- /dev/null +++ b/core/database/foxx/tests/repo.test.js @@ -0,0 +1,237 @@ +"use strict"; + +const chai = require("chai"); +const { expect } = chai; +const { Repo, PathType } = require("../api/repo"); +const g_db = require("@arangodb").db; +const g_lib = require("../api/support"); +const arangodb = require("@arangodb"); + +describe("Testing Repo class", () => { + beforeEach(() => { + g_db.d.truncate(); + g_db.alloc.truncate(); + g_db.loc.truncate(); + g_db.repo.truncate(); + }); + + it("unit_repo: should throw an error if the repo does not exist", () => { + const repo = new Repo("invalidKey"); + expect(repo.exists()).to.be.false; + expect(repo.key()).to.equal("invalidKey"); + expect(repo.error()).to.equal(g_lib.ERR_NOT_FOUND); + }); + + it("unit_repo: should return REPO_ROOT_PATH for exact match with repo root", () => { + const path = "/repo_root"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType(path)).to.equal(PathType.REPO_ROOT_PATH); + }); + + it("unit_repo: should return UNKNOWN for invalid path not matching repo root", () => { + const path = "/repo_root"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/invalid_path")).to.equal(PathType.UNKNOWN); + }); + + it("unit_repo: should return PROJECT_PATH for valid project paths", () => { + const path = "/repo_root"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/repo_root/project/bam")).to.equal(PathType.PROJECT_PATH); + }); + + it("unit_repo: should return USER_PATH for valid user paths", () => { + const path = "/repo_root"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/repo_root/user/george")).to.equal(PathType.USER_PATH); + }); + + it("unit_repo: should return UNKNOWN for a path that does not start with repo root", () => { + const path = "/repo_root"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/randome_string/user/george/id")).to.equal(PathType.UNKNOWN); + }); + + it("unit_repo: should trim trailing slashes from repo root path and input path", () => { + const path = "/repo_root"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/repo_root/user/")).to.equal(PathType.REPO_PATH); + }); + + it("unit_repo: should handle an empty relative path correctly", () => { + const path = "/repo_root"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/repo_root/")).to.equal(PathType.REPO_ROOT_PATH); + }); + + it("unit_repo: should handle an unknown path that begins with project", () => { + const path = "/repo_root"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/random_string/project_bam")).to.equal(PathType.UNKNOWN); + }); + + it("unit_repo: should handle an repo base path", () => { + const path = "/mnt/repo_root"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/mnt")).to.equal(PathType.REPO_BASE_PATH); + }); + + it("unit_repo: should handle an repo base path with ending /", () => { + const path = "/mnt/repo_root"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/mnt/")).to.equal(PathType.REPO_BASE_PATH); + }); + + it("unit_repo: should handle an repo base path containing only /", () => { + const path = "/mnt/repo_root"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/")).to.equal(PathType.REPO_BASE_PATH); + }); + + it("unit_repo: should handle an repo base path and repo root path are the same and only containing only /", () => { + const path = "/"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/")).to.equal(PathType.REPO_ROOT_PATH); + }); + + it("unit_repo: should handle an repo base path containing only part of base.", () => { + const path = "/mnt/repo_root"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/m")).to.equal(PathType.UNKNOWN); + }); + + it("unit_repo: should handle an repo root path containing only part of root.", () => { + const path = "/mnt/repo_root"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/mnt/re")).to.equal(PathType.UNKNOWN); + }); + + it("unit_repo: should handle an repo path containing only part of project.", () => { + const path = "/mnt/repo_root"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/mnt/repo_root/pro")).to.equal(PathType.UNKNOWN); + }); + + it("unit_repo: should handle an repo path containing only part of user.", () => { + const path = "/mnt/repo_root"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/mnt/repo_root/us")).to.equal(PathType.UNKNOWN); + }); + + it("unit_repo: should handle a project record path.", () => { + const path = "/mnt/repo_root"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/mnt/repo_root/project/bam/4243")).to.equal( + PathType.PROJECT_RECORD_PATH, + ); + }); + + it("unit_repo: should handle a user record path.", () => { + const path = "/mnt/repo_root"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/mnt/repo_root/user/jane/4243")).to.equal(PathType.USER_RECORD_PATH); + }); + + it("unit_repo: should handle a user record path.", () => { + const path = "/mnt/datafed/compose-home/"; + g_db.repo.save({ + _id: "repo/foo", + _key: "foo", + path: path, + }); + const repo = new Repo("foo"); + expect(repo.pathType("/mnt/datafed/compose-home/user/tim/1135")).to.equal( + PathType.USER_RECORD_PATH, + ); + }); +}); diff --git a/core/database/foxx/tests/support.test.js b/core/database/foxx/tests/support.test.js index c0431f0ec..04c96c78b 100644 --- a/core/database/foxx/tests/support.test.js +++ b/core/database/foxx/tests/support.test.js @@ -1,26 +1,88 @@ -"use strict" +"use strict"; // Integration test of API const chai = require("chai"); const should = chai.should(); const expect = chai.expect; const assert = chai.assert; -const g_lib = require("../api/support") +const g_lib = require("../api/support"); describe("the Foxx microservice support module evaluating isUUID.", () => { - it("should return true if string is a UUID.", () => { - var uuid = "XXXXYYYY-XXXX-YYYY-XXXX-YYYYXXXXYYYY" + it("unit_support: should return true if string is a UUID.", () => { + var uuid = "XXXXYYYY-XXXX-YYYY-XXXX-YYYYXXXXYYYY"; expect(g_lib.isUUID(uuid)).to.be.true; }); }); describe("the Foxx microservice support module evaluating isUUIDList.", () => { - it("should return true if string is a UUID List.", () => { - var uuids = "XXXXYYYY-XXXX-YYYY-XXXX-YYYYXXXXYYYY,XXXXYYYY-XXXX-YYYY-XXXX-YYYYXXXXYYYY" + it("unit_support: should return true if string is a UUID List.", () => { + var uuids = "XXXXYYYY-XXXX-YYYY-XXXX-YYYYXXXXYYYY,XXXXYYYY-XXXX-YYYY-XXXX-YYYYXXXXYYYY"; expect(g_lib.isUUIDList(uuids)).to.be.true; }); - it("should return false because one of the provided items is not a uuid", () => { - var uuids = "XXXXYYYY-XXXX-YYYY-XXXX-YYYYXXXXYYYY,132" + it("unit_support: should return false because one of the provided items is not a uuid", () => { + var uuids = "XXXXYYYY-XXXX-YYYY-XXXX-YYYYXXXXYYYY,132"; expect(g_lib.isUUIDList(uuids)).to.be.false; }); -}); \ No newline at end of file +}); + +describe("unit_support: the Foxx microservice support module evaluating parseOtherTokenData.", () => { + const test_uuid = "1cbaaee5-b938-4a4e-87a8-f1ec4d5d92f9"; // fake UUID + const test_scopes = "urn:globus:auth:scope:transfer.api.globus.org:all+email"; + it("should yield parsed data for a GLOBUS_TRANSFER token when provided a UUID and scopes in order", () => { + // arrange + const test_str = test_uuid + "|" + test_scopes; + + // act + const result_object = g_lib.parseOtherTokenData( + g_lib.AccessTokenType.GLOBUS_TRANSFER, + test_str, + ); + + // assert + expect(result_object.uuid).to.equal(test_uuid); + expect(result_object.scopes).to.equal(test_scopes); + }); + + it("should error for GLOBUS_TRANSFER token if given UUID and scopes with incorrect separator.", () => { + const test_str = test_uuid + "!" + test_scopes; + const err_fn = () => + g_lib.parseOtherTokenData(g_lib.AccessTokenType.GLOBUS_TRANSFER, test_str); + + expect(err_fn).to.throw("Unexpected count of additional token data provided"); + }); + + it("should error for GLOBUS_TRANSFER token if given UUID but no scopes.", () => { + const err_fn = () => + g_lib.parseOtherTokenData(g_lib.AccessTokenType.GLOBUS_TRANSFER, test_uuid); + + expect(err_fn).to.throw("Unexpected count of additional token data provided"); + }); + + it("should error for GLOBUS_TRANSFER token if given scopes but no UUID.", () => { + const err_fn = () => + g_lib.parseOtherTokenData(g_lib.AccessTokenType.GLOBUS_TRANSFER, test_scopes); + + expect(err_fn).to.throw("Unexpected count of additional token data provided"); + }); + + it("should error for GLOBUS_TRANSFER token if given UUID and scopes in incorrect order.", () => { + // arrange + const test_str = test_scopes + "|" + test_uuid; + const err_fn = () => + g_lib.parseOtherTokenData(g_lib.AccessTokenType.GLOBUS_TRANSFER, test_str); + + expect(err_fn).to.throw("Provided other_token_data does not follow format"); + }); + + it("should do nothing and return an empty object for unspecified token_type values", () => { + // arrange + const test_str = test_uuid + "|" + test_scopes; + const sentinel_token_type = -1; // TODO: provide for better sentinel values + + // act + const result_object = g_lib.parseOtherTokenData(sentinel_token_type, test_str); + + // assert + expect(result_object).to.be.empty; + }); +}); diff --git a/core/database/foxx/tests/user_fixture.js b/core/database/foxx/tests/user_fixture.js new file mode 100644 index 000000000..816f3b602 --- /dev/null +++ b/core/database/foxx/tests/user_fixture.js @@ -0,0 +1,61 @@ +const { db } = require("@arangodb"); +const g_lib = require("../api/support"); + +const current_time = Math.floor(Date.now() / 1000); +const get_token_test_user = "getTokenUser"; +const get_model_test_user = "getModelUser"; +const get_globus_token_model_user = "getGlobusTokenModelUser"; +const user_token_user = "userTokenUser"; +const user_collection_token_user = "userCollectionTokenUser"; +const uid_list = [ + "testUser0", + "testUser1", + "testUser2", + "testUser3", + "testUser4", + get_token_test_user, + get_model_test_user, + get_globus_token_model_user, + user_token_user, + user_collection_token_user, +]; +const end_uid = uid_list.at(-1); +const base_user_data = { + name_first: "test", + name_last: "user", + is_admin: true, + max_coll: g_lib.DEF_MAX_COLL, + max_proj: g_lib.DEF_MAX_PROJ, + max_sav_qry: g_lib.DEF_MAX_SAV_QRY, + ct: current_time, + ut: current_time, +}; + +const users_needing_token = [user_token_user, user_collection_token_user]; + +if (!db._collection("u")) { + throw "This collection - u - does not exist"; +} else if (!db.u.exists(end_uid)) { + uid_list.map((uid, idx) => { + if (!db.u.exists(uid)) { + const minimal_user_data = { + _key: uid, + name: "test user" + " " + uid, + ...base_user_data, + }; + let user_data; + if (users_needing_token.includes(uid)) { + user_data = { + access: "access for " + uid, + refresh: "refresh for " + uid, + expiration: current_time + 123456789, + ...minimal_user_data, + }; + } else { + user_data = minimal_user_data; + } + + db.u.save(user_data); + } + }); +} diff --git a/core/database/foxx/tests/user_model.test.js b/core/database/foxx/tests/user_model.test.js new file mode 100644 index 000000000..b32307a16 --- /dev/null +++ b/core/database/foxx/tests/user_model.test.js @@ -0,0 +1,192 @@ +"use strict"; + +const { UserModel, User } = require("../api/models/user"); +const { DataFedOAuthToken } = require("../api/models/DataFedOAuthToken"); +const g_lib = require("../api/support"); + +// Unit test of DB user model +const { expect } = require("chai"); +const { db } = require("@arangodb"); + +describe("unit_user_model: User Model tests", () => { + // test setup - give some arbitrary token + let working_user_doc; + let get_user_doc; + before(() => { + get_user_doc = Object.freeze(db.u.document({ _key: "getModelUser" })); + const update_user_doc = db.u.update( + get_user_doc, + { + ...get_user_doc, + access: "get user access token", + refresh: "get user refresh token", + expiration: 123456789, + }, + { returnNew: true }, + ); + working_user_doc = Object.freeze(update_user_doc.new); + }); + + describe("unit_user_model: calling constructor", () => { + it("should create a user object when passed an id", () => { + const user_model = new UserModel("u/getModelUser"); + expect(user_model).to.be.instanceOf(UserModel); + }); + it("should create a user object when passed a key", () => { + const user_model = new UserModel(null, "getModelUser"); + expect(user_model).to.be.instanceOf(UserModel); + }); + it("should throw an error if neither id nor key are provided", () => { + expect(() => new UserModel()).to.throw("User ID or Key must be provided"); + }); + }); + + describe("unit_user_model: calling exists", () => { + const user_model_exists = new UserModel("u/getModelUser"); + const user_model_dne = new UserModel("u/userNotExists"); + + it("should return true when the user exists on DB", () => { + const user_exists = user_model_exists.exists(); + expect(user_exists).to.be.true; + }); + + it("should return false when the user does not exist on DB", () => { + const user_exists = user_model_dne.exists(); + expect(user_exists).to.be.false; + }); + }); + + describe("unit_user_model: calling get", () => { + const user_model_exists = new UserModel("u/getModelUser"); + const user_model_dne = new UserModel("u/userNotExists"); + + it("should return a read only user object when user exists", () => { + const user = user_model_exists.get(); + + expect(user).to.be.instanceOf(User); + expect(user).to.be.frozen; + expect(user).to.include({ + id: working_user_doc._id, + key: working_user_doc._key, + name: working_user_doc.name, + first_name: working_user_doc.first_name, + last_name: working_user_doc.last_name, + is_admin: working_user_doc.is_admin, + maximum_collections: working_user_doc.max_coll, + maximum_projects: working_user_doc.max_proj, + maximum_saved_queries: working_user_doc.max_sav_qry, + creation_time: working_user_doc.ct, + update_time: working_user_doc.ut, + // These values should be undefined + password: working_user_doc.password, + email: working_user_doc.email, + options: working_user_doc.options, + }); + }); + + it("should return a ready only empty user object with all fields undefined when user does not exist", () => { + const user = user_model_dne.get(); + + expect(user).to.be.instanceOf(User); + expect(user).to.be.frozen; + Object.keys(User).map((key) => { + expect(user).to.have.property(key, undefined); + }); + }); + + // TODO: this is mostly to document current functionality, we will likely want updates in the future + it("should not update when the database data updates", () => { + // arrange + const test_no_update_token_data = { + access: "test no update access", + refresh: "test no update refresh", + }; + const inserted_data = db.u.insert( + { ...get_user_doc, ...test_no_update_token_data, _key: "test_get_before_update" }, + { returnNew: true }, + ); + const working_user_model = new UserModel(inserted_data._id); + const old_user = working_user_model.get(); + + // act + let updated_data = db.u.update( + inserted_data, + { email: "new_test_email@example.com" }, + { returnNew: true }, + ); + const new_user = working_user_model.get(); + + // assert + expect(new_user).to.deep.equal(old_user); + expect(new_user).to.have.property("email", undefined); + expect(new_user.email).to.equal(updated_data.email); + + // cleanup + db.u.remove(updated_data); + }); + + it("should reflect updates when a new user model is built", () => { + // arrange + const test_update_token_data = { + access: "test update access", + refresh: "test update refresh", + }; + const inserted_data = db.u.insert( + { ...get_user_doc, ...test_update_token_data, _key: "test_get_after_update" }, + { returnNew: true }, + ); + const old_user = new UserModel(inserted_data._id).get(); + + // act + let updated_data = db.u.update( + inserted_data, + { email: "new_test_email@example.com" }, + { returnNew: true }, + ); + const new_user = new UserModel(inserted_data._id).get(); + + // assert + expect(new_user).to.not.deep.equal(old_user); + expect(new_user).to.have.property("email", "new_test_email@example.com"); + expect(new_user.email).to.not.equal(updated_data.email); + + // cleanup + db.u.remove(updated_data); + }); + }); + + describe("unit_user_model: calling get_token", () => { + const user_model_exists = new UserModel("u/getModelUser"); + const user_model_dne = new UserModel("u/userNotExists"); + + it("should return a read only token object when user exists", () => { + const token = user_model_exists.get_token(); + + expect(token).to.be.instanceOf(DataFedOAuthToken); + expect(token).to.be.frozen; + expect(token).to.include({ + access: working_user_doc.access, + refresh: working_user_doc.refresh, + expiration: working_user_doc.expiration, + type: g_lib.AccessTokenType.GLOBUS_DEFAULT, + dependent_scopes: "", + }); + }); + + it("should return an empty object when user does not exist", () => { + const token = user_model_dne.get_token(); + + expect(token).to.be.instanceOf(DataFedOAuthToken); + expect(token).to.be.frozen; + expect(token).to.include({ + access: undefined, + refresh: undefined, + expiration: undefined, + type: g_lib.AccessTokenType.GLOBUS_DEFAULT, + dependent_scopes: "", + }); + }); + + // assuming previous update tests sufficient to prove same logic here + }); +}); diff --git a/core/database/foxx/tests/user_router.test.js b/core/database/foxx/tests/user_router.test.js new file mode 100644 index 000000000..63b368839 --- /dev/null +++ b/core/database/foxx/tests/user_router.test.js @@ -0,0 +1,254 @@ +"use strict"; +// NOTE: completion of tests requires successful run of user_fixture.js script + +// Need to pull enum from support +const g_lib = require("../api/support"); + +// Integration test of API +const { expect } = require("chai"); +const request = require("@arangodb/request"); +const { baseUrl } = module.context; +const { db } = require("@arangodb"); + +const usr_base_url = `${baseUrl}/usr`; + +// NOTE: describe block strings are compared against test specification during test call, not file name +describe("unit_user_router: the Foxx microservice user_router token/set endpoint", () => { + const test_param_indexes = [0, 1, 2, 3, 4]; + const test_params = test_param_indexes.map((param_index) => { + return { + _key: "testUser" + param_index, + access: "access_token" + param_index, + refresh: "refresh_token" + param_index, + }; + }); + const test_uuid = "1cbaaee5-b938-4a4e-87a8-f1ec4d5d92f9"; // fake UUID + const test_scope = "urn:globus:auth:scope:transfer.api.globus.org:all"; + const test_edge_params = { + type: g_lib.AccessTokenType.GLOBUS_TRANSFER, + other_token_data: test_uuid + "%7C" + test_scope, // URL encoded | character + }; + + it("should accept a valid user's token and execute an update", () => { + // arrange + // NOTE: the get request has query params instead of a body + const query_params = test_params[0]; + // TODO: make encoded query params less hard coded + const request_string = `${usr_base_url}/token/set?client=${query_params._key}&access=${query_params.access}&refresh=${query_params.refresh}&expires_in=500000`; + + // act + const response = request.get(request_string); + + // assert + expect(response.status).to.equal(204); + + const user_token_data = db.u.document({ _key: query_params._key }); + expect(user_token_data).to.include(query_params); + }); + + it("should error when only additionally provided type", () => { + // arrange + const local_test_params = test_params[1]; + const query_params = { + ...local_test_params, + type: test_edge_params.type, + }; + // TODO: make encoded query params less hard coded + const request_string = `${usr_base_url}/token/set?client=${query_params._key}&access=${query_params.access}&refresh=${query_params.refresh}&expires_in=500000&type=${query_params.type}`; + + // act + const response = request.get(request_string); + + // assert + expect(response.status).to.equal(400); + expect(response.body).to.include("type and other_token_data depend on one another"); + + const user_token_data = db.u.document({ _key: query_params._key }); + const user_token_edge = db.globus_token.outEdges(user_token_data._id); + expect(user_token_edge).to.be.empty; + }); + + it("should error when only additionally provided other token data", () => { + // arrange + const local_test_params = test_params[2]; + const query_params = { + ...local_test_params, + other_token_data: test_edge_params.other_token_data, + }; + // TODO: make encoded query params less hard coded + const request_string = `${usr_base_url}/token/set?client=${query_params._key}&access=${query_params.access}&refresh=${query_params.refresh}&expires_in=500000&other_token_data=${query_params.other_token_data}`; + + // act + const response = request.get(request_string); + + // assert + expect(response.status).to.equal(400); + expect(response.body).to.include("the default action cannot process other_token_data"); + + const user_token_data = db.u.document({ _key: query_params._key }); + const user_token_edge = db.globus_token.outEdges(user_token_data._id); + expect(user_token_edge).to.be.empty; + }); + + it("should error when additionally provided the default type and other token data", () => { + // arrange + const local_test_params = test_params[2]; + const query_params = { + ...local_test_params, + type: g_lib.AccessTokenType.GLOBUS_DEFAULT, + other_token_data: test_edge_params.other_token_data, + }; + // TODO: make encoded query params less hard coded + const request_string = `${usr_base_url}/token/set?client=${query_params._key}&access=${query_params.access}&refresh=${query_params.refresh}&expires_in=500000&type=${query_params.type}&other_token_data=${query_params.other_token_data}`; + + // act + const response = request.get(request_string); + + // assert + expect(response.status).to.equal(400); + expect(response.body).to.include("the default action cannot process other_token_data"); + + const user_token_data = db.u.document({ _key: query_params._key }); + const user_token_edge = db.globus_token.outEdges(user_token_data._id); + expect(user_token_edge).to.be.empty; + }); + + it("should accept a valid user's token with additional type and globus collection data and add it to globus_token edge", () => { + // arrange + const local_test_params = test_params[3]; + const query_params = { + user_key: local_test_params._key, + access: local_test_params.access, + refresh: local_test_params.refresh, + ...test_edge_params, + }; + + const expected_doc_key = test_uuid + "_" + query_params.type + "_" + query_params.user_key; + const expected = { + ...query_params, + _key: expected_doc_key, + _from: "u/" + query_params.user_key, + _to: "globus_coll/" + test_uuid, + }; + delete expected.other_token_data; // unwanted data + delete expected.user_key; + + // TODO: make encoded query params less hard coded + const request_string = `${usr_base_url}/token/set?client=${query_params.user_key}&access=${query_params.access}&refresh=${query_params.refresh}&expires_in=500000&type=${query_params.type}&other_token_data=${query_params.other_token_data}`; + + // act + const response = request.get(request_string); + + // assert + expect(response.status).to.equal(204); + + // TODO: better data expectation when doc is defined + const globus_collection_data = db.globus_coll.exists({ _key: test_uuid }); + expect(globus_collection_data).to.exist; + + const globus_token_data = db.globus_token.document({ + _key: expected_doc_key, + }); + expect(globus_token_data).to.include(expected); + + const user_data = db.u.document({ _key: query_params.user_key }); + expect(user_data.access).to.not.equal(query_params.access); // should not update user doc + }); +}); +describe("unit_user_router: the Foxx microservice user_router token/get endpoint", () => { + const test_uuid = "b68ef5fb-f511-4e98-b8a3-dbc6acbcb6f2"; // fake UUID + const test_scope = "urn:globus:auth:scope:transfer.api.globus.org:all"; + const get_token_test_user = "getTokenUser"; + const test_access_token = "test_access_token"; + const test_refresh_token = "test_refresh_token"; + const test_globus_access_token = "test_globus_access_token"; + const test_globus_refresh_token = "test_globus_refresh_token"; + const test_globus_token_type = g_lib.AccessTokenType.GLOBUS_TRANSFER; + const test_other_token_data = test_uuid + "%7C" + test_scope; + const test_expires_in = "12345689"; + before(() => { + // One time set up of some test user data + const default_token_query_string = `${usr_base_url}/token/set?client=${get_token_test_user}&access=${test_access_token}&refresh=${test_refresh_token}&expires_in=${test_expires_in}`; + const default_token_response = request.get(default_token_query_string); + expect(default_token_response.status).to.equal(204); + + const collection_token_query_string = `${usr_base_url}/token/set?client=${get_token_test_user}&access=${test_globus_access_token}&refresh=${test_globus_refresh_token}&expires_in=500000&type=${test_globus_token_type}&other_token_data=${test_other_token_data}`; + const collection_token_response = request.get(collection_token_query_string); + expect(collection_token_response.status).to.equal(204); + }); + + const token_get_test_user_base_url = `${usr_base_url}/token/get?client=${get_token_test_user}`; + it("Should reject the optional collection_id param if it is not a valid GUID", () => { + const invalid_guid = "invalid_guid"; + const invalid_guid_url = `${token_get_test_user_base_url}&collection_id=${invalid_guid}`; + + const response = request.get(invalid_guid_url); + + expect(response.status).to.equal(400); + expect(response.body).to.include( + 'query parameter \\"collection_id\\" must be a valid GUID', + ); + }); + + it("Should reject optional collection_type param if it is not of value `mapped`", () => { + const not_mapped = "not_mapped"; + const invalid_type_url = `${token_get_test_user_base_url}&collection_type=${not_mapped}`; + + const response = request.get(invalid_type_url); + + expect(response.status).to.equal(400); + expect(response.body).to.include( + 'query parameter \\"collection_type\\" must be one of [mapped]', + ); + }); + + it("Should retrieve the default token when optional params are not provided", () => { + const response = request.get(token_get_test_user_base_url); + + expect(response.status).to.equal(200); + + const json_body = JSON.parse(response.body); + expect(json_body).to.include({ needs_consent: false }); + expect(json_body).to.include({ access: test_access_token, refresh: test_refresh_token }); + expect(response.body).to.include("expires_in"); + expect(json_body).to.include({ token_type: g_lib.AccessTokenType.GLOBUS_DEFAULT }); + }); + + it("Should retrieve specified collection token when optional params are provided", () => { + const collection_url = `${token_get_test_user_base_url}&collection_id=${test_uuid}&collection_type=mapped`; + + const response = request.get(collection_url); + + expect(response.status).to.equal(200); + + const json_body = JSON.parse(response.body); + expect(json_body).to.include({ needs_consent: false }); + expect(json_body).to.include({ + access: test_globus_access_token, + refresh: test_globus_refresh_token, + }); + expect(response.body).to.include("expires_in"); + expect(json_body).to.include({ token_type: test_globus_token_type }); + expect(json_body).to.include({ scopes: test_scope }); + }); + + it("Should indicate consent flow is needed when a token is not found for a specified collection", () => { + const collection_not_related_uuid = "94445318-2097-4ed8-8550-f73cd292b11f"; // TODO: pull from globus_collection_fixture.js + const collection_not_related_url = `${token_get_test_user_base_url}&collection_id=${collection_not_related_uuid}&collection_type=mapped`; + + const response = request.get(collection_not_related_url); + + expect(response.status).to.equal(200); + expect(JSON.parse(response.body)).to.include({ needs_consent: true }); + }); + + it("Should indicate consent flow is needed when a specified collection cannot be found", () => { + const collection_not_exists_uuid = "d08c40c6-b778-427d-9963-255ce2bbbd2e"; // Fake UUID + const collection_not_exists_url = `${token_get_test_user_base_url}&collection_id=${collection_not_exists_uuid}&collection_type=mapped`; + + const response = request.get(collection_not_exists_url); + + expect(response.status).to.equal(200); + expect(JSON.parse(response.body)).to.include({ needs_consent: true }); + }); +}); diff --git a/core/database/foxx/tests/user_token.test.js b/core/database/foxx/tests/user_token.test.js new file mode 100644 index 000000000..79d7d0977 --- /dev/null +++ b/core/database/foxx/tests/user_token.test.js @@ -0,0 +1,335 @@ +"use strict"; + +const g_lib = require("../api/support"); +const { UserToken } = require("../api/lib/user_token"); +const { DataFedOAuthToken } = require("../api/models/DataFedOAuthToken"); + +const { expect } = require("chai"); + +describe("unit_user_token: The user_token library module class UserToken evaluating static method validateRequestParams", () => { + const valid_params = { + // random ID + collection_id: "ba873943-199d-4c9c-a998-10383329e5df", + collection_type: "mapped", + }; + it("Should throw an error when query_params collection_id is defined and collection_type is not", () => { + const collection_id_params = { + collection_id: valid_params.collection_id, + }; + expect(() => UserToken.validateRequestParams(collection_id_params)).to.throw( + "Requires 'collection_id' and 'collection_type' both if one is present", + ); + }); + it("Should throw an error when query_params collection_type is defined and collection_id is not", () => { + const collection_type_params = { + collection_type: valid_params.collection_type, + }; + expect(() => UserToken.validateRequestParams(collection_type_params)).to.throw( + "Requires 'collection_id' and 'collection_type' both if one is present", + ); + }); + it("Should return true when both expected query_params are present", () => { + const is_collection_token = UserToken.validateRequestParams(valid_params); + + expect(is_collection_token).to.be.true; + }); + it("Should return false when neither expected query_params is present", () => { + const is_collection_token = UserToken.validateRequestParams({}); + + expect(is_collection_token).to.be.false; + }); +}); + +describe("unit_user_token: The user_token library module class UserToken evaluating static method formatUserToken", () => { + const valid_token_doc = { + access: "fake access token", + refresh: "fake refresh token", + expiration: 123456789, + }; + const valid_collection_token_doc = { + ...valid_token_doc, + type: g_lib.AccessTokenType.GLOBUS_TRANSFER, + dependent_scopes: "fake token scope", + }; + it("Should return an object with default values if needs_consent=true", () => { + const default_values = { + access: "", + refresh: "", + expires_in: 0, + token_type: g_lib.AccessTokenType.ACCESS_SENTINEL, + scopes: "", + }; + const is_collection_token = true; + const needs_consent = true; + + const response_token = UserToken.formatUserToken( + is_collection_token, + valid_collection_token_doc, + needs_consent, + ); + + expect(response_token.needs_consent).to.be.true; + expect(response_token).to.include(default_values); + }); + + it("Should return relevant information from a token document when needs_consent=false and is_collection_token=false", () => { + const is_collection_token = false; + const needs_consent = false; + + const token_document = valid_token_doc; + + const response_token = UserToken.formatUserToken( + is_collection_token, + token_document, + needs_consent, + ); + + expect(response_token.needs_consent).to.be.false; + expect(response_token.access).to.equal(token_document.access); + expect(response_token.refresh).to.equal(token_document.refresh); + expect(response_token.expires_in).to.exist; + expect(response_token.token_type).to.equal(g_lib.AccessTokenType.GLOBUS_DEFAULT); + }); + + it("Should return relevant information from a token document when needs_consent=false and is_collection_token=true", () => { + const is_collection_token = true; + const needs_consent = false; + + const token_document = valid_collection_token_doc; + + const response_token = UserToken.formatUserToken( + is_collection_token, + token_document, + needs_consent, + ); + + expect(response_token.needs_consent).to.be.false; + expect(response_token.access).to.equal(token_document.access); + expect(response_token.refresh).to.equal(token_document.refresh); + expect(response_token.expires_in).to.exist; + expect(response_token.token_type).to.equal(token_document.type); + expect(response_token.scopes).to.equal(token_document.dependent_scopes); + }); + + it("Should flag needs_consent=true if token_document does not hold scope information for a collection_token", () => { + const is_collection_token = true; + const needs_consent = false; + + const token_document = { ...valid_collection_token_doc, dependent_scopes: undefined }; + + const response_token = UserToken.formatUserToken( + is_collection_token, + token_document, + needs_consent, + ); + + expect(response_token.needs_consent).to.be.true; + // These following values should not matter + expect(response_token.access).to.equal(token_document.access); + expect(response_token.refresh).to.equal(token_document.refresh); + expect(response_token.expires_in).to.exist; + expect(response_token.token_type).to.equal(token_document.type); + expect(response_token.scopes).to.equal(token_document.dependent_scopes); + }); + + it("Should flag needs_consent=true if token_document does not hold type information for a collection_token", () => { + const is_collection_token = true; + const needs_consent = false; + + const token_document = { ...valid_collection_token_doc, type: undefined }; + + const response_token = UserToken.formatUserToken( + is_collection_token, + token_document, + needs_consent, + ); + + expect(response_token.needs_consent).to.be.true; + // The following values should not matter + expect(response_token.access).to.equal(token_document.access); + expect(response_token.refresh).to.equal(token_document.refresh); + expect(response_token.expires_in).to.exist; + expect(response_token.token_type).to.equal(token_document.type); + expect(response_token.scopes).to.equal(token_document.dependent_scopes); + }); +}); + +// "magic" values from fixture files +const user_token_user = "userTokenUser"; +const user_collection_token_user = "userCollectionTokenUser"; +const globus_collection_token_collection = "126a23d4-45ed-49fb-bde2-76b5f44d20d1"; +const globus_collection_does_not_exist = "c8f55b3b-48ef-4075-b3ea-1b16ff5f956e"; // random fake UUID +describe("unit_user_token: calling constructor", () => { + it("should create a user token object when provided a user_id", () => { + const kwargs = { user_id: "u/" + user_token_user }; + const user_token = new UserToken(kwargs); + + expect(user_token).to.be.instanceOf(UserToken); + }); + it("should create a user token object when provided a user_key", () => { + const kwargs = { user_key: user_token_user }; + const user_token = new UserToken(kwargs); + + expect(user_token).to.be.instanceOf(UserToken); + }); + it("should create a user token object when provided a user_id and globus_collection_id", () => { + const kwargs = { + user_id: "u/" + user_token_user, + globus_collection_id: "9deac418-f96b-414e-a2c4-7278408c0766", // some fake UUID + }; + const user_token = new UserToken(kwargs); + + expect(user_token).to.be.instanceOf(UserToken); + }); + it("should create a user token object when provided a user_key and globus_collection_id", () => { + const kwargs = { + user_key: user_token_user, + globus_collection_id: "9deac418-f96b-414e-a2c4-7278408c0766", // some fake UUID + }; + const user_token = new UserToken(kwargs); + + expect(user_token).to.be.instanceOf(UserToken); + }); + it("should throw an error when provided a user_id for a user that does not exist", () => { + const kwargs = { user_id: "u/fake_user" }; + expect(() => new UserToken(kwargs)).to.throw("Specified user does not exist: "); + }); + it("should throw an error when provided a user_key for a user that does not exist", () => { + const kwargs = { user_key: "fake_user" }; + expect(() => new UserToken(kwargs)).to.throw("Specified user does not exist: "); + }); + it("should throw an error when provided a user and globus_collection_id, and user does not exist", () => { + const kwargs = { + user_id: "u/fake_user", + globus_collection_id: "9deac418-f96b-414e-a2c4-7278408c0766", // some fake UUID + }; + expect(() => new UserToken(kwargs)).to.throw("Specified user does not exist: "); + }); +}); + +describe("unit_user_token: calling exists", () => { + it("should return true when provided only user_id and user DB object has a token", () => { + const user_token = new UserToken({ user_id: "u/" + user_token_user }); + const user_token_exists = user_token.exists(); + expect(user_token_exists).to.be.true; + }); + it("should return true when provided only user_key and user DB object has a token", () => { + const user_token = new UserToken({ user_key: user_token_user }); + const user_token_exists = user_token.exists(); + expect(user_token_exists).to.be.true; + }); + // assuming no cases where user does not have a token, sign-up process should cover that + it("should return true when user and collection are provided and DB object exists for token", () => { + const user_token = new UserToken({ + user_id: "u/" + user_collection_token_user, + globus_collection_id: globus_collection_token_collection, + }); + const user_token_exists = user_token.exists(); + expect(user_token_exists).to.be.true; + }); + it("should return false when user and collection are provided and DB object does not exist for token", () => { + const user_token = new UserToken({ + user_id: "u/" + user_token_user, + globus_collection_id: globus_collection_token_collection, + }); + const user_token_exists = user_token.exists(); + expect(user_token_exists).to.be.false; + }); + it("should return false when user and collection are provided and collection does not exist", () => { + const user_token = new UserToken({ + user_id: "u/" + user_token_user, + globus_collection_id: globus_collection_does_not_exist, + }); + const user_token_exists = user_token.exists(); + expect(user_token_exists).to.be.false; + }); +}); + +describe("unit_user_token: calling get_token", () => { + it("should return readonly DataFedOAuthToken object when provided only user_id and user DB object has a token", () => { + const user_token = new UserToken({ user_id: "u/" + user_token_user }); + const user_token_oauth_token = user_token.get_token(); + + expect(user_token_oauth_token).to.be.instanceOf(DataFedOAuthToken); + expect(user_token_oauth_token).to.be.frozen; + expect(user_token_oauth_token) + .to.have.property("access") + .that.includes("access for " + user_token_user); + expect(user_token_oauth_token) + .to.have.property("refresh") + .that.includes("refresh for " + user_token_user); + expect(user_token_oauth_token).to.have.property("expiration").that.is.a("number"); + expect(user_token_oauth_token).to.include({ + type: g_lib.AccessTokenType.GLOBUS_DEFAULT, + dependent_scopes: "", + }); + }); + it("should return readonly DataFedOAuthToken object when provided only user_key and user DB object has a token", () => { + const user_token = new UserToken({ user_key: user_token_user }); + const user_token_oauth_token = user_token.get_token(); + + expect(user_token_oauth_token).to.be.instanceOf(DataFedOAuthToken); + expect(user_token_oauth_token).to.be.frozen; + expect(user_token_oauth_token) + .to.have.property("access") + .that.includes("access for " + user_token_user); + expect(user_token_oauth_token) + .to.have.property("refresh") + .that.includes("refresh for " + user_token_user); + expect(user_token_oauth_token).to.have.property("expiration").that.is.a("number"); + expect(user_token_oauth_token).to.include({ + type: g_lib.AccessTokenType.GLOBUS_DEFAULT, + dependent_scopes: "", + }); + }); + // assuming no cases where user does not have a token, sign-up process should cover that + it("should return readonly DataFedOAuthToken object when user and collection are provided and DB object exists for token", () => { + const user_token = new UserToken({ + user_id: "u/" + user_collection_token_user, + globus_collection_id: globus_collection_token_collection, + }); + const user_token_oauth_token = user_token.get_token(); + + expect(user_token_oauth_token).to.be.instanceOf(DataFedOAuthToken); + expect(user_token_oauth_token).to.be.frozen; + expect(user_token_oauth_token) + .to.have.property("access") + .that.includes("globus token access for "); + expect(user_token_oauth_token) + .to.have.property("refresh") + .that.includes("globus token refresh for "); + expect(user_token_oauth_token).to.have.property("expiration").that.is.a("number"); + expect(user_token_oauth_token).to.include({ + type: g_lib.AccessTokenType.GLOBUS_TRANSFER, + dependent_scopes: "some fake scopes", // from fixture + }); + }); + it("should return empty readonly DataFedOAuthToken object when user and collection are provided and DB object does not exist for token", () => { + const user_token = new UserToken({ + user_id: "u/" + user_token_user, + globus_collection_id: globus_collection_token_collection, + }); + const user_token_oauth_token = user_token.get_token(); + + expect(user_token_oauth_token).to.be.instanceOf(DataFedOAuthToken); + expect(user_token_oauth_token).to.be.frozen; + expect(user_token_oauth_token).to.include({ + access: undefined, + refresh: undefined, + expiration: undefined, + type: undefined, + dependent_scopes: undefined, + }); + }); + it("should return empty readonly DataFedOAuthToken object when user and collection are provided and collection does not exist", () => { + const user_token = new UserToken({ + user_id: "u/" + user_token_user, + globus_collection_id: globus_collection_does_not_exist, + }); + const user_token_oauth_token = user_token.get_token(); + + expect(user_token_oauth_token).to.be.instanceOf(DataFedOAuthToken); + expect(user_token_oauth_token).to.be.frozen; + expect(user_token_oauth_token).to.be.empty; + }); +}); diff --git a/core/database/foxx/tests/version.test.js b/core/database/foxx/tests/version.test.js index 1ee8ec7cc..1441f9394 100644 --- a/core/database/foxx/tests/version.test.js +++ b/core/database/foxx/tests/version.test.js @@ -1,16 +1,14 @@ -"use strict" +"use strict"; // Integration test of API const chai = require("chai"); const should = chai.should(); const expect = chai.expect; const request = require("@arangodb/request"); -const { - baseUrl -} = module.context; +const { baseUrl } = module.context; describe("the Foxx microservice version route.", () => { - it("should return version information about the release and the foxx service and api versions.", () => { + it("unit_version: should return version information about the release and the foxx service and api versions.", () => { const response = request.get(`${baseUrl}/version`); expect(response.status).to.equal(200); var object = JSON.parse(response.body); @@ -20,4 +18,4 @@ describe("the Foxx microservice version route.", () => { object.should.have.property("release_hour"); object.should.have.property("release_minute"); }); -}); \ No newline at end of file +}); diff --git a/core/database/tests/test_fixture_setup.sh b/core/database/tests/test_fixture_setup.sh new file mode 100755 index 000000000..4d14656b8 --- /dev/null +++ b/core/database/tests/test_fixture_setup.sh @@ -0,0 +1,145 @@ +#!/bin/bash + + +set -uef -o pipefail + +SCRIPT=$(realpath "$BASH_SOURCE[0]") +SOURCE=$(dirname "$SCRIPT") +PROJECT_ROOT=$(realpath "${SOURCE}/../../../") +source "${PROJECT_ROOT}/config/datafed.sh" +source "${PROJECT_ROOT}/scripts/dependency_versions.sh" +source "${PROJECT_ROOT}/scripts/dependency_install_functions.sh" + +Help() +{ + echo "$(basename $0) Will initialize fixtures for Foxx tests" + echo + echo "Syntax: $(basename $0) [-h|u|p|y]" + echo "options:" + echo "-h, --help Print this help message." + echo "-u, --database-user Database user, needed to log into the database." + echo "-f, --foxx-api-major-version The major version number to mount the foxx api under." + echo "-p, --database-password Database password, needed to log into the database." + echo " This is a REQUIRED parameters if it is not" + echo " provided via the command line it can also be set" + echo " using the enviromental variable" + echo " DATAFED_DATABASE_PASSWORD." + echo + echo "NOTE: Do not run this script with sudo!" +} + +local_DATABASE_NAME="sdms" +local_DATABASE_USER="root" + +if [ -z "${DATAFED_DATABASE_HOST:-}" ] +then + local_DATAFED_DATABASE_HOST="localhost" +else + local_DATAFED_DATABASE_HOST=$(printenv DATAFED_DATABASE_HOST) +fi + +if [ -z "${DATAFED_DATABASE_PASSWORD:-}" ] +then + local_DATAFED_DATABASE_PASSWORD="" +else + local_DATAFED_DATABASE_PASSWORD=$(printenv DATAFED_DATABASE_PASSWORD) +fi + +if [ -z "${FOXX_MAJOR_API_VERSION:-}" ] +then + local_FOXX_MAJOR_API_VERSION=$(cat ${PROJECT_ROOT}/cmake/Version.cmake | grep -o -P "(?<=FOXX_API_MAJOR).*(?=\))" | xargs ) +else + local_FOXX_MAJOR_API_VERSION=$(printenv FOXX_MAJOR_API_VERSION) +fi + +VALID_ARGS=$(getopt -o hu:p:f: --long 'help',database-user:,database-password:,foxx-api-major-version: -- "$@") +if [[ $? -ne 0 ]]; then + exit 1; +fi +eval set -- "$VALID_ARGS" +while [ : ]; do + echo "$1" + case "$1" in + -h | --help) + Help + exit 0 + ;; + -u | --database-user) + echo "Processing 'Database user' option. Input argument is '$2'" + local_DATABASE_USER=$2 + shift 2 + ;; + -p | --database-password) + echo "Processing 'Database password' option. Input argument is '$2'" + local_DATAFED_DATABASE_PASSWORD=$2 + shift 2 + ;; + -f | --foxx-api-major-version) + echo "Processing 'Foxx major api version' option. Input argument is '$2'" + local_FOXX_MAJOR_API_VERSION=$2 + shift 2 + ;; + --) shift; + break + ;; + \?) # incorrect option + echo "Error: Invalid option" + exit;; + esac +done + +ERROR_DETECTED=0 +if [ -z "$local_DATAFED_DATABASE_PASSWORD" ] +then + echo "Error DATAFED_DATABASE_PASSWORD is not defined, this is a required argument" + echo " This variable can be set using the command line option -p, --database-password" + echo " or with the environment variable DATAFED_DATABASE_PASSWORD." + ERROR_DETECTED=1 +fi + +if [ "$ERROR_DETECTED" == "1" ] +then + exit 1 +fi + +# There are apparently 3 different ways to deploy Foxx microservices, +# Using curl with http requests +# Using the Arango web ui +# Using node module +# +# The web deployment requires manual interaction, and I could not figure out +# the syntax for the REST http endpoints with curl so we are going to try the +# node module + +# Will only install if it is not already installed +install_nvm +install_node + +FOXX_PREFIX="" +if ! command -v foxx > /dev/null 2>&1; then + FOXX_PREFIX="${DATAFED_DEPENDENCIES_INSTALL_PATH}/npm/bin/" +fi + +PATH_TO_PASSWD_FILE=${SOURCE}/database_temp.password + +# set up test user fixtures, this script should be idempotent, this script is described in the manifest +"${FOXX_PREFIX}foxx" script -u "${local_DATABASE_USER}" \ + --server "tcp://${local_DATAFED_DATABASE_HOST}:8529" \ + -p "${PATH_TO_PASSWD_FILE}" \ + --database "${local_DATABASE_NAME}" \ + "/api/${local_FOXX_MAJOR_API_VERSION}" user-fixture + +# set up test globus collection fixtures, this script should be idempotent, this script is described in the manifest +"${FOXX_PREFIX}foxx" script -u "${local_DATABASE_USER}" \ + --server "tcp://${local_DATAFED_DATABASE_HOST}:8529" \ + -p "${PATH_TO_PASSWD_FILE}" \ + --database "${local_DATABASE_NAME}" \ + "/api/${local_FOXX_MAJOR_API_VERSION}" collection-fixture + +# set up test globus token fixtures, this script should be idempotent, this script is described in the manifest +# order matters, must follow user and collection fixtures +"${FOXX_PREFIX}foxx" script -u "${local_DATABASE_USER}" \ + --server "tcp://${local_DATAFED_DATABASE_HOST}:8529" \ + -p "${PATH_TO_PASSWD_FILE}" \ + --database "${local_DATABASE_NAME}" \ + "/api/${local_FOXX_MAJOR_API_VERSION}" globus-token-fixture \ No newline at end of file diff --git a/core/database/tests/test_foxx.sh b/core/database/tests/test_foxx.sh index 5dbb28e67..35d52b72d 100755 --- a/core/database/tests/test_foxx.sh +++ b/core/database/tests/test_foxx.sh @@ -1,13 +1,21 @@ #!/bin/bash -# -e has been removed so that if an error occurs the PASSWORD File is deleted and not left lying around -# -u has been removed because we are checking for possible non existent env variables -set -f -o pipefail +# History +# +# -e added back in because CI jobs are not failing when there are problems in +# this script. Residual password files can be removed a different way. i.e. in +# a cleanup script associated with a CI job. +# +# -e has been removed so that if an error occurs the PASSWORD File is deleted +# and not left lying around +set -euf -o pipefail -SCRIPT=$(realpath "$0") +SCRIPT=$(realpath "$BASH_SOURCE[0]") SOURCE=$(dirname "$SCRIPT") PROJECT_ROOT=$(realpath ${SOURCE}/../../../) source ${PROJECT_ROOT}/config/datafed.sh +source "${PROJECT_ROOT}/scripts/dependency_versions.sh" +source "${PROJECT_ROOT}/scripts/dependency_install_functions.sh" Help() { @@ -32,14 +40,14 @@ Help() local_DATABASE_NAME="sdms" local_DATABASE_USER="root" -if [ -z "${DATAFED_DATABASE_PASSWORD}" ] +if [ -z "${DATAFED_DATABASE_PASSWORD:-}" ] then local_DATAFED_DATABASE_PASSWORD="" else local_DATAFED_DATABASE_PASSWORD=$(printenv DATAFED_DATABASE_PASSWORD) fi -if [ -z "${FOXX_MAJOR_API_VERSION}" ] +if [ -z "${FOXX_MAJOR_API_VERSION:-}" ] then local_FOXX_MAJOR_API_VERSION=$(cat ${PROJECT_ROOT}/cmake/Version.cmake | grep -o -P "(?<=FOXX_API_MAJOR).*(?=\))" | xargs ) else @@ -110,39 +118,30 @@ fi # The web deployment requires manual interaction, and I could not figure out the # syntax for the REST http endpoints with curl so we are going to try the node module -## Will create the zip file in the build directory to keep datafed source code clean -#cd ../../build -## Zip up the api -#zip datafed.zip ../core/database/api/* -# -## Get the size of the file in bytes -#bytes=$(wc -c < datafed.zip) - -NODE_VERSION="v14.21.3" - -export NVM_DIR="$HOME/.nvm" -[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm - -nvm use $NODE_VERSION +# Will only install if not already present +install_nvm +install_node FOXX_PREFIX="" -{ - # Determine if exists globally first - which foxx -} || { - FOXX_PREFIX="~/bin/" -} +if ! command -v foxx > /dev/null 2>&1; then + FOXX_PREFIX="${DATAFED_DEPENDENCIES_INSTALL_PATH}/npm/bin/" +fi PATH_TO_PASSWD_FILE=${SOURCE}/database_temp.password if [ "$TEST_TO_RUN" == "all" ] then + # WARNING Foxx and arangosh arguments differ --server is used for Foxx not --server.endpoint "${FOXX_PREFIX}foxx" test -u "${local_DATABASE_USER}" \ + --server "tcp://${DATAFED_DATABASE_HOST}:8529" \ -p "${PATH_TO_PASSWD_FILE}" \ --database "${local_DATABASE_NAME}" \ "/api/${local_FOXX_MAJOR_API_VERSION}" --reporter spec else + echo "Test: $TEST_TO_RUN" + # WARNING Foxx and arangosh arguments differ --server is used for Foxx not --server.endpoint "${FOXX_PREFIX}foxx" test -u "${local_DATABASE_USER}" \ + --server "tcp://${DATAFED_DATABASE_HOST}:8529" \ -p "${PATH_TO_PASSWD_FILE}" \ --database "${local_DATABASE_NAME}" \ - "/api/${local_FOXX_MAJOR_API_VERSION}" "$TEST_TO_RUN" --reporter spec + "/api/${local_FOXX_MAJOR_API_VERSION}" "$TEST_TO_RUN" --reporter spec --verbose fi diff --git a/core/database/tests/test_setup.sh b/core/database/tests/test_setup.sh index fbb85a3c6..023edcfb4 100755 --- a/core/database/tests/test_setup.sh +++ b/core/database/tests/test_setup.sh @@ -1,13 +1,22 @@ #!/bin/bash -# -e has been removed so that if an error occurs the PASSWORD File is deleted and not left lying around -# -u has been removed because we are checking for possible non existent env variables -set -f -o pipefail +# History +# +# -e added back in because CI jobs are not failing when there are problems in +# this script. Residual password files can be removed a different way. i.e. in +# a cleanup script associated with a CI job. +# +# -e has been removed so that if an error occurs the PASSWORD File is deleted +# and not left lying around -SCRIPT=$(realpath "$0") +set -uef -o pipefail + +SCRIPT=$(realpath "$BASH_SOURCE[0]") SOURCE=$(dirname "$SCRIPT") PROJECT_ROOT=$(realpath "${SOURCE}/../../../") source "${PROJECT_ROOT}/config/datafed.sh" +source "${PROJECT_ROOT}/scripts/dependency_versions.sh" +source "${PROJECT_ROOT}/scripts/dependency_install_functions.sh" Help() { @@ -31,21 +40,28 @@ Help() local_DATABASE_NAME="sdms" local_DATABASE_USER="root" -if [ -z "${DATAFED_DATABASE_PASSWORD}" ] +if [ -z "${DATAFED_DATABASE_HOST:-}" ] +then + local_DATAFED_DATABASE_HOST="localhost" +else + local_DATAFED_DATABASE_HOST=$(printenv DATAFED_DATABASE_HOST) +fi + +if [ -z "${DATAFED_DATABASE_PASSWORD:-}" ] then local_DATAFED_DATABASE_PASSWORD="" else local_DATAFED_DATABASE_PASSWORD=$(printenv DATAFED_DATABASE_PASSWORD) fi -if [ -z "${DATAFED_ZEROMQ_SYSTEM_SECRET}" ] +if [ -z "${DATAFED_ZEROMQ_SYSTEM_SECRET:-}" ] then local_DATAFED_ZEROMQ_SYSTEM_SECRET="" else local_DATAFED_ZEROMQ_SYSTEM_SECRET=$(printenv DATAFED_ZEROMQ_SYSTEM_SECRET) fi -if [ -z "${FOXX_MAJOR_API_VERSION}" ] +if [ -z "${FOXX_MAJOR_API_VERSION:-}" ] then local_FOXX_MAJOR_API_VERSION=$(cat ${PROJECT_ROOT}/cmake/Version.cmake | grep -o -P "(?<=FOXX_API_MAJOR).*(?=\))" | xargs ) else @@ -117,17 +133,17 @@ fi # We are now going to initialize the DataFed database in Arango, but only if sdms database does # not exist -output=$(curl --dump - --user $local_DATABASE_USER:$local_DATAFED_DATABASE_PASSWORD http://localhost:8529/_api/database/user) +output=$(curl --user $local_DATABASE_USER:$local_DATAFED_DATABASE_PASSWORD http://${local_DATAFED_DATABASE_HOST}:8529/_api/database/user) if [[ "$output" =~ .*"sdms".* ]]; then echo "SDMS already exists do nothing" else echo "Creating SDMS" - arangosh --server.password "${local_DATAFED_DATABASE_PASSWORD}" --server.username "${local_DATABASE_USER}" --javascript.execute "${PROJECT_ROOT}/core/database/foxx/db_create.js" + arangosh --server.endpoint "tcp://${local_DATAFED_DATABASE_HOST}:8529" --server.password "${local_DATAFED_DATABASE_PASSWORD}" --server.username "${local_DATABASE_USER}" --javascript.execute "${PROJECT_ROOT}/core/database/foxx/db_create.js" # Give time for the database to be created sleep 2 - arangosh --server.password "${local_DATAFED_DATABASE_PASSWORD}" --server.username "${local_DATABASE_USER}" --javascript.execute-string 'db._useDatabase("sdms"); db.config.insert({"_key": "msg_daily", "msg" : "DataFed servers will be off-line for regular maintenance every Sunday night from 11:45 pm until 12:15 am EST Monday morning."}, {overwrite: true});' - arangosh --server.password "${local_DATAFED_DATABASE_PASSWORD}" --server.username "${local_DATABASE_USER}" --javascript.execute-string "db._useDatabase(\"sdms\"); db.config.insert({ \"_key\": \"system\", \"_id\": \"config/system\", \"secret\": \"${local_DATAFED_ZEROMQ_SYSTEM_SECRET}\"}, {overwrite: true } );" + arangosh --server.endpoint "tcp://${local_DATAFED_DATABASE_HOST}:8529" --server.password "${local_DATAFED_DATABASE_PASSWORD}" --server.username "${local_DATABASE_USER}" --javascript.execute-string 'db._useDatabase("sdms"); db.config.insert({"_key": "msg_daily", "msg" : "DataFed servers will be off-line for regular maintenance every Sunday night from 11:45 pm until 12:15 am EST Monday morning."}, {overwrite: true});' + arangosh --server.endpoint "tcp://${local_DATAFED_DATABASE_HOST}:8529" --server.password "${local_DATAFED_DATABASE_PASSWORD}" --server.username "${local_DATABASE_USER}" --javascript.execute-string "db._useDatabase(\"sdms\"); db.config.insert({ \"_key\": \"system\", \"_id\": \"config/system\", \"secret\": \"${local_DATAFED_ZEROMQ_SYSTEM_SECRET}\"}, {overwrite: true } );" fi # There are apparently 3 different ways to deploy Foxx microservices, @@ -135,32 +151,27 @@ fi # Using the Arango web ui # Using node module # -# The web deployment requires manual interaction, and I could not figure out the -# syntax for the REST http endpoints with curl so we are going to try the node module +# The web deployment requires manual interaction, and I could not figure out +# the syntax for the REST http endpoints with curl so we are going to try the +# node module -## Will create the zip file in the build directory to keep datafed source code clean -#cd ../../build -## Zip up the api -#zip datafed.zip ../core/database/foxx/api/* -# -## Get the size of the file in bytes -#bytes=$(wc -c < datafed.zip) +# Will only install if it is not already installed +install_nvm +install_node -NODE_VERSION="v14.21.3" - -export NVM_DIR="$HOME/.nvm" -[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm +# Install foxx service node module +$NVM_DIR/nvm-exec npm install --global foxx-cli -nvm install "$NODE_VERSION" -nvm use "$NODE_VERSION" +FOXX_PREFIX="" +if ! command -v foxx > /dev/null 2>&1; then + FOXX_PREFIX="${DATAFED_DEPENDENCIES_INSTALL_PATH}/npm/bin/" +fi PATH_TO_PASSWD_FILE=${SOURCE}/database_temp.password -# Install foxx service node module -$NVM_DIR/nvm-exec npm install --global foxx-cli echo "$local_DATAFED_DATABASE_PASSWORD" > "${PATH_TO_PASSWD_FILE}" - # Check if database foxx services have already been installed -existing_services=$(foxx list -a -u "$local_DATABASE_USER" -p "${PATH_TO_PASSWD_FILE}" --database "$local_DATABASE_NAME") +# WARNING Foxx and arangosh arguments differ --server is used for Foxx not --server.endpoint +existing_services=$("${FOXX_PREFIX}foxx" list -a -u "$local_DATABASE_USER" -p "${PATH_TO_PASSWD_FILE}" --server "tcp://${local_DATAFED_DATABASE_HOST}:8529" --database "$local_DATABASE_NAME") echo "existing services ${existing_services}" if [[ "$existing_services" =~ .*"DataFed".* ]] diff --git a/core/database/tests/test_teardown.sh b/core/database/tests/test_teardown.sh index 09ce68a17..b7a1652a6 100755 --- a/core/database/tests/test_teardown.sh +++ b/core/database/tests/test_teardown.sh @@ -1,7 +1,14 @@ #!/bin/bash -# -e has been removed so that if an error occurs the PASSWORD File is deleted and not left lying around -set -uf -o pipefail +# History +# +# -e added back in because CI jobs are not failing when there are problems in +# this script. Residual password files can be removed a different way. i.e. in +# a cleanup script associated with a CI job. +# +# -e has been removed so that if an error occurs the PASSWORD File is deleted +# and not left lying around +set -euf -o pipefail SCRIPT=$(realpath "$0") SOURCE=$(dirname "$SCRIPT") diff --git a/core/docker/Dockerfile b/core/docker/Dockerfile index bab738f2a..a9dfb8a6a 100644 --- a/core/docker/Dockerfile +++ b/core/docker/Dockerfile @@ -55,6 +55,7 @@ SHELL ["/bin/bash", "-c"] ARG DATAFED_DIR ARG DATAFED_INSTALL_PATH +ARG DATAFED_DEPENDENCIES_INSTALL_PATH ARG BUILD_DIR ARG LIB_DIR diff --git a/core/server/AuthenticationManager.hpp b/core/server/AuthenticationManager.hpp index d648da8ab..14f316c2e 100644 --- a/core/server/AuthenticationManager.hpp +++ b/core/server/AuthenticationManager.hpp @@ -91,6 +91,7 @@ class AuthenticationManager : public IAuthenticationManager { * - PERSISTENT **/ virtual std::string getUID(const std::string &pub_key) const final; + }; } // namespace Core diff --git a/core/server/ClientWorker.cpp b/core/server/ClientWorker.cpp index 2c3084ee0..41c01ef00 100644 --- a/core/server/ClientWorker.cpp +++ b/core/server/ClientWorker.cpp @@ -1362,19 +1362,49 @@ std::unique_ptr ClientWorker::procUserGetAccessTokenRequest( string acc_tok, ref_tok; uint32_t expires_in; + bool needs_consent; + int token_type; + string scopes; + + string collection_id; + string collection_type; + + if (request->has_collection_type()) { + collection_type = request->collection_type(); + } + if (request->has_collection_id()) { + collection_id = request->collection_id(); + } m_db_client.setClient(a_uid); - m_db_client.userGetAccessToken(acc_tok, ref_tok, expires_in, log_context); + m_db_client.userGetAccessToken(acc_tok, ref_tok, expires_in, collection_id, + collection_type, needs_consent, token_type, + scopes, log_context); - if (expires_in < 300) { + if (needs_consent) { + // short circuit to reply + } else if (expires_in < 300) { DL_INFO(log_context, "Refreshing access token for " << a_uid); - - m_globus_api.refreshAccessToken(ref_tok, acc_tok, expires_in); - m_db_client.userSetAccessToken(acc_tok, expires_in, ref_tok, log_context); + if (token_type == AccessTokenType::GLOBUS_DEFAULT) { + m_globus_api.refreshAccessToken(ref_tok, acc_tok, expires_in); + m_db_client.userSetAccessToken(acc_tok, expires_in, ref_tok, log_context); + } else { + try { + m_globus_api.refreshAccessToken(ref_tok, acc_tok, expires_in); + m_db_client.userSetAccessToken( + acc_tok, expires_in, ref_tok, (AccessTokenType)token_type, + collection_id + "|" + scopes, log_context); + } catch (TraceException &e) { // NOTE: assumes refresh failed (invalid or + // failure). new token fetched will upsert + // and overwrite old values on database + needs_consent = true; + } + } } reply.set_access(acc_tok); reply.set_expires_in(expires_in); + reply.set_needs_consent(needs_consent); PROC_MSG_END(log_context); } diff --git a/core/server/ClientWorker.hpp b/core/server/ClientWorker.hpp index 832136ad5..cee872363 100644 --- a/core/server/ClientWorker.hpp +++ b/core/server/ClientWorker.hpp @@ -198,7 +198,7 @@ class ClientWorker : public nlohmann::json_schema::basic_error_handler { void schemaLoader(const nlohmann::json_uri &a_uri, nlohmann::json &a_value, LogContext log_context); - void error(const nlohmann::json_pointer> &a_ptr, + void error(const nlohmann::json::json_pointer &a_ptr, const nlohmann::json &a_inst, const std::string &a_err_msg) override { (void)a_ptr; diff --git a/core/server/DatabaseAPI.cpp b/core/server/DatabaseAPI.cpp index e931223c8..6b24f4a35 100644 --- a/core/server/DatabaseAPI.cpp +++ b/core/server/DatabaseAPI.cpp @@ -4,6 +4,7 @@ // Local public includes #include "common/DynaLog.hpp" +#include "common/SDMS.pb.h" #include "common/TraceException.hpp" #include "common/Util.hpp" @@ -11,6 +12,7 @@ #include #include #include +#include #include // Standard includes @@ -75,32 +77,23 @@ void DatabaseAPI::setClient(const std::string &a_client) { m_client = curl_easy_escape(m_curl, a_client.c_str(), 0); } -long DatabaseAPI::dbGet(const char *a_url_path, - const vector> &a_params, - libjson::Value &a_result, LogContext log_context, - bool a_log) { - (void)a_log; - - a_result.clear(); - +const std::string DatabaseAPI::buildSearchParamURL( + const char *endpoint_path, + const std::vector> ¶m_vec) { string url; - string res_json; - char error[CURL_ERROR_SIZE]; - - error[0] = 0; url.reserve(512); // TODO Get URL base from ctor url.append(m_db_url); - url.append(a_url_path); + url.append(endpoint_path); url.append("?client="); url.append(m_client); char *esc_txt; - for (vector>::const_iterator iparam = a_params.begin(); - iparam != a_params.end(); ++iparam) { + for (vector>::const_iterator iparam = param_vec.begin(); + iparam != param_vec.end(); ++iparam) { url.append("&"); url.append(iparam->first.c_str()); url.append("="); @@ -109,6 +102,25 @@ long DatabaseAPI::dbGet(const char *a_url_path, curl_free(esc_txt); } + return url; +} + +long DatabaseAPI::dbGet(const char *a_url_path, + const vector> &a_params, + libjson::Value &a_result, LogContext log_context, + bool a_log) { + (void)a_log; + + a_result.clear(); + + string res_json; + char error[CURL_ERROR_SIZE]; + + error[0] = 0; + + // TODO: construct URL outside of function + const string url = buildSearchParamURL(a_url_path, a_params); + DL_DEBUG(log_context, "get url: " << url); curl_easy_setopt(m_curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &res_json); @@ -148,37 +160,14 @@ long DatabaseAPI::dbGet(const char *a_url_path, } } -bool DatabaseAPI::dbGetRaw(const char *a_url_path, - const vector> &a_params, - string &a_result) { +bool DatabaseAPI::dbGetRaw(const std::string url, string &a_result) { a_result.clear(); - string url; char error[CURL_ERROR_SIZE]; a_result.clear(); error[0] = 0; - url.reserve(512); - - // TODO Get URL base from ctor - url.append(m_db_url); - url.append(a_url_path); - url.append("?client="); - url.append(m_client); - - char *esc_txt; - - for (vector>::const_iterator iparam = a_params.begin(); - iparam != a_params.end(); ++iparam) { - url.append("&"); - url.append(iparam->first.c_str()); - url.append("="); - esc_txt = curl_easy_escape(m_curl, iparam->second.c_str(), 0); - url.append(esc_txt); - curl_free(esc_txt); - } - curl_easy_setopt(m_curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &a_result); curl_easy_setopt(m_curl, CURLOPT_ERRORBUFFER, error); @@ -202,31 +191,13 @@ long DatabaseAPI::dbPost(const char *a_url_path, a_result.clear(); - string url; string res_json; char error[CURL_ERROR_SIZE]; error[0] = 0; - url.reserve(512); - - // TODO Get URL base from ctor - url.append(m_db_url); - url.append(a_url_path); - url.append("?client="); - url.append(m_client); - - char *esc_txt; - - for (vector>::const_iterator iparam = a_params.begin(); - iparam != a_params.end(); ++iparam) { - url.append("&"); - url.append(iparam->first.c_str()); - url.append("="); - esc_txt = curl_easy_escape(m_curl, iparam->second.c_str(), 0); - url.append(esc_txt); - curl_free(esc_txt); - } + // TODO: construct URL outside of function + const string url = buildSearchParamURL(a_url_path, a_params); curl_easy_setopt(m_curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &res_json); @@ -315,8 +286,9 @@ void DatabaseAPI::clientLinkIdentity(const std::string &a_identity, bool DatabaseAPI::uidByPubKey(const std::string &a_pub_key, std::string &a_uid) { - bool found = dbGetRaw("usr/find/by_pub_key", {{"pub_key", a_pub_key}}, a_uid); - return found; + const string url = + buildSearchParamURL("usr/find/by_pub_key", {{"pub_key", a_pub_key}}); + return dbGetRaw(url, a_uid); } bool DatabaseAPI::userGetKeys(std::string &a_pub_key, std::string &a_priv_key, @@ -355,12 +327,21 @@ void DatabaseAPI::userClearKeys(LogContext log_context) { dbGet("usr/keys/clear", {}, result, log_context); } -void DatabaseAPI::userGetAccessToken(std::string &a_acc_tok, - std::string &a_ref_tok, - uint32_t &a_expires_in, - LogContext log_context) { +void DatabaseAPI::userGetAccessToken( + std::string &a_acc_tok, std::string &a_ref_tok, uint32_t &a_expires_in, + const std::string collection_id, const std::string collection_type, + bool &needs_consent, int &token_type, // TODO: use underlying type? + std::string &scopes, LogContext log_context) { Value result; - dbGet("usr/token/get", {}, result, log_context); + std::vector> params = {}; + + if (!collection_id.empty()) { + params.push_back({"collection_id", collection_id}); + } + if (!collection_type.empty()) { + params.push_back({"collection_type", collection_type}); + } + dbGet("usr/token/get", params, result, log_context); TRANSLATE_BEGIN() @@ -369,29 +350,51 @@ void DatabaseAPI::userGetAccessToken(std::string &a_acc_tok, a_acc_tok = obj.getString("access"); a_ref_tok = obj.getString("refresh"); a_expires_in = (uint32_t)obj.getNumber("expires_in"); + needs_consent = obj.getBool("needs_consent"); + token_type = (int)obj.getNumber("token_type"); + // NOTE: scopes will be a blank string for token_type=GLOBUS_DEFAULT + scopes = obj.getString("scopes"); TRANSLATE_END(result, log_context) } void DatabaseAPI::userSetAccessToken(const std::string &a_acc_tok, - uint32_t a_expires_in, + const uint32_t a_expires_in, const std::string &a_ref_tok, + const SDMS::AccessTokenType &token_type, + const std::string &other_token_data, LogContext log_context) { string result; - dbGetRaw("usr/token/set", - {{"access", a_acc_tok}, - {"refresh", a_ref_tok}, - {"expires_in", to_string(a_expires_in)}}, - result); + std::vector> params = { + {"access", a_acc_tok}, + {"refresh", a_ref_tok}, + {"expires_in", to_string(a_expires_in)}}; + if (token_type != SDMS::AccessTokenType::ACCESS_SENTINEL) { + params.push_back({"type", to_string(token_type)}); + } + if (!other_token_data.empty()) { + params.push_back({"other_token_data", other_token_data}); + } + const string url = buildSearchParamURL("usr/token/set", params); + dbGetRaw(url, result); DL_TRACE(log_context, "token expires in: " << to_string(a_expires_in)); } +void DatabaseAPI::userSetAccessToken(const std::string &a_access_token, + const uint32_t a_expires_in, + const std::string &a_refresh_token, + LogContext log_context) { + userSetAccessToken(a_access_token, a_expires_in, a_refresh_token, + SDMS::AccessTokenType::GLOBUS_DEFAULT, "", log_context); +} + void DatabaseAPI::userSetAccessToken( const Auth::UserSetAccessTokenRequest &a_request, Anon::AckReply &a_reply, LogContext log_context) { (void)a_reply; userSetAccessToken(a_request.access(), a_request.expires_in(), - a_request.refresh(), log_context); + a_request.refresh(), a_request.type(), a_request.other(), + log_context); } void DatabaseAPI::getExpiringAccessTokens( @@ -426,7 +429,9 @@ void DatabaseAPI::getExpiringAccessTokens( void DatabaseAPI::purgeTransferRecords(size_t age) { string result; - dbGetRaw("xfr/purge", {{"age", to_string(age)}}, result); + const string url = + buildSearchParamURL("xfr/purge", {{"age", to_string(age)}}); + dbGetRaw(url, result); } void DatabaseAPI::userCreate(const Auth::UserCreateRequest &a_request, @@ -881,64 +886,63 @@ void DatabaseAPI::recordCreate(const Auth::RecordCreateRequest &a_request, Auth::RecordDataReply &a_reply, LogContext log_context) { Value result; + nlohmann::json payload; - string body; + payload["title"] = a_request.title(); - if (a_request.has_metadata()) - body.reserve(a_request.metadata().size() + 4 * 1024); - else - body.reserve(4 * 1024); - - body.append("{\"title\":\""); - body.append(escapeJSON(a_request.title())); - body.append("\""); + if (a_request.has_desc()) { + payload["desc"] = a_request.desc(); + } - if (a_request.has_desc()) - body += ",\"desc\":\"" + escapeJSON(a_request.desc()) + "\""; - if (a_request.has_alias()) - body += ",\"alias\":\"" + a_request.alias() + "\""; + if (a_request.has_alias()) { + payload["alias"] = a_request.alias(); + } if (a_request.tags_size()) { - body += ",\"tags\":["; + nlohmann::json tags = nlohmann::json::array(); for (int i = 0; i < a_request.tags_size(); i++) { - if (i) - body += ","; - body += "\"" + a_request.tags(i) + "\""; + tags.push_back(a_request.tags(i)); } - body += "]"; + payload["tags"] = tags; } - if (a_request.has_metadata()) - body += ",\"md\":" + a_request.metadata(); - if (a_request.has_sch_id()) - body += string(",\"sch_id\":\"") + a_request.sch_id() + "\""; - if (a_request.has_parent_id()) - body += ",\"parent\":\"" + a_request.parent_id() + "\""; + if (a_request.has_metadata()) { + payload["md"] = a_request.metadata(); + } + if (a_request.has_sch_id()) { + payload["sch_id"] = a_request.sch_id(); + } + if (a_request.has_parent_id()) { + payload["parent"] = a_request.parent_id(); + } if (a_request.has_external()) { - body.append(",\"external\":\""); - body.append(a_request.external() ? "true" : "false"); - body.append("\""); + payload["external"] = a_request.external(); } else { - if (a_request.has_ext()) - body += ",\"ext\":\"" + a_request.ext() + "\""; - if (a_request.has_ext_auto()) - body += - string(",\"ext_auto\":") + (a_request.ext_auto() ? "true" : "false"); - } - if (a_request.has_source()) - body += ",\"source\":\"" + a_request.source() + "\""; - if (a_request.has_repo_id()) - body += ",\"repo\":\"" + a_request.repo_id() + "\""; + if (a_request.has_ext()) { + payload["ext"] = a_request.ext(); + } + if (a_request.has_ext_auto()) { + payload["ext_auto"] = a_request.ext_auto(); + } + } + if (a_request.has_source()) { + payload["source"] = a_request.source(); + } + if (a_request.has_repo_id()) { + payload["repo"] = a_request.repo_id(); + } if (a_request.deps_size()) { - body += ",\"deps\":["; + nlohmann::json deps = nlohmann::json::array(); for (int i = 0; i < a_request.deps_size(); i++) { - body += string(i > 0 ? "," : "") + "{\"id\":\"" + a_request.deps(i).id() + - "\",\"type\":" + to_string(a_request.deps(i).type()) + "}"; + nlohmann::json dep_entry; + dep_entry["id"] = a_request.deps(i).id(); + dep_entry["type"] = to_string(a_request.deps(i).type()); + deps.push_back(dep_entry); } - body += "]"; + payload["deps"] = deps; } - body += "}"; + string body = payload.dump(-1, ' ', true); DL_DEBUG(log_context, "dat create: " << body); @@ -960,65 +964,70 @@ void DatabaseAPI::recordCreateBatch( void DatabaseAPI::recordUpdate(const Auth::RecordUpdateRequest &a_request, Auth::RecordDataReply &a_reply, libjson::Value &result, LogContext log_context) { - string body = "{\"id\":\"" + a_request.id() + "\""; - if (a_request.has_title()) - body += ",\"title\":\"" + escapeJSON(a_request.title()) + "\""; - if (a_request.has_desc()) - body += ",\"desc\":\"" + escapeJSON(a_request.desc()) + "\""; - if (a_request.has_alias()) - body += ",\"alias\":\"" + a_request.alias() + "\""; + nlohmann::json payload; + payload["id"] = a_request.id(); + if (a_request.has_title()) { + payload["title"] = a_request.title(); + } + if (a_request.has_desc()) { + payload["desc"] = a_request.desc(); + } + if (a_request.has_alias()) { + payload["alias"] = a_request.alias(); + } if (a_request.has_tags_clear() && a_request.tags_clear()) { - body += ",\"tags_clear\":true"; + payload["tags_clear"] = a_request.tags_clear(); } else if (a_request.tags_size()) { - body += ",\"tags\":["; + nlohmann::json tags = nlohmann::json::array(); for (int i = 0; i < a_request.tags_size(); i++) { - if (i) - body += ","; - body += "\"" + a_request.tags(i) + "\""; + tags.push_back(a_request.tags(i)); } - body += "]"; + payload["tags"] = tags; } if (a_request.has_metadata()) { - body += ",\"md\":" + - (a_request.metadata().size() ? a_request.metadata() : "\"\""); + payload["md"] = a_request.metadata(); if (a_request.has_mdset()) { - body += ",\"mdset\":"; - body += (a_request.mdset() ? "true" : "false"); + payload["mdset"] = a_request.mdset(); } } - if (a_request.has_sch_id()) - body += string(",\"sch_id\":\"") + a_request.sch_id() + "\""; - if (a_request.has_source()) - body += ",\"source\":\"" + a_request.source() + "\""; - if (a_request.has_ext()) - body += ",\"ext\":\"" + a_request.ext() + "\""; - if (a_request.has_ext_auto()) - body += - string(",\"ext_auto\":") + (a_request.ext_auto() ? "true" : "false"); + if (a_request.has_sch_id()) { + payload["sch_id"] = a_request.sch_id(); + } + if (a_request.has_source()) { + payload["source"] = a_request.source(); + } + if (a_request.has_ext()) { + payload["ext"] = a_request.ext(); + } + if (a_request.has_ext_auto()) { + payload["ext_auto"] = a_request.ext_auto(); + } if (a_request.dep_add_size()) { - body += ",\"dep_add\":["; + nlohmann::json dep_add = nlohmann::json::array(); for (int i = 0; i < a_request.dep_add_size(); i++) { - body += string(i > 0 ? "," : "") + "{\"id\":\"" + - a_request.dep_add(i).id() + - "\",\"type\":" + to_string(a_request.dep_add(i).type()) + "}"; + nlohmann::json dep_add_entry; + dep_add_entry["id"] = a_request.dep_add(i).id(); + dep_add_entry["type"] = to_string(a_request.dep_add(i).type()); + dep_add.push_back(dep_add_entry); } - body += "]"; + payload["dep_add"] = dep_add; } if (a_request.dep_rem_size()) { - body += ",\"dep_rem\":["; + nlohmann::json dep_rem = nlohmann::json::array(); for (int i = 0; i < a_request.dep_rem_size(); i++) { - body += string(i > 0 ? "," : "") + "{\"id\":\"" + - a_request.dep_rem(i).id() + - "\",\"type\":" + to_string(a_request.dep_rem(i).type()) + "}"; + nlohmann::json dep_rem_entry; + dep_rem_entry["id"] = a_request.dep_rem(i).id(); + dep_rem_entry["type"] = to_string(a_request.dep_rem(i).type()); + dep_rem.push_back(dep_rem_entry); } - body += "]"; + payload["dep_rem"] = dep_rem; } - body += "}"; + string body = payload.dump(-1, ' ', true); dbPost("dat/update", {}, &body, result, log_context); @@ -1039,16 +1048,20 @@ void DatabaseAPI::recordUpdateSize(const Auth::RepoDataSizeReply &a_size_rep, LogContext log_context) { libjson::Value result; - string body = "{\"records\":["; + nlohmann::json payload; - for (int i = 0; i < a_size_rep.size_size(); i++) { - if (i > 0) - body += ","; - body += "{\"id\":\"" + a_size_rep.size(i).id() + - "\",\"size\":" + to_string(a_size_rep.size(i).size()) + "}"; + nlohmann::json records = nlohmann::json::array(); + for (int i = 0; i < a_size_rep.size_size(); i++) { // size size :D + nlohmann::json record_entry; + record_entry["id"] = a_size_rep.size(i).id(); + record_entry["size"] = + to_string(a_size_rep.size(i).size()); // size size size!! :D + // TODO: the word size has lost all meaning + records.push_back(record_entry); } + payload["records"] = records; - body += "]}"; + string body = payload.dump(-1, ' ', true); dbPost("dat/update/size", {}, &body, result, log_context); } @@ -1067,15 +1080,14 @@ void DatabaseAPI::recordExport(const Auth::RecordExportRequest &a_request, LogContext log_context) { Value result; - string body = "{\"id\":["; - + nlohmann::json payload; + nlohmann::json ids = nlohmann::json::array(); for (int i = 0; i < a_request.id_size(); i++) { - if (i > 0) - body += ","; - body += "\"" + a_request.id(i) + "\""; + ids.push_back(a_request.id(i)); } + payload["id"] = ids; - body += "]}"; + string body = payload.dump(-1, ' ', true); dbPost("dat/export", {}, &body, result, log_context); @@ -1274,13 +1286,16 @@ void DatabaseAPI::generalSearch(const Auth::SearchRequest &a_request, uint32_t cnt = parseSearchRequest(a_request, qry_begin, qry_end, qry_filter, params, log_context); - string body = - "{\"mode\":" + to_string(a_request.mode()) + ",\"published\":" + - ((a_request.has_published() && a_request.published()) ? "true" - : "false") + - ",\"qry_begin\":\"" + qry_begin + "\",\"qry_end\":\"" + qry_end + - "\",\"qry_filter\":\"" + qry_filter + "\",\"params\":{" + params + - "},\"limit\":" + to_string(cnt) + "}"; + nlohmann::json payload; + payload["mode"] = to_string(a_request.mode()); + payload["published"] = a_request.has_published() && a_request.published(); + payload["qry_begin"] = qry_begin; + payload["qry_end"] = qry_end; + payload["qry_filter"] = qry_filter; + payload["params"] = "{" + params + "}"; + payload["limit"] = to_string(cnt); + + string body = payload.dump(-1, ' ', true); DL_DEBUG(log_context, "Query: [" << body << "]"); @@ -1311,32 +1326,35 @@ void DatabaseAPI::collCreate(const Auth::CollCreateRequest &a_request, Auth::CollDataReply &a_reply, LogContext log_context) { Value result; - string body = "{\"title\":\"" + escapeJSON(a_request.title()) + "\""; + nlohmann::json payload; - if (a_request.has_desc()) - body += ",\"desc\":\"" + escapeJSON(a_request.desc()) + "\""; + payload["title"] = a_request.title(); + + if (a_request.has_desc()) { + payload["desc"] = a_request.desc(); + } - if (a_request.has_alias()) - body += ",\"alias\":\"" + a_request.alias() + "\""; + if (a_request.has_alias()) { + payload["alias"] = a_request.alias(); + } - if (a_request.has_parent_id()) - body += ",\"parent\":\"" + a_request.parent_id() + "\""; + if (a_request.has_parent_id()) { + payload["parent"] = a_request.parent_id(); + } - if (a_request.has_topic()) - body += ",\"topic\":\"" + escapeJSON(a_request.topic()) + "\""; + if (a_request.has_topic()) { + payload["topic"] = a_request.topic(); + } if (a_request.tags_size()) { - body += ",\"tags\":["; + nlohmann::json tags = nlohmann::json::array(); for (int i = 0; i < a_request.tags_size(); i++) { - if (i) - body += ","; - body += "\"" + a_request.tags(i) + "\""; + tags.push_back(a_request.tags(i)); } - body += "]"; + payload["tags"] = tags; } - body += "}"; - + string body = payload.dump(-1, ' ', true); dbPost("col/create", {}, &body, result, log_context); setCollData(a_reply, result, log_context); @@ -1346,34 +1364,35 @@ void DatabaseAPI::collUpdate(const Auth::CollUpdateRequest &a_request, Auth::CollDataReply &a_reply, LogContext log_context) { Value result; - string body = "{\"id\":\"" + a_request.id() + "\""; - - if (a_request.has_title()) - body += ",\"title\":\"" + escapeJSON(a_request.title()) + "\""; + nlohmann::json payload; + payload["id"] = a_request.id(); + if (a_request.has_title()) { + payload["title"] = a_request.title(); + } - if (a_request.has_desc()) - body += ",\"desc\":\"" + escapeJSON(a_request.desc()) + "\""; + if (a_request.has_desc()) { + payload["desc"] = a_request.desc(); + } - if (a_request.has_alias()) - body += ",\"alias\":\"" + a_request.alias() + "\""; + if (a_request.has_alias()) { + payload["alias"] = a_request.alias(); + } - if (a_request.has_topic()) - body += ",\"topic\":\"" + escapeJSON(a_request.topic()) + "\""; + if (a_request.has_topic()) { + payload["topic"] = a_request.topic(); + } if (a_request.has_tags_clear() && a_request.tags_clear()) { - body += ",\"tags_clear\":true"; + payload["tags_clear"] = a_request.tags_clear(); } else if (a_request.tags_size()) { - body += ",\"tags\":["; + nlohmann::json tags = nlohmann::json::array(); for (int i = 0; i < a_request.tags_size(); i++) { - if (i) - body += ","; - body += "\"" + a_request.tags(i) + "\""; + tags.push_back(a_request.tags(i)); } - body += "]"; + payload["tags"] = tags; } - body += "}"; - + string body = payload.dump(-1, ' ', true); dbPost("col/update", {}, &body, result, log_context); setCollData(a_reply, result, log_context); @@ -1733,12 +1752,16 @@ void DatabaseAPI::queryCreate(const Auth::QueryCreateRequest &a_request, EXCEPT(1, "Invalid search request"); } - string body = - string("{") + "\"qry_begin\":\"" + qry_begin + "\",\"qry_end\":\"" + - qry_end + "\",\"qry_filter\":\"" + qry_filter + "\",\"params\":{" + - params + "},\"limit\":" + to_string(cnt) + ",\"title\":\"" + - escapeJSON(a_request.title()) + "\"" + ",\"query\":" + query_json + "}"; + nlohmann::json payload; + payload["qry_begin"] = qry_begin; + payload["qry_end"] = qry_end; + payload["qry_filter"] = qry_filter; + payload["params"] = params; + payload["limit"] = to_string(cnt); + payload["title"] = a_request.title(); + payload["query"] = nlohmann::json::parse(query_json); + string body = payload.dump(-1, ' ', true); dbPost("qry/create", {}, &body, result, log_context); setQueryData(a_reply, result, log_context); @@ -1748,10 +1771,11 @@ void DatabaseAPI::queryUpdate(const Auth::QueryUpdateRequest &a_request, Auth::QueryDataReply &a_reply, LogContext log_context) { Value result; - string body = "{\"id\":\"" + a_request.id() + "\""; + nlohmann::json payload; + payload["id"] = a_request.id(); if (a_request.has_title()) { - body += ",\"title\":\"" + escapeJSON(a_request.title()) + "\""; + payload["title"] = a_request.title(); } if (a_request.has_query()) { @@ -1772,13 +1796,15 @@ void DatabaseAPI::queryUpdate(const Auth::QueryUpdateRequest &a_request, EXCEPT(1, "Invalid search request"); } - body += ",\"qry_begin\":\"" + qry_begin + "\",\"qry_end\":\"" + qry_end + - "\",\"qry_filter\":\"" + qry_filter + "\",\"params\":{" + params + - "},\"limit\":" + to_string(cnt) + ",\"query\":" + query_json; + payload["qry_begin"] = qry_begin; + payload["qry_end"] = qry_end; + payload["qry_filter"] = qry_filter; + payload["params"] = params; + payload["limit"] = to_string(cnt); + payload["query"] = nlohmann::json::parse(query_json); } - body += "}"; - + string body = payload.dump(-1, ' ', true); dbPost("qry/update", {}, &body, result, log_context); setQueryData(a_reply, result, log_context); @@ -2132,32 +2158,33 @@ void DatabaseAPI::repoCreate(const Auth::RepoCreateRequest &a_request, LogContext log_context) { Value result; - string body = "{\"id\":\"" + a_request.id() + "\""; - body += ",\"title\":\"" + escapeJSON(a_request.title()) + "\""; - body += ",\"path\":\"" + escapeJSON(a_request.path()) + "\""; - body += ",\"pub_key\":\"" + escapeJSON(a_request.pub_key()) + "\""; - body += ",\"address\":\"" + a_request.address() + "\""; - body += ",\"endpoint\":\"" + a_request.endpoint() + "\""; - body += ",\"capacity\":\"" + to_string(a_request.capacity()) + "\""; - - if (a_request.has_desc()) - body += ",\"desc\":\"" + escapeJSON(a_request.desc()) + "\""; - if (a_request.has_domain()) - body += ",\"domain\":\"" + a_request.domain() + "\""; - if (a_request.has_exp_path()) - body += ",\"exp_path\":\"" + escapeJSON(a_request.exp_path()) + "\""; + nlohmann::json payload; + payload["id"] = a_request.id(); + payload["title"] = a_request.title(); + payload["path"] = a_request.path(); + payload["pub_key"] = a_request.pub_key(); + payload["address"] = a_request.address(); + payload["endpoint"] = a_request.endpoint(); + payload["capacity"] = to_string(a_request.capacity()); + if (a_request.has_desc()) { + payload["desc"] = a_request.desc(); + } + if (a_request.has_domain()) { + payload["domain"] = a_request.domain(); + } + if (a_request.has_exp_path()) { + payload["exp_path"] = a_request.exp_path(); + } if (a_request.admin_size() > 0) { - body += ",\"admins\":["; + nlohmann::json admins = nlohmann::json::array(); for (int i = 0; i < a_request.admin_size(); ++i) { - if (i > 0) - body += ","; - body += "\"" + a_request.admin(i) + "\""; + admins.push_back(a_request.admin(i)); } - body += "]"; + payload["admins"] = admins; } - body += "}"; + string body = payload.dump(-1, ' ', true); dbPost("repo/create", {}, &body, result, log_context); std::vector temp; @@ -2168,38 +2195,44 @@ void DatabaseAPI::repoUpdate(const Auth::RepoUpdateRequest &a_request, Auth::RepoDataReply &a_reply, LogContext log_context) { Value result; + nlohmann::json payload; + payload["id"] = a_request.id(); - string body = "{\"id\":\"" + a_request.id() + "\""; - if (a_request.has_title()) - body += ",\"title\":\"" + escapeJSON(a_request.title()) + "\""; - if (a_request.has_desc()) - body += ",\"desc\":\"" + escapeJSON(a_request.desc()) + "\""; - if (a_request.has_path()) - body += ",\"path\":\"" + escapeJSON(a_request.path()) + "\""; - if (a_request.has_exp_path()) - body += ",\"exp_path\":\"" + escapeJSON(a_request.exp_path()) + "\""; - if (a_request.has_domain()) - body += ",\"domain\":\"" + a_request.domain() + "\""; - if (a_request.has_pub_key()) - body += ",\"pub_key\":\"" + escapeJSON(a_request.pub_key()) + "\""; - if (a_request.has_address()) - body += ",\"address\":\"" + a_request.address() + "\""; - if (a_request.has_endpoint()) - body += ",\"endpoint\":\"" + a_request.endpoint() + "\""; - if (a_request.has_capacity()) - body += ",\"capacity\":\"" + to_string(a_request.capacity()) + "\""; - + if (a_request.has_title()) { + payload["title"] = a_request.title(); + } + if (a_request.has_desc()) { + payload["desc"] = a_request.desc(); + } + if (a_request.has_path()) { + payload["path"] = a_request.path(); + } + if (a_request.has_exp_path()) { + payload["exp_path"] = a_request.exp_path(); + } + if (a_request.has_domain()) { + payload["domain"] = a_request.domain(); + } + if (a_request.has_pub_key()) { + payload["pub_key"] = a_request.pub_key(); + } + if (a_request.has_address()) { + payload["address"] = a_request.address(); + } + if (a_request.has_endpoint()) { + payload["endpoint"] = a_request.endpoint(); + } + if (a_request.has_capacity()) { + payload["capacity"] = to_string(a_request.capacity()); + } if (a_request.admin_size() > 0) { - body += ",\"admins\":["; + nlohmann::json admins = nlohmann::json::array(); for (int i = 0; i < a_request.admin_size(); ++i) { - if (i > 0) - body += ","; - body += "\"" + a_request.admin(i) + "\""; + admins.push_back(a_request.admin(i)); } - body += "]"; + payload["admins"] = admins; } - body += "}"; - + string body = payload.dump(-1, ' ', true); dbPost("repo/update", {}, &body, result, log_context); std::vector temp; @@ -2859,17 +2892,15 @@ void DatabaseAPI::schemaView(const Auth::SchemaViewRequest &a_request, void DatabaseAPI::schemaCreate(const Auth::SchemaCreateRequest &a_request, LogContext log_context) { libjson::Value result; - string body = "{\"id\":\""; - body.append(a_request.id()); - body.append("\",\"desc\":\""); - body.append(escapeJSON(a_request.desc())); - body.append("\",\"pub\":"); - body.append(a_request.pub() ? "true" : "false"); - body.append(",\"sys\":"); - body.append(a_request.sys() ? "true" : "false"); - body.append(",\"def\":"); - body.append(a_request.def()); - body.append("}"); + + nlohmann::json payload; + + payload["id"] = a_request.id(); + payload["desc"] = a_request.desc(); + payload["pub"] = a_request.pub(); + payload["sys"] = a_request.sys(); + payload["def"] = a_request.def(); + string body = payload.dump(-1, ' ', true); dbPost("schema/create", {}, &body, result, log_context); } @@ -2877,39 +2908,25 @@ void DatabaseAPI::schemaCreate(const Auth::SchemaCreateRequest &a_request, void DatabaseAPI::schemaRevise(const Auth::SchemaReviseRequest &a_request, LogContext log_context) { libjson::Value result; - string body = "{"; + + nlohmann::json payload; if (a_request.has_desc()) { - body.append("\"desc\":\""); - body.append(a_request.desc()); - body.append("\""); + payload["desc"] = a_request.desc(); } if (a_request.has_pub()) { - if (body.size() > 1) - body.append(","); - - body.append("\"pub\":"); - body.append(a_request.pub() ? "true" : "false"); + payload["pub"] = a_request.pub(); } if (a_request.has_sys()) { - if (body.size() > 1) - body.append(","); - - body.append("\"sys\":"); - body.append(a_request.sys() ? "true" : "false"); + payload["sys"] = a_request.sys(); } if (a_request.has_def()) { - if (body.size() > 1) - body.append(","); - - body.append("\"def\":"); - body.append(a_request.def()); + payload["def"] = a_request.def(); } - - body.append("}"); + string body = payload.dump(-1, ' ', true); dbPost("schema/revise", {{"id", a_request.id()}}, &body, result, log_context); } @@ -2917,51 +2934,28 @@ void DatabaseAPI::schemaRevise(const Auth::SchemaReviseRequest &a_request, void DatabaseAPI::schemaUpdate(const Auth::SchemaUpdateRequest &a_request, LogContext log_context) { libjson::Value result; - string body = "{"; + nlohmann::json payload; if (a_request.has_id_new()) { - if (body.size() > 1) - body.append(","); - - body.append("\"id\":\""); - body.append(a_request.id_new()); - body.append("\""); + payload["id"] = a_request.id_new(); } if (a_request.has_desc()) { - if (body.size() > 1) - body.append(","); - - body.append("\"desc\":\""); - body.append(a_request.desc()); - body.append("\""); + payload["desc"] = a_request.desc(); } if (a_request.has_pub()) { - if (body.size() > 1) - body.append(","); - - body.append("\"pub\":"); - body.append(a_request.pub() ? "true" : "false"); + payload["pub"] = a_request.pub(); } if (a_request.has_sys()) { - if (body.size() > 1) - body.append(","); - - body.append("\"sys\":"); - body.append(a_request.sys() ? "true" : "false"); + payload["sys"] = a_request.sys(); } if (a_request.has_def()) { - if (body.size() > 1) - body.append(","); - - body.append("\"def\":"); - body.append(a_request.def()); + payload["def"] = a_request.def(); } - - body.append("}"); + string body = payload.dump(-1, ' ', true); dbPost("schema/update", {{"id", a_request.id()}}, &body, result, log_context); } @@ -3107,6 +3101,7 @@ void DatabaseAPI::taskAbort(const std::string &a_task_id, libjson::Value &a_task_reply, LogContext log_context) { libjson::Value doc(a_msg); + // TODO: json serialization --FLAG CHECK ON THIS LATER string body = doc.toString(); dbPost("task/abort", {{"task_id", a_task_id}}, &body, a_task_reply, @@ -3117,29 +3112,39 @@ void DatabaseAPI::taskInitDataGet(const Auth::DataGetRequest &a_request, Auth::DataGetReply &a_reply, libjson::Value &a_result, LogContext log_context) { - string body = "{\"id\":["; + nlohmann::json payload; + nlohmann::json ids = nlohmann::json::array(); for (int i = 0; i < a_request.id_size(); i++) { - if (i > 0) - body += ","; + ids.push_back(a_request.id(i)); + } + payload["id"] = ids; - body += "\"" + a_request.id(i) + "\""; + if (a_request.has_path()) { + payload["path"] = a_request.path(); } - body += "]"; - if (a_request.has_path()) - body += ",\"path\":\"" + a_request.path() + "\""; + if (a_request.has_encrypt()) { + payload["encrypt"] = to_string(a_request.encrypt()); + } - if (a_request.has_encrypt()) - body += ",\"encrypt\":" + to_string(a_request.encrypt()); + if (a_request.has_orig_fname() && a_request.orig_fname()) { + payload["orig_fname"] = a_request.orig_fname(); + } + + if (a_request.has_check() && a_request.check()) { + payload["check"] = a_request.check(); + } - if (a_request.has_orig_fname() && a_request.orig_fname()) - body += ",\"orig_fname\":true"; + if (a_request.has_collection_id()) { + payload["collection_id"] = a_request.collection_id(); + } - if (a_request.has_check() && a_request.check()) - body += ",\"check\":true"; + if (a_request.has_collection_type()) { + payload["collection_type"] = a_request.collection_type(); + } - body += "}"; + string body = payload.dump(-1, ' ', true); dbPost("dat/get", {}, &body, a_result, log_context); @@ -3181,22 +3186,34 @@ void DatabaseAPI::taskInitDataPut(const Auth::DataPutRequest &a_request, Auth::DataPutReply &a_reply, libjson::Value &a_result, LogContext log_context) { - string body = "{\"id\":[\"" + a_request.id() + "\"]"; + nlohmann::json payload; + payload["id"] = + nlohmann::json::array({a_request.id()}); // why is this an array? - if (a_request.has_path()) - body += ",\"path\":\"" + a_request.path() + "\""; + if (a_request.has_path()) { + payload["path"] = a_request.path(); + } - if (a_request.has_encrypt()) - body += ",\"encrypt\":" + to_string(a_request.encrypt()); + if (a_request.has_encrypt()) { + payload["encrypt"] = to_string(a_request.encrypt()); + } - if (a_request.has_ext()) - body += ",\"ext\":\"" + a_request.ext() + "\""; + if (a_request.has_ext()) { + payload["ext"] = a_request.ext(); + } - if (a_request.has_check() && a_request.check()) - body += ",\"check\":true"; + if (a_request.has_check() && a_request.check()) { + payload["check"] = a_request.check(); + } - body += "}"; + if (a_request.has_collection_id()) { + payload["collection_id"] = a_request.collection_id(); + } + if (a_request.has_collection_type()) { + payload["collection_type"] = a_request.collection_type(); + } + string body = payload.dump(-1, ' ', true); dbPost("dat/put", {}, &body, a_result, log_context); setDataPutReply(a_reply, a_result, log_context); @@ -3241,16 +3258,9 @@ void DatabaseAPI::setDataPutReply(Auth::DataPutReply &a_reply, void DatabaseAPI::taskInitRecordCollectionDelete( const std::vector &a_ids, TaskDataReply &a_reply, libjson::Value &a_result, LogContext log_context) { - string body = "{\"ids\":["; - - for (vector::const_iterator i = a_ids.begin(); i != a_ids.end(); - ++i) { - if (i != a_ids.begin()) - body += ","; - - body += "\"" + *i + "\""; - } - body += "]}"; + nlohmann::json payload; + payload["ids"] = a_ids; + string body = payload.dump(-1, ' ', true); dbPost("dat/delete", {}, &body, a_result, log_context); @@ -3261,21 +3271,21 @@ void DatabaseAPI::taskInitRecordAllocChange( const Auth::RecordAllocChangeRequest &a_request, Auth::RecordAllocChangeReply &a_reply, libjson::Value &a_result, LogContext log_context) { - string body = "{\"ids\":["; - + nlohmann::json payload; + nlohmann::json ids = nlohmann::json::array(); for (int i = 0; i < a_request.id_size(); i++) { - if (i > 0) - body += ","; + ids.push_back(a_request.id(i)); + } + payload["ids"] = ids; - body += "\"" + a_request.id(i) + "\""; + payload["repo_id"] = a_request.repo_id(); + if (a_request.has_proj_id()) { + payload["proj_id"] = a_request.proj_id(); + } + if (a_request.has_check()) { + payload["check"] = a_request.check(); } - body += "],\"repo_id\":\"" + a_request.repo_id() + "\""; - if (a_request.has_proj_id()) - body += string(",\"proj_id\":\"") + a_request.proj_id() + "\""; - if (a_request.has_check()) - body += - string(",\"check\":\"") + (a_request.check() ? "true" : "false") + "\""; - body += "}"; + string body = payload.dump(-1, ' ', true); dbPost("dat/alloc_chg", {}, &body, a_result, log_context); @@ -3301,23 +3311,22 @@ void DatabaseAPI::taskInitRecordOwnerChange( const Auth::RecordOwnerChangeRequest &a_request, Auth::RecordOwnerChangeReply &a_reply, libjson::Value &a_result, LogContext log_context) { - string body = "{\"ids\":["; - + nlohmann::json payload; + nlohmann::json ids = nlohmann::json::array(); for (int i = 0; i < a_request.id_size(); i++) { - if (i > 0) - body += ","; - - body += "\"" + a_request.id(i) + "\""; + ids.push_back(a_request.id(i)); + } + payload["ids"] = ids; + payload["coll_id"] = a_request.coll_id(); + if (a_request.has_repo_id()) { + payload["repo_id"] = a_request.repo_id(); } - body += "],\"coll_id\":\"" + a_request.coll_id() + "\""; - if (a_request.has_repo_id()) - body += ",\"repo_id\":\"" + a_request.repo_id() + "\""; // if ( a_request.has_proj_id() ) // body += string(",\"proj_id\":\"") + a_request.proj_id() + "\""; - if (a_request.has_check()) - body += - string(",\"check\":\"") + (a_request.check() ? "true" : "false") + "\""; - body += "}"; + if (a_request.has_check()) { + payload["check"] = a_request.check(); + } + string body = payload.dump(-1, ' ', true); dbPost("dat/owner_chg", {}, &body, a_result, log_context); @@ -3346,15 +3355,15 @@ void DatabaseAPI::taskInitRecordOwnerChange( void DatabaseAPI::taskInitProjectDelete( const Auth::ProjectDeleteRequest &a_request, Auth::TaskDataReply &a_reply, libjson::Value &a_result, LogContext log_context) { - string body = "{\"ids\":["; + nlohmann::json payload; + nlohmann::json ids = nlohmann::json::array(); for (int i = 0; i < a_request.id_size(); i++) { - if (i > 0) - body += ","; - - body += "\"" + a_request.id(i) + "\""; + ids.push_back(a_request.id(i)); } - body += "]}"; + payload["ids"] = ids; + + string body = payload.dump(-1, ' ', true); dbPost("prj/delete", {}, &body, a_result, log_context); @@ -3530,31 +3539,24 @@ void DatabaseAPI::taskUpdate(const std::string &a_id, LogContext log_context, if (!a_status && !a_progress && !a_state) return; - string body = "{"; - string delim = ""; + nlohmann::json payload; if (a_status) { - body += "\"status\":" + to_string(*a_status); - delim = ","; + payload["status"] = to_string(*a_status); } if (a_message) { - body += delim + "\"message\":\"" + *a_message + "\""; - if (!delim.size()) - delim = ","; + payload["message"] = *a_message; } if (a_progress) { - body += delim + "\"progress\":" + to_string(*a_progress); - if (!delim.size()) - delim = ","; + payload["progress"] = to_string(*a_progress); } if (a_state) { - body += delim + "\"state\":" + a_state->toString(); + payload["state"] = a_state->toString(); } - - body += "}"; + string body = payload.dump(-1, ' ', true); Value result; dbPost("task/update", {{"task_id", a_id}}, &body, result, log_context); @@ -3622,10 +3624,72 @@ void DatabaseAPI::taskPurge(uint32_t a_age_sec, LogContext log_context) { dbGet("task/purge", {{"age_sec", to_string(a_age_sec)}}, result, log_context); } -void DatabaseAPI::metricsUpdateMsgCounts( +/* TODO: verify formatting + old format: + { + timestamp: .., + total: .., + uids: { + first_of_tuple[0]: { + tot: second_of_tuple[0], + msg: { + second_of_tuple[0]_tuple_0: second_of_tuple[0]_tuple_1, + second_of_tuple[1]_tuple_0: second_of_tuple[1]_tuple_1, + ... + } + } + first_of_tuple[1]: ... + } + } + new format: + { + timestamp: .., + total: .., + uids: { + first_of_tuple[0]: { + tot: second_of_tuple[0], + msg: { + second_of_tuple[0]_tuple_0: second_of_tuple[0]_tuple_1, + second_of_tuple[1]_tuple_0: second_of_tuple[1]_tuple_1, + } + } + } + } + */ + +std::string DatabaseAPI::newJsonMetricParse( uint32_t a_timestamp, uint32_t a_total, - const std::map> &a_metrics, - LogContext log_context) { + const std::map> &a_metrics) { + map>::const_iterator u; + map::const_iterator m; + nlohmann::json payload; + payload["timestamp"] = to_string(a_timestamp); + payload["total"] = to_string(a_total); + + nlohmann::json uids; + for (u = a_metrics.begin(); u != a_metrics.end(); ++u) { + nlohmann::json uid_body; + uid_body["tot"] = to_string(u->second.at(0)); + nlohmann::json uid_msg; + for (m = u->second.begin(); m != u->second.end(); ++m) { + if (m->first != 0) { + uid_msg[to_string(m->first)] = to_string(m->second); + } + } + uid_body["msg"] = uid_msg; + + uids[u->first] = uid_body; + } + + payload["uids"] = uids; + string body = payload.dump(-1, ' ', true); + return body; +} + +// TODO: verify and remove +std::string DatabaseAPI::oldJsonMetricParse( + uint32_t a_timestamp, uint32_t a_total, + const std::map> &a_metrics) { map>::const_iterator u; map::const_iterator m; string body = "{\"timestamp\":" + to_string(a_timestamp) + @@ -3655,6 +3719,29 @@ void DatabaseAPI::metricsUpdateMsgCounts( } body += "}}"; + return body; +} + +void DatabaseAPI::metricsUpdateMsgCounts( + uint32_t a_timestamp, uint32_t a_total, + const std::map> &a_metrics, + LogContext log_context) { + + string body; + string new_body = newJsonMetricParse(a_timestamp, a_total, a_metrics); + string old_body = oldJsonMetricParse(a_timestamp, a_total, a_metrics); + + if (new_body == old_body) { + // on match use safer serialization + body = new_body; + } else { + body = old_body; + DL_WARNING( + log_context, + "Serialized metric bodies did not match, new serialization yielded:\n" + << new_body << "\n old serialization yielded:\n" + << old_body); + } libjson::Value result; @@ -3817,9 +3904,9 @@ uint32_t DatabaseAPI::parseSearchRequest(const Auth::SearchRequest &a_request, "name:name,alias:i.alias") + (a_request.mode() == SM_DATA ? ",size:i.size,md_err:i.md_err" : "") + "}"; - a_qry_begin = escapeJSON(a_qry_begin); - a_qry_end = escapeJSON(a_qry_end); - a_qry_filter = escapeJSON(a_qry_filter); + a_qry_begin = a_qry_begin; + a_qry_end = a_qry_end; + a_qry_filter = a_qry_filter; return cnt; } @@ -3845,8 +3932,8 @@ string DatabaseAPI::parseSearchTextPhrase(const string &a_phrase, There is no NOR operator since this would produce low-specificity queryies. - If terms are included before a category is specified, these terms apply to all - categories (as if they were copied as-is into each category phrase) + If terms are included before a category is specified, these terms apply to + all categories (as if they were copied as-is into each category phrase) Categories may only be specified once. @@ -3856,8 +3943,8 @@ string DatabaseAPI::parseSearchTextPhrase(const string &a_phrase, The order of categories and terms does not matter, they are grouped by operator in an expression such as: - (term1 or term2 or term3) and term4 and term5 and not term6 and not term7 - OR terms AND terms NAND terms + (term1 or term2 or term3) and term4 and term5 and not term6 and not + term7 OR terms AND terms NAND terms */ static map cat_map = {{"t:", 1}, {"title:", 1}, {"d:", 2}, {"desc:", 2}, @@ -4112,7 +4199,8 @@ std::string DatabaseAPI::parseSearchMetadata(const std::string &a_query, switch (state) { case PS_SINGLE_QUOTE: // Single quote (not escaped) - // Must account for escaped quotes (\') and preceeding escaped backslashes + // Must account for escaped quotes (\') and preceeding escaped + // backslashes // (\\) For example: 'abc\'' - quote is escaped 'abc\\'' - backslash is // escaped, not quote 'abc\\\'' - backslash and quote are escaped // 'abc\\\\'' - two backslashes are escaped, and quote @@ -4200,8 +4288,8 @@ std::string DatabaseAPI::parseSearchMetadata(const std::string &a_query, state = PS_STOP; } - // Determine if identifier needs to be prefixed with iterator by testing - // against allowed identifiers + // Determine if identifier needs to be prefixed with iterator by + // testing against allowed identifiers if (tmp == "desc") { result.append(a_iter); result.append("['desc']"); diff --git a/core/server/DatabaseAPI.hpp b/core/server/DatabaseAPI.hpp index 627dfcb74..ce5e0a649 100644 --- a/core/server/DatabaseAPI.hpp +++ b/core/server/DatabaseAPI.hpp @@ -51,10 +51,23 @@ class DatabaseAPI { void userSetKeys(const std::string &a_pub_key, const std::string &a_priv_key, LogContext log_context); void userClearKeys(LogContext log_context); - void userSetAccessToken(const std::string &a_acc_tok, uint32_t a_expires_in, - const std::string &a_ref_tok, LogContext log_context); + void userSetAccessToken(const std::string &a_acc_tok, + const uint32_t a_expires_in, + const std::string &a_ref_tok, + const SDMS::AccessTokenType &token_type, + const std::string &other_token_data, + LogContext log_context); + void userSetAccessToken(const std::string &a_access_token, + const uint32_t a_expires_in, + const std::string &a_refresh_token, + LogContext log_context); void userGetAccessToken(std::string &a_acc_tok, std::string &a_ref_tok, - uint32_t &a_expires_in, LogContext log_context); + uint32_t &a_expires_in, + const std::string collection_id, + const std::string collection_type, + bool &needs_consent, + int &token_type, // TODO: use underlying type? + std::string &scopes, LogContext log_context); void getExpiringAccessTokens(uint32_t a_expires_in, std::vector &a_expiring_tokens, LogContext log_context); @@ -324,10 +337,7 @@ class DatabaseAPI { long dbGet(const char *a_url_path, const std::vector> &a_params, libjson::Value &a_result, LogContext, bool a_log = true); - bool - dbGetRaw(const char *a_url_path, - const std::vector> &a_params, - std::string &a_result); + bool dbGetRaw(const std::string url, std::string &a_result); long dbPost(const char *a_url_path, const std::vector> &a_params, const std::string *a_body, libjson::Value &a_result, LogContext); @@ -406,6 +416,18 @@ class DatabaseAPI { std::string parseSearchIdAlias(const std::string &a_query, const std::string &a_iter); + const std::string buildSearchParamURL( + const char *endpoint_path, + const std::vector> ¶m_vec); + + std::string newJsonMetricParse( + uint32_t a_timestamp, uint32_t a_total, + const std::map> &a_metrics); + + std::string oldJsonMetricParse( + uint32_t a_timestamp, uint32_t a_total, + const std::map> &a_metrics); + CURL *m_curl; char *m_client; std::string m_client_uid; diff --git a/core/server/TaskWorker.cpp b/core/server/TaskWorker.cpp index bc8cf0e63..1278db017 100644 --- a/core/server/TaskWorker.cpp +++ b/core/server/TaskWorker.cpp @@ -11,9 +11,11 @@ #include "common/ICommunicator.hpp" #include "common/IMessage.hpp" #include "common/MessageFactory.hpp" +#include "common/SDMS.pb.h" #include "common/SocketOptions.hpp" // Standard includes +#include "common/TraceException.hpp" #include "unistd.h" #include #include @@ -21,7 +23,7 @@ using namespace std; using namespace libjson; -//#define TASK_DELAY sleep(60); +// #define TASK_DELAY sleep(60); #define TASK_DELAY namespace SDMS { @@ -64,7 +66,7 @@ void TaskWorker::workerThread(LogContext log_context) { string err_msg; Value task_cmd; Value::ObjectIter iter; - uint32_t cmd; + uint32_t cmd = 0; int step; bool first; int db_connection_backoff; @@ -208,16 +210,43 @@ TaskWorker::cmdRawDataTransfer(TaskWorker &me, const Value &a_task_params, string acc_tok = obj.getString("acc_tok"); string ref_tok = obj.getString("ref_tok"); uint32_t expires_in = obj.getNumber("acc_tok_exp_in"); + uint32_t token_type = + obj.getNumber("token_type"); // TODO: use enum if possible + string collection_id; + string scopes; + if (token_type == AccessTokenType::GLOBUS_TRANSFER) { + // fields must be present on transfer tokens + scopes = obj.getString("scopes"); + collection_id = obj.getString("collection_id"); + } DL_TRACE(log_context, ">>>> Token Expires in: " << expires_in); if (expires_in < 3600) { - DL_DEBUG(log_context, "Refreshing access token for " - << uid << " (expires in " << expires_in << ")"); - me.m_glob.refreshAccessToken(ref_tok, acc_tok, expires_in); me.m_db.setClient(uid); - me.m_db.userSetAccessToken(acc_tok, expires_in, ref_tok, log_context); + + if (token_type == + AccessTokenType::GLOBUS_DEFAULT) { // TODO: this work is mostly + // duplicated from ClientWorker + DL_DEBUG(log_context, "Refreshing access token for " + << uid << " (expires in " << expires_in << ")"); + + me.m_glob.refreshAccessToken(ref_tok, acc_tok, expires_in); + me.m_db.userSetAccessToken(acc_tok, expires_in, ref_tok, log_context); + } else { + try { + me.m_glob.refreshAccessToken(ref_tok, acc_tok, expires_in); + me.m_db.userSetAccessToken(acc_tok, expires_in, ref_tok, + (AccessTokenType)token_type, + collection_id + "|" + scopes, log_context); + } catch (TraceException &e) { + DL_ERROR(log_context, + "Failure when refreshing Globus Mapped collection token for " + << uid << " on collection " << collection_id); + throw e; + } + } } if (type == TT_DATA_GET || type == TT_DATA_PUT) { diff --git a/core/server/main.cpp b/core/server/main.cpp index b75ac294d..2654a0619 100644 --- a/core/server/main.cpp +++ b/core/server/main.cpp @@ -15,6 +15,7 @@ // Standard includes #include "Config.hpp" +#include #include #include #include @@ -30,7 +31,7 @@ namespace po = boost::program_options; int main(int a_argc, char **a_argv) { global_logger.setSysLog(false); global_logger.addStream(std::cerr); - global_logger.setLevel(LogLevel::INFO); + global_logger.setLevel(LogLevel::TRACE); LogContext log_context; log_context.thread_name = "core_server"; log_context.thread_id = 0; @@ -46,6 +47,10 @@ int main(int a_argc, char **a_argv) { string cfg_file; bool gen_keys = false; + // Note: we may want to dynamically choose type at compile time + // based on underlying type of LogLevel enum + unsigned int cfg_log_level = UINT_MAX; + po::options_description opts("Options"); opts.add_options()("help,?", "Show help")( @@ -80,7 +85,8 @@ int main(int a_argc, char **a_argv) { "Number of task worker threads")("cfg", po::value(&cfg_file), "Use config file for options")( "gen-keys", po::bool_switch(&gen_keys), - "Generate new server keys then exit"); + "Generate new server keys then exit")( + "log-level", po::value(&cfg_log_level), "Set log level"); try { po::variables_map opt_map; @@ -147,6 +153,44 @@ int main(int a_argc, char **a_argv) { return 0; } + if (cfg_log_level != UINT_MAX) { + if (cfg_log_level >= + static_cast(LogLevel::LAST_SENTINEL)) { + DL_ERROR(log_context, + "Invalid log level provided, defaulting to INFO"); + } else { + LogLevel cast_log_level = static_cast(cfg_log_level); + std::string str_log_level = ""; + switch (cast_log_level) { + case LogLevel::CRITICAL: + str_log_level = "CRITICAL"; + break; + case LogLevel::ERROR: + str_log_level = "ERROR"; + break; + case LogLevel::WARNING: + str_log_level = "WARNING"; + break; + case LogLevel::INFO: + str_log_level = "INFO"; + break; + case LogLevel::DEBUG: + str_log_level = "DEBUG"; + break; + case LogLevel::TRACE: + str_log_level = "TRACE"; + break; + case LogLevel::LAST_SENTINEL: + str_log_level = "INVALID"; // should never be reached + EXCEPT_PARAM(1, "Unexpected state when setting log level, " + + to_string(cfg_log_level)); + break; + } + std::string log_message = "Setting log level to " + str_log_level; + DL_INFO(log_context, log_message); + global_logger.setLevel(cast_log_level); + } + } } catch (po::unknown_option &e) { DL_ERROR(log_context, "Options error: " << e.what()); return 1; diff --git a/core/server/tests/CMakeLists.txt b/core/server/tests/CMakeLists.txt index 932023f93..96a5ce6f4 100644 --- a/core/server/tests/CMakeLists.txt +++ b/core/server/tests/CMakeLists.txt @@ -1,3 +1,3 @@ -if( ENABLE_UNIT_TESTS ) +if( ENABLE_UNIT_TESTS OR ENABLE_MEMORY_TESTS ) add_subdirectory(unit) -endif() +endif( ENABLE_UNIT_TESTS OR ENABLE_MEMORY_TESTS ) diff --git a/core/server/tests/unit/CMakeLists.txt b/core/server/tests/unit/CMakeLists.txt index 3c46fb112..f42b95ef9 100644 --- a/core/server/tests/unit/CMakeLists.txt +++ b/core/server/tests/unit/CMakeLists.txt @@ -10,6 +10,11 @@ foreach(PROG if(BUILD_SHARED_LIBS) target_compile_definitions(unit_${PROG} PRIVATE BOOST_TEST_DYN_LINK) endif() - add_test(unit_${PROG} unit_${PROG}) + if ( ENABLE_UNIT_TESTS ) + add_test(unit_${PROG} unit_${PROG}) + endif( ENABLE_UNIT_TESTS ) + if ( ENABLE_MEMORY_TESTS ) + add_test(NAME memory_${PROG} COMMAND valgrind --leak-check=full --error-exitcode=1 $) + endif( ENABLE_MEMORY_TESTS ) endforeach(PROG) diff --git a/core/server/tests/unit/test_AuthMap.cpp b/core/server/tests/unit/test_AuthMap.cpp index a337e8447..2699629fa 100644 --- a/core/server/tests/unit/test_AuthMap.cpp +++ b/core/server/tests/unit/test_AuthMap.cpp @@ -4,10 +4,24 @@ #include #include +// Local private includes #include "AuthMap.hpp" +// Third party includes +#include + using namespace SDMS::Core; +struct GlobalProtobufTeardown { + ~GlobalProtobufTeardown() { + // This is the teardown function that runs once at the end + google::protobuf::ShutdownProtobufLibrary(); + } +}; + +// Declare a global fixture instance +BOOST_GLOBAL_FIXTURE(GlobalProtobufTeardown); + BOOST_AUTO_TEST_SUITE(AuthMapTest) BOOST_AUTO_TEST_CASE(testing_AuthMap) { diff --git a/core/server/tests/unit/test_AuthenticationManager.cpp b/core/server/tests/unit/test_AuthenticationManager.cpp index ecaa6a7b2..0cded3e03 100644 --- a/core/server/tests/unit/test_AuthenticationManager.cpp +++ b/core/server/tests/unit/test_AuthenticationManager.cpp @@ -10,6 +10,7 @@ #include #include #include +#include // Standard includes #include @@ -17,6 +18,16 @@ using namespace SDMS::Core; +struct GlobalProtobufTeardown { + ~GlobalProtobufTeardown() { + // This is the teardown function that runs once at the end + google::protobuf::ShutdownProtobufLibrary(); + } +}; + +// Declare a global fixture instance +BOOST_GLOBAL_FIXTURE(GlobalProtobufTeardown); + BOOST_AUTO_TEST_SUITE(AuthenticationManagerTest) BOOST_AUTO_TEST_CASE(testing_AuthenticationManagerPurgeTrans) { diff --git a/doc_source/source/admin/install_bare_metal.rst b/doc_source/source/admin/install_bare_metal.rst index ea309f773..44171394d 100644 --- a/doc_source/source/admin/install_bare_metal.rst +++ b/doc_source/source/admin/install_bare_metal.rst @@ -132,10 +132,14 @@ Steps to deploy DataFed Database: 1. Download and install the latest ArangoDB server package for your host operating system. (see example, below) -Example download/install of ArangoDB 3.7 for Ubuntu:: +Example download/install of ArangoDB 3.12.4 for Ubuntu:: - wget https://download.arangodb.com/arangodb37/Community/Linux/arangodb3_3.7.10-1_amd64.deb - sudo apt install ./arangodb3_3.7.10-1_amd64.deb + curl -OL https://download.arangodb.com/arangodb312/DEBIAN/Release.key + sudo apt-key add - < Release.key + echo 'deb https://download.arangodb.com/arangodb312/DEBIAN/ /' | sudo tee /etc/apt/sources.list.d/arangodb.list + sudo apt-get install apt-transport-https + sudo apt-get update + sudo apt-get install arangodb3 It should start automatically with an install but to run the arangodb service, you can also interact with it via systemctl:: @@ -311,4 +315,4 @@ Networking If the web server and core server are on different machines you will need to ensure that they can communicate, this will require exchanging the public keys -that are in the /opt/datafed/keys folder. \ No newline at end of file +that are in the /opt/datafed/keys folder. diff --git a/doc_source/source/admin/install_docker.rst b/doc_source/source/admin/install_docker.rst index 289f2dc42..2fbebce14 100644 --- a/doc_source/source/admin/install_docker.rst +++ b/doc_source/source/admin/install_docker.rst @@ -48,12 +48,16 @@ To deploy DataFed, its containers must be built from source code hosted on `GitH Prior to building DataFed, Docker must be installed. The following examples are based on Debian. -Downloading DataFed:: +Downloading DataFed: + +.. code-block:: bash git clone https://github.com/ORNL/DataFed.git If you are deploying in development mode, the next step is to enter configuration options that are listed in ./.env To -generate a template for this file you will first need to run:: +generate a template for this file you will first need to run: + +.. code-block:: bash ./compose/all/generate_env.sh @@ -82,7 +86,9 @@ automatically configure much of the setup. Building Containers =================== -To build the containers you must simply run:: +To build the containers you must simply run: + +.. code-block:: bash ./compose/all/build_containers_for_compose.sh @@ -92,8 +98,17 @@ This is due to dependency caching, since the first build is what builds and cach Running the Containers (Development) ==================================== +Note: Before running the containers, ensure that the necessary directories are created on the host machine with the +correct permissions. You can create the directories by running the following script: + +.. code-block:: bash + + ./scripts/globus/setup_collection_directory.sh all + For convenience, development installations are fully supported utilizing docker compose. -Once fully built and configured, the development instance can be started with the following commands:: +Once fully built and configured, the development instance can be started with the following commands: + +.. code-block:: bash ./compose/all/unset_env.sh docker compose -f ./compose/all/compose.yml up @@ -106,7 +121,9 @@ Running the Containers (Production) Running the containers in production is a similar process to running them in development mode, except the Docker containers are run manually rather than being run by Docker compose. -To begin, you will want to create a Docker network to attach the containers to so that they may communicate:: +To begin, you will want to create a Docker network to attach the containers to so that they may communicate: + +.. code-block:: bash docker network create datafed-network @@ -115,7 +132,9 @@ Following are examples of docker run commands for each service Core Service ------------ -Here is an example for the core service:: +Here is an example for the core service: + +.. code-block:: bash docker run -d \ --restart=always \ @@ -141,7 +160,9 @@ Here is an example for the core service:: Web Service ------------ -Here is an example for the web service:: +Here is an example for the web service: + +.. code-block:: bash docker run -d \ --restart=always \ @@ -169,7 +190,9 @@ Here is an example for the web service:: Repository Service ------------ -Here is an example for the repository service:: +Here is an example for the repository service: + +.. code-block:: bash docker run -d \ --restart=always \ @@ -197,7 +220,9 @@ Here is an example for the repository service:: Globus Service ------------ -Here is an example for the Globus Connect Server service:: +Here is an example for the Globus Connect Server service: + +.. code-block:: bash docker run -d \ --restart=always \ @@ -238,7 +263,9 @@ Nginx Service This service is not necessary for Datafed to function, however it is included here as a convenience, as it will allow you to setup temporary redirects for maintenance, rate limiting, better security using a standardized tool. -Here is an example:: +Here is an example: + +.. code-block:: bash docker run -d \ --restart=always \ diff --git a/doc_source/source/dev/design.rst b/doc_source/source/dev/design.rst index 4671b2bb5..81adca6fe 100644 --- a/doc_source/source/dev/design.rst +++ b/doc_source/source/dev/design.rst @@ -2,3 +2,4 @@ Architecture & Design ===================== +DataFed is designed in part as a hub and spoke model. Where the metadata services act as the hub and the spokes are DataFed managed repositories that connect to it. diff --git a/doc_source/source/dev/project.rst b/doc_source/source/dev/project.rst index b77d820d4..844480249 100644 --- a/doc_source/source/dev/project.rst +++ b/doc_source/source/dev/project.rst @@ -14,3 +14,7 @@ Personnel - Dale Stansberry, Sr. Software Developer - PI, architect, lead developer of the DataFed Project - Suhas Somnath, Computer Scientist - Scientific user requirements and Python interface development - Jessica Breet, Data Scientist - Scientific user requirements and system testing +- Josh Brown, Software Engineer +- Aaron Perez, Full Stack +- Blake, Nedved, Sotware Developer +- Tony, Ramirez, Software Developer diff --git a/doc_source/source/dev/testing.rst b/doc_source/source/dev/testing.rst new file mode 100644 index 000000000..99555357b --- /dev/null +++ b/doc_source/source/dev/testing.rst @@ -0,0 +1,76 @@ +======= +Testing +======= + +If you're developing DataFed, there are several ways to test the application. This guide focuses on running **unit tests** for the Foxx microservices used with ArangoDB. + +Unit Testing with Foxx Microservices +==================================== + +ArangoDB supports running small applications called *Foxx microservices*. You can run unit tests for these services without standing up the full DataFed application by using a standalone ArangoDB instance. + +1. Start an ArangoDB Container +--------------------------- + +First, pull the official ArangoDB Docker image: + +NOTE: the use of 3.12.4 is what has been tested, other minor versions changes of ArangoDB should also work. + +.. code-block:: bash + + docker pull arangodb/arangodb:3.12.4 + +Next, run the container, specifying a root password for the database: + +.. code-block:: bash + + docker run -d \ + -e ARANGO_ROOT_PASSWORD="" \ + -p 8529:8529 \ + arangodb/arangodb:3.12.4 + +You now have a running ArangoDB instance to install Foxx services and run tests against. + +2. Build Docker Images +------------------- + +To run Foxx tests, you'll need two images: +- A **dependencies image** +- A **Foxx services image** + +Assuming you're at the root of the DataFed repository: + +**Build the dependencies image:** + +.. code-block:: bash + + docker build -f ./docker/Dockerfile.dependencies . -t datafed-dependencies:latest + +**Build the Foxx services image:** + +.. code-block:: bash + + docker build \ + --build-arg DEPENDENCIES=datafed-dependencies:latest \ + -f ./docker/Dockerfile.foxx . \ + -t datafed-foxx:latest + +3. Run Unit Tests +-------------- + +Now, run the Foxx container with the appropriate environment variables to install the services and enable testing: + +DATAFED_DATABASE_PASSWORD, and DATAFED_ZEROMQ_SYSTEM_SECRET can be anything but they should be consistent with what is in the config/datafed.sh file. + +.. code-block:: bash + + docker run \ + -e DATAFED_DATABASE_PASSWORD="" \ + -e DATAFED_ZEROMQ_SYSTEM_SECRET="" \ + -e INSTALL_FOXX=ON \ + -e ENABLE_FOXX_TESTS=TRUE \ + --network=host \ + datafed-foxx:latest + +This will deploy the Foxx microservices and automatically execute the unit tests against the ArangoDB instance. + diff --git a/doc_source/source/index.rst b/doc_source/source/index.rst index 3d902bf26..878350dea 100644 --- a/doc_source/source/index.rst +++ b/doc_source/source/index.rst @@ -75,6 +75,7 @@ by subsequent documents on this site. dev/project dev/design + dev/testing dev/release dev/roadmap diff --git a/doc_source/source/user/web/portal.rst b/doc_source/source/user/web/portal.rst index 490fdf364..c4ba8e927 100644 --- a/doc_source/source/user/web/portal.rst +++ b/doc_source/source/user/web/portal.rst @@ -97,6 +97,175 @@ Search The ``Search`` tab below the action buttons allows users to query DataFed for data matching a specified metadata expression within a specified scope. +Schemas +------- + +DataFed currently supports schema creation for records through the web portal. + +Schema Creation +^^^^^^^^^^^^^^^ + +To create a new schema, navigate to the main dashboard and click the ``Schemas`` button. This will open the ``Create New Schema`` dialog, which consists of three separate tabs: ``General``, ``Definition``, and ``References``. + +- **General Tab**: + In this tab, you must provide a valid string identifier (`ID`) and a brief `Description` of the schema. + +- **Definition Tab**: + This tab requires a **valid JSON Schema definition**. DataFed conforms to the official [JSON Schema standard](https://json-schema.org/). + +- **References Tab**: + This section lists locations where the schema is referenced within DataFed. + +### Example Schema Definition + +The following is an example of a JSON schema definition used in DataFed: + +.. code-block:: json + { + "properties": { + "Cat": { + "properties": { + "Height": { + "type": "string" + }, + "LastSeen_DateTime": { + "type": "string" + }, + "Name": { + "type": "string" + }, + "Photo_Date": { + "type": "string" + }, + "Weight": { + "type": "string" + } + }, + "required": [ + "Name", + "Photo_Date", + "Height", + "Weight", + "LastSeen_DateTime" + ], + "type": "object" + }, + "Owner": { + "properties": { + "Address": { + "type": "string" + }, + "Name": { + "type": "string" + } + }, + "required": [ + "Name", + "Address" + ], + "type": "object" + } + }, + "required": [ + "Cat", + "Owner" + ], + "type": "object" + } + +### Example Schema Using Enums + +The following example demonstrates the use of **enums** to enforce predefined choices for various fields: + +.. code-block:: json + { + "properties": { + "data_format": { + "description": "The format in which experimental data is stored.", + "enum": [ + "CSV", + "JSON", + "HDF5", + "NetCDF" + ], + "type": "string" + }, + "experiment_type": { + "description": "The type of scientific experiment being conducted.", + "enum": [ + "Physics", + "Chemistry", + "Biology", + "Astronomy", + "Materials Science" + ], + "type": "string" + }, + "instrument": { + "description": "The scientific instrument used for measurements.", + "enum": [ + "Spectrometer", + "Microscope", + "X-ray Diffractometer", + "Mass Spectrometer", + "Electron Microscope" + ], + "type": "string" + }, + "measurement_unit": { + "description": "The SI unit of measurement used in the experiment.", + "enum": [ + "meters", + "kilograms", + "seconds", + "kelvin", + "moles", + "amperes", + "candela" + ], + "type": "string" + }, + "status": { + "description": "The current status of the experiment.", + "enum": [ + "Pending", + "In Progress", + "Completed", + "Failed" + ], + "type": "string" + } + }, + "required": [ + "experiment_type", + "measurement_unit", + "instrument", + "status", + "data_format" + ], + "type": "object" + } + +### Example Schema Using References + +The following example demonstrates the use of **references** to existing schemas, assuming the previous schema was saved as **equipment** with verison number 0 **equipment:0**: + +.. code-block:: json + { + "properties": { + "equipment": { + "$ref": "equipment:0" + }, + "voltage": { + "type": "number" + } + }, + "required": [ + "voltage", + "equipment" + ], + "type": "object" + } Transfers --------- diff --git a/docker/Dockerfile.dependencies b/docker/Dockerfile.dependencies index 6d92130ce..8788a2b87 100644 --- a/docker/Dockerfile.dependencies +++ b/docker/Dockerfile.dependencies @@ -14,6 +14,7 @@ ARG BUILD_DIR ARG DATAFED_INSTALL_PATH ARG DEBIAN_FRONTEND=noninteractive ARG LIB_DIR +ARG DATAFED_DEPENDENCIES_INSTALL_PATH ENV BUILD_DIR="${BUILD_DIR}" ENV DATAFED_DIR="${DATAFED_DIR}" diff --git a/docker/Dockerfile.foxx b/docker/Dockerfile.foxx index 9c4dcbaa9..29b936d99 100644 --- a/docker/Dockerfile.foxx +++ b/docker/Dockerfile.foxx @@ -22,12 +22,19 @@ ARG BUILD_DIR ARG DATAFED_INSTALL_PATH ARG DATAFED_DEPENDENCIES_INSTALL_PATH +# WARNING +# +# Do not overwrite PATH here, overwriting PATH could lead to inconsistencies in +# your build. Docker will automatically pull from the host env if declared here. +# If PATH is different on the host you could create a broken container. + ENV BUILD_DIR="${BUILD_DIR}" ENV DATAFED_DIR="${DATAFED_DIR}" ENV DATAFED_DEPENDENCIES_INSTALL_PATH="${DATAFED_DEPENDENCIES_INSTALL_PATH}" -ENV PATH=${DATAFED_DEPENDENCIES_INSTALL_PATH}/bin:${PATH} ENV DATAFED_INSTALL_PATH="$DATAFED_INSTALL_PATH" ENV DATAFED_DEFAULT_LOG_PATH="$DATAFED_INSTALL_PATH/logs" +# Set to false by default to avoid wiping the database +ENV ENABLE_FOXX_TESTS="FALSE" COPY ./core/CMakeLists.txt ${BUILD_DIR}/core/CMakeLists.txt COPY ./CMakeLists.txt ${BUILD_DIR} @@ -46,12 +53,12 @@ RUN mkdir -p ${DATAFED_DIR} RUN mkdir -p ${DATAFED_INSTALL_PATH} RUN mkdir -p ${DATAFED_DEFAULT_LOG_PATH} -RUN curl -OL https://download.arangodb.com/arangodb311/DEBIAN/Release.key; apt-key add - < Release.key +RUN curl -OL https://download.arangodb.com/arangodb312/DEBIAN/Release.key; apt-key add - < Release.key # RUN echo 'deb https://download.arangodb.com/arangodb311/DEBIAN/ /' | tee /etc/apt/sources.list.d/arangodb.list # If trust the site but the gpg key has expired can add [trusted=yes] # i.e. -RUN echo 'deb [trusted=yes] https://download.arangodb.com/arangodb311/DEBIAN/ /' | tee /etc/apt/sources.list.d/arangodb.list +RUN echo 'deb [trusted=yes] https://download.arangodb.com/arangodb312/DEBIAN/ /' | tee /etc/apt/sources.list.d/arangodb.list RUN apt update RUN apt install arangodb3-client -y RUN arangosh --version diff --git a/docker/Dockerfile.runtime b/docker/Dockerfile.runtime index e63864ec5..6742e4326 100644 --- a/docker/Dockerfile.runtime +++ b/docker/Dockerfile.runtime @@ -1,5 +1,6 @@ ARG DATAFED_DIR="/datafed" ARG DATAFED_INSTALL_PATH="/opt/datafed" +ARG DATAFED_DEPENDENCIES_INSTALL_PATH="/opt/datafed/dependencies" ARG GCS_IMAGE="code.ornl.gov:4567/dlsw/datafed/gcs-ubuntu-focal" ARG BUILD_DIR="$DATAFED_DIR/source" ARG LIB_DIR="/usr/local/lib" diff --git a/docker/entrypoint_foxx.sh b/docker/entrypoint_foxx.sh index d91fdd98e..ea60c6bee 100755 --- a/docker/entrypoint_foxx.sh +++ b/docker/entrypoint_foxx.sh @@ -33,17 +33,28 @@ then # Check to see if foxx has previously been installed "${PROJECT_ROOT}/scripts/generate_datafed.sh" - "${DATAFED_DEPENDENCIES_INSTALL_PATH}/bin/cmake" -S. -B build \ - -DBUILD_REPO_SERVER=False \ - -DBUILD_COMMON=False \ - -DBUILD_AUTHZ=False \ - -DBUILD_CORE_SERVER=False \ - -DBUILD_WEB_SERVER=False \ - -DBUILD_DOCS=False \ - -DBUILD_PYTHON_CLIENT=False \ - -DBUILD_FOXX=True \ - -DINSTALL_FOXX=True + # Define common CMake options + cmake_options=( + -S. -B build + -DBUILD_REPO_SERVER=False + -DBUILD_COMMON=False + -DBUILD_AUTHZ=False + -DBUILD_CORE_SERVER=False + -DBUILD_WEB_SERVER=False + -DBUILD_DOCS=False + -DBUILD_PYTHON_CLIENT=False + -DBUILD_FOXX=True + -DINSTALL_FOXX=True + ) + # Add the ENABLE_FOXX_TESTS option if it's set to TRUE + # Should only run this if you are ok with making changes to the database + if [ "$ENABLE_FOXX_TESTS" == "TRUE" ]; then + cmake_options+=(-DENABLE_FOXX_TESTS=True) + fi + + # Run the CMake command with the constructed options + "${DATAFED_DEPENDENCIES_INSTALL_PATH}/bin/cmake" "${cmake_options[@]}" "${DATAFED_DEPENDENCIES_INSTALL_PATH}/bin/cmake" --build build @@ -51,14 +62,25 @@ then # should be replaced with health check at some point sleep 5 "${DATAFED_DEPENDENCIES_INSTALL_PATH}/bin/cmake" --build build --target install - + + if [ "$ENABLE_FOXX_TESTS" == "TRUE" ] + then + "${DATAFED_DEPENDENCIES_INSTALL_PATH}/bin/cmake" \ + --build build \ + --target test + EXIT_CODE="$?" + if [ "$EXIT_CODE" != "0" ]; then exit "$EXIT_CODE"; fi + fi + + # Create flag to indicate container has done its job touch "$install_flag" chown -R "$UID":"$UID" "/tmp" - else - echo "/tmp/.foxx_is_installed has been found skipping reinstall" + echo "$install_flag has been found skipping reinstall" fi -echo "Sleeping" -sleep 1000 - +# Keep container alive for a little bit, the CI pipelines check that the +# container actually runs. If the container runs to fast the pipeline check +# might fail because it wasn't able to determine if the container actually +# ran. +sleep 60 diff --git a/docs/_sources/admin/general.rst.txt b/docs/_sources/admin/general.rst.txt index c780e1c4e..4003f9ee3 100644 --- a/docs/_sources/admin/general.rst.txt +++ b/docs/_sources/admin/general.rst.txt @@ -135,10 +135,14 @@ Steps to deploy DataFed Database: 1. Download and install the latest ArangoDB server package for your host operating system. (see example, below) -Example download/install of ArangoDB 3.7 for Ubuntu:: +Example download/install of ArangoDB 3.12.4 for Ubuntu:: - wget https://download.arangodb.com/arangodb37/Community/Linux/arangodb3_3.7.10-1_amd64.deb - sudo apt install ./arangodb3_3.7.10-1_amd64.deb + curl -OL https://download.arangodb.com/arangodb312/DEBIAN/Release.key + sudo apt-key add - < Release.key + echo 'deb https://download.arangodb.com/arangodb312/DEBIAN/ /' | sudo tee /etc/apt/sources.list.d/arangodb.list + sudo apt-get install apt-transport-https + sudo apt-get update + sudo apt-get install arangodb3 It should start automatically with an install but to run the arangodb service, you can also interact with it via systemctl:: @@ -191,6 +195,7 @@ Example datafed-core.cfg file:: cred-dir = /opt/datafed/keys client-id = client-secret = + log-level = 4 To run the service:: diff --git a/docs/_static/doctools.js b/docs/_static/doctools.js index d06a71d75..064f4b780 100644 --- a/docs/_static/doctools.js +++ b/docs/_static/doctools.js @@ -10,144 +10,135 @@ */ "use strict"; -const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ - "TEXTAREA", - "INPUT", - "SELECT", - "BUTTON", -]); +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set(["TEXTAREA", "INPUT", "SELECT", "BUTTON"]); const _ready = (callback) => { - if (document.readyState !== "loading") { - callback(); - } else { - document.addEventListener("DOMContentLoaded", callback); - } + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } }; /** * Small JavaScript module for the documentation. */ const Documentation = { - init: () => { - Documentation.initDomainIndexTable(); - Documentation.initOnKeyListeners(); - }, - - /** - * i18n support - */ - TRANSLATIONS: {}, - PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), - LOCALE: "unknown", - - // gettext and ngettext don't access this so that the functions - // can safely bound to a different name (_ = Documentation.gettext) - gettext: (string) => { - const translated = Documentation.TRANSLATIONS[string]; - switch (typeof translated) { - case "undefined": - return string; // no translation - case "string": - return translated; // translation exists - default: - return translated[0]; // (singular, plural) translation tuple exists - } - }, - - ngettext: (singular, plural, n) => { - const translated = Documentation.TRANSLATIONS[singular]; - if (typeof translated !== "undefined") - return translated[Documentation.PLURAL_EXPR(n)]; - return n === 1 ? singular : plural; - }, - - addTranslations: (catalog) => { - Object.assign(Documentation.TRANSLATIONS, catalog.messages); - Documentation.PLURAL_EXPR = new Function( - "n", - `return (${catalog.plural_expr})` - ); - Documentation.LOCALE = catalog.locale; - }, - - /** - * helper function to focus on search bar - */ - focusSearchBar: () => { - document.querySelectorAll("input[name=q]")[0]?.focus(); - }, - - /** - * Initialise the domain index toggle buttons - */ - initDomainIndexTable: () => { - const toggler = (el) => { - const idNumber = el.id.substr(7); - const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); - if (el.src.substr(-9) === "minus.png") { - el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; - toggledRows.forEach((el) => (el.style.display = "none")); - } else { - el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; - toggledRows.forEach((el) => (el.style.display = "")); - } - }; - - const togglerElements = document.querySelectorAll("img.toggler"); - togglerElements.forEach((el) => - el.addEventListener("click", (event) => toggler(event.currentTarget)) - ); - togglerElements.forEach((el) => (el.style.display = "")); - if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); - }, - - initOnKeyListeners: () => { - // only install a listener if it is really needed - if ( - !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && - !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS - ) - return; - - document.addEventListener("keydown", (event) => { - // bail for input elements - if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; - // bail with special keys - if (event.altKey || event.ctrlKey || event.metaKey) return; - - if (!event.shiftKey) { - switch (event.key) { - case "ArrowLeft": - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; - - const prevLink = document.querySelector('link[rel="prev"]'); - if (prevLink && prevLink.href) { - window.location.href = prevLink.href; - event.preventDefault(); + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function("n", `return (${catalog.plural_expr})`); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); } - break; - case "ArrowRight": - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; - - const nextLink = document.querySelector('link[rel="next"]'); - if (nextLink && nextLink.href) { - window.location.href = nextLink.href; - event.preventDefault(); + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)), + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } } - break; - } - } - - // some keyboard layouts may need Shift to get / - switch (event.key) { - case "/": - if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; - Documentation.focusSearchBar(); - event.preventDefault(); - } - }); - }, + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, }; // quick alias for translations diff --git a/docs/_static/documentation_options.js b/docs/_static/documentation_options.js index 84ac268b8..8ea24e087 100644 --- a/docs/_static/documentation_options.js +++ b/docs/_static/documentation_options.js @@ -1,14 +1,14 @@ var DOCUMENTATION_OPTIONS = { - URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), - VERSION: '1.4', - LANGUAGE: 'en', + URL_ROOT: document.getElementById("documentation_options").getAttribute("data-url_root"), + VERSION: "1.4", + LANGUAGE: "en", COLLAPSE_INDEX: false, - BUILDER: 'html', - FILE_SUFFIX: '.html', - LINK_SUFFIX: '.html', + BUILDER: "html", + FILE_SUFFIX: ".html", + LINK_SUFFIX: ".html", HAS_SOURCE: true, - SOURCELINK_SUFFIX: '.txt', + SOURCELINK_SUFFIX: ".txt", NAVIGATION_WITH_KEYS: false, SHOW_SEARCH_SUMMARY: true, ENABLE_SEARCH_SHORTCUTS: true, -}; \ No newline at end of file +}; diff --git a/docs/_static/js/badge_only.js b/docs/_static/js/badge_only.js index 526d7234b..0b0a813fc 100644 --- a/docs/_static/js/badge_only.js +++ b/docs/_static/js/badge_only.js @@ -1 +1,54 @@ -!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=4)}({4:function(e,t,r){}}); \ No newline at end of file +!(function (e) { + var t = {}; + function r(n) { + if (t[n]) return t[n].exports; + var o = (t[n] = { i: n, l: !1, exports: {} }); + return e[n].call(o.exports, o, o.exports, r), (o.l = !0), o.exports; + } + (r.m = e), + (r.c = t), + (r.d = function (e, t, n) { + r.o(e, t) || Object.defineProperty(e, t, { enumerable: !0, get: n }); + }), + (r.r = function (e) { + "undefined" != typeof Symbol && + Symbol.toStringTag && + Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }), + Object.defineProperty(e, "__esModule", { value: !0 }); + }), + (r.t = function (e, t) { + if ((1 & t && (e = r(e)), 8 & t)) return e; + if (4 & t && "object" == typeof e && e && e.__esModule) return e; + var n = Object.create(null); + if ( + (r.r(n), + Object.defineProperty(n, "default", { enumerable: !0, value: e }), + 2 & t && "string" != typeof e) + ) + for (var o in e) + r.d( + n, + o, + function (t) { + return e[t]; + }.bind(null, o), + ); + return n; + }), + (r.n = function (e) { + var t = + e && e.__esModule + ? function () { + return e.default; + } + : function () { + return e; + }; + return r.d(t, "a", t), t; + }), + (r.o = function (e, t) { + return Object.prototype.hasOwnProperty.call(e, t); + }), + (r.p = ""), + r((r.s = 4)); +})({ 4: function (e, t, r) {} }); diff --git a/docs/_static/js/html5shiv-printshiv.min.js b/docs/_static/js/html5shiv-printshiv.min.js index 2b43bd062..414bf5e58 100644 --- a/docs/_static/js/html5shiv-printshiv.min.js +++ b/docs/_static/js/html5shiv-printshiv.min.js @@ -1,4 +1,226 @@ /** -* @preserve HTML5 Shiv 3.7.3-pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed -*/ -!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=y.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=y.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),y.elements=c+" "+a,j(b)}function f(a){var b=x[a[v]];return b||(b={},w++,a[v]=w,x[w]=b),b}function g(a,c,d){if(c||(c=b),q)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():u.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||t.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),q)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return y.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(y,b.frag)}function j(a){a||(a=b);var d=f(a);return!y.shivCSS||p||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),q||i(a,d),a}function k(a){for(var b,c=a.getElementsByTagName("*"),e=c.length,f=RegExp("^(?:"+d().join("|")+")$","i"),g=[];e--;)b=c[e],f.test(b.nodeName)&&g.push(b.applyElement(l(b)));return g}function l(a){for(var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(A+":"+a.nodeName);d--;)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function m(a){for(var b,c=a.split("{"),e=c.length,f=RegExp("(^|[\\s,>+~])("+d().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),g="$1"+A+"\\:$2";e--;)b=c[e]=c[e].split("}"),b[b.length-1]=b[b.length-1].replace(f,g),c[e]=b.join("}");return c.join("{")}function n(a){for(var b=a.length;b--;)a[b].removeNode()}function o(a){function b(){clearTimeout(g._removeSheetTimer),d&&d.removeNode(!0),d=null}var d,e,g=f(a),h=a.namespaces,i=a.parentWindow;return!B||a.printShived?a:("undefined"==typeof h[A]&&h.add(A),i.attachEvent("onbeforeprint",function(){b();for(var f,g,h,i=a.styleSheets,j=[],l=i.length,n=Array(l);l--;)n[l]=i[l];for(;h=n.pop();)if(!h.disabled&&z.test(h.media)){try{f=h.imports,g=f.length}catch(o){g=0}for(l=0;g>l;l++)n.push(f[l]);try{j.push(h.cssText)}catch(o){}}j=m(j.reverse().join("")),e=k(a),d=c(a,j)}),i.attachEvent("onafterprint",function(){n(e),clearTimeout(g._removeSheetTimer),g._removeSheetTimer=setTimeout(b,500)}),a.printShived=!0,a)}var p,q,r="3.7.3",s=a.html5||{},t=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,u=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",w=0,x={};!function(){try{var a=b.createElement("a");a.innerHTML="",p="hidden"in a,q=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){p=!0,q=!0}}();var y={elements:s.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:r,shivCSS:s.shivCSS!==!1,supportsUnknownElements:q,shivMethods:s.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=y,j(b);var z=/^$|\b(?:all|print)\b/,A="html5shiv",B=!q&&function(){var c=b.documentElement;return!("undefined"==typeof b.namespaces||"undefined"==typeof b.parentWindow||"undefined"==typeof c.applyElement||"undefined"==typeof c.removeNode||"undefined"==typeof a.attachEvent)}();y.type+=" print",y.shivPrint=o,o(b),"object"==typeof module&&module.exports&&(module.exports=y)}("undefined"!=typeof window?window:this,document); \ No newline at end of file + * @preserve HTML5 Shiv 3.7.3-pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed + */ +!(function (a, b) { + function c(a, b) { + var c = a.createElement("p"), + d = a.getElementsByTagName("head")[0] || a.documentElement; + return ( + (c.innerHTML = "x"), d.insertBefore(c.lastChild, d.firstChild) + ); + } + function d() { + var a = y.elements; + return "string" == typeof a ? a.split(" ") : a; + } + function e(a, b) { + var c = y.elements; + "string" != typeof c && (c = c.join(" ")), + "string" != typeof a && (a = a.join(" ")), + (y.elements = c + " " + a), + j(b); + } + function f(a) { + var b = x[a[v]]; + return b || ((b = {}), w++, (a[v] = w), (x[w] = b)), b; + } + function g(a, c, d) { + if ((c || (c = b), q)) return c.createElement(a); + d || (d = f(c)); + var e; + return ( + (e = d.cache[a] + ? d.cache[a].cloneNode() + : u.test(a) + ? (d.cache[a] = d.createElem(a)).cloneNode() + : d.createElem(a)), + !e.canHaveChildren || t.test(a) || e.tagUrn ? e : d.frag.appendChild(e) + ); + } + function h(a, c) { + if ((a || (a = b), q)) return a.createDocumentFragment(); + c = c || f(a); + for (var e = c.frag.cloneNode(), g = 0, h = d(), i = h.length; i > g; g++) + e.createElement(h[g]); + return e; + } + function i(a, b) { + b.cache || + ((b.cache = {}), + (b.createElem = a.createElement), + (b.createFrag = a.createDocumentFragment), + (b.frag = b.createFrag())), + (a.createElement = function (c) { + return y.shivMethods ? g(c, a, b) : b.createElem(c); + }), + (a.createDocumentFragment = Function( + "h,f", + "return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&(" + + d() + .join() + .replace(/[\w\-:]+/g, function (a) { + return b.createElem(a), b.frag.createElement(a), 'c("' + a + '")'; + }) + + ");return n}", + )(y, b.frag)); + } + function j(a) { + a || (a = b); + var d = f(a); + return ( + !y.shivCSS || + p || + d.hasCSS || + (d.hasCSS = !!c( + a, + "article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}", + )), + q || i(a, d), + a + ); + } + function k(a) { + for ( + var b, + c = a.getElementsByTagName("*"), + e = c.length, + f = RegExp("^(?:" + d().join("|") + ")$", "i"), + g = []; + e--; + + ) + (b = c[e]), f.test(b.nodeName) && g.push(b.applyElement(l(b))); + return g; + } + function l(a) { + for ( + var b, + c = a.attributes, + d = c.length, + e = a.ownerDocument.createElement(A + ":" + a.nodeName); + d--; + + ) + (b = c[d]), b.specified && e.setAttribute(b.nodeName, b.nodeValue); + return (e.style.cssText = a.style.cssText), e; + } + function m(a) { + for ( + var b, + c = a.split("{"), + e = c.length, + f = RegExp("(^|[\\s,>+~])(" + d().join("|") + ")(?=[[\\s,>+~#.:]|$)", "gi"), + g = "$1" + A + "\\:$2"; + e--; + + ) + (b = c[e] = c[e].split("}")), + (b[b.length - 1] = b[b.length - 1].replace(f, g)), + (c[e] = b.join("}")); + return c.join("{"); + } + function n(a) { + for (var b = a.length; b--; ) a[b].removeNode(); + } + function o(a) { + function b() { + clearTimeout(g._removeSheetTimer), d && d.removeNode(!0), (d = null); + } + var d, + e, + g = f(a), + h = a.namespaces, + i = a.parentWindow; + return !B || a.printShived + ? a + : ("undefined" == typeof h[A] && h.add(A), + i.attachEvent("onbeforeprint", function () { + b(); + for (var f, g, h, i = a.styleSheets, j = [], l = i.length, n = Array(l); l--; ) + n[l] = i[l]; + for (; (h = n.pop()); ) + if (!h.disabled && z.test(h.media)) { + try { + (f = h.imports), (g = f.length); + } catch (o) { + g = 0; + } + for (l = 0; g > l; l++) n.push(f[l]); + try { + j.push(h.cssText); + } catch (o) {} + } + (j = m(j.reverse().join(""))), (e = k(a)), (d = c(a, j)); + }), + i.attachEvent("onafterprint", function () { + n(e), + clearTimeout(g._removeSheetTimer), + (g._removeSheetTimer = setTimeout(b, 500)); + }), + (a.printShived = !0), + a); + } + var p, + q, + r = "3.7.3", + s = a.html5 || {}, + t = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i, + u = + /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i, + v = "_html5shiv", + w = 0, + x = {}; + !(function () { + try { + var a = b.createElement("a"); + (a.innerHTML = ""), + (p = "hidden" in a), + (q = + 1 == a.childNodes.length || + (function () { + b.createElement("a"); + var a = b.createDocumentFragment(); + return ( + "undefined" == typeof a.cloneNode || + "undefined" == typeof a.createDocumentFragment || + "undefined" == typeof a.createElement + ); + })()); + } catch (c) { + (p = !0), (q = !0); + } + })(); + var y = { + elements: + s.elements || + "abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video", + version: r, + shivCSS: s.shivCSS !== !1, + supportsUnknownElements: q, + shivMethods: s.shivMethods !== !1, + type: "default", + shivDocument: j, + createElement: g, + createDocumentFragment: h, + addElements: e, + }; + (a.html5 = y), j(b); + var z = /^$|\b(?:all|print)\b/, + A = "html5shiv", + B = + !q && + (function () { + var c = b.documentElement; + return !( + "undefined" == typeof b.namespaces || + "undefined" == typeof b.parentWindow || + "undefined" == typeof c.applyElement || + "undefined" == typeof c.removeNode || + "undefined" == typeof a.attachEvent + ); + })(); + (y.type += " print"), + (y.shivPrint = o), + o(b), + "object" == typeof module && module.exports && (module.exports = y); +})("undefined" != typeof window ? window : this, document); diff --git a/docs/_static/js/html5shiv.min.js b/docs/_static/js/html5shiv.min.js index cd1c674f5..8a8d7c549 100644 --- a/docs/_static/js/html5shiv.min.js +++ b/docs/_static/js/html5shiv.min.js @@ -1,4 +1,127 @@ /** -* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed -*/ -!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3-pre",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document); \ No newline at end of file + * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed + */ +!(function (a, b) { + function c(a, b) { + var c = a.createElement("p"), + d = a.getElementsByTagName("head")[0] || a.documentElement; + return ( + (c.innerHTML = "x"), d.insertBefore(c.lastChild, d.firstChild) + ); + } + function d() { + var a = t.elements; + return "string" == typeof a ? a.split(" ") : a; + } + function e(a, b) { + var c = t.elements; + "string" != typeof c && (c = c.join(" ")), + "string" != typeof a && (a = a.join(" ")), + (t.elements = c + " " + a), + j(b); + } + function f(a) { + var b = s[a[q]]; + return b || ((b = {}), r++, (a[q] = r), (s[r] = b)), b; + } + function g(a, c, d) { + if ((c || (c = b), l)) return c.createElement(a); + d || (d = f(c)); + var e; + return ( + (e = d.cache[a] + ? d.cache[a].cloneNode() + : p.test(a) + ? (d.cache[a] = d.createElem(a)).cloneNode() + : d.createElem(a)), + !e.canHaveChildren || o.test(a) || e.tagUrn ? e : d.frag.appendChild(e) + ); + } + function h(a, c) { + if ((a || (a = b), l)) return a.createDocumentFragment(); + c = c || f(a); + for (var e = c.frag.cloneNode(), g = 0, h = d(), i = h.length; i > g; g++) + e.createElement(h[g]); + return e; + } + function i(a, b) { + b.cache || + ((b.cache = {}), + (b.createElem = a.createElement), + (b.createFrag = a.createDocumentFragment), + (b.frag = b.createFrag())), + (a.createElement = function (c) { + return t.shivMethods ? g(c, a, b) : b.createElem(c); + }), + (a.createDocumentFragment = Function( + "h,f", + "return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&(" + + d() + .join() + .replace(/[\w\-:]+/g, function (a) { + return b.createElem(a), b.frag.createElement(a), 'c("' + a + '")'; + }) + + ");return n}", + )(t, b.frag)); + } + function j(a) { + a || (a = b); + var d = f(a); + return ( + !t.shivCSS || + k || + d.hasCSS || + (d.hasCSS = !!c( + a, + "article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}", + )), + l || i(a, d), + a + ); + } + var k, + l, + m = "3.7.3-pre", + n = a.html5 || {}, + o = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i, + p = + /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i, + q = "_html5shiv", + r = 0, + s = {}; + !(function () { + try { + var a = b.createElement("a"); + (a.innerHTML = ""), + (k = "hidden" in a), + (l = + 1 == a.childNodes.length || + (function () { + b.createElement("a"); + var a = b.createDocumentFragment(); + return ( + "undefined" == typeof a.cloneNode || + "undefined" == typeof a.createDocumentFragment || + "undefined" == typeof a.createElement + ); + })()); + } catch (c) { + (k = !0), (l = !0); + } + })(); + var t = { + elements: + n.elements || + "abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video", + version: m, + shivCSS: n.shivCSS !== !1, + supportsUnknownElements: l, + shivMethods: n.shivMethods !== !1, + type: "default", + shivDocument: j, + createElement: g, + createDocumentFragment: h, + addElements: e, + }; + (a.html5 = t), j(b), "object" == typeof module && module.exports && (module.exports = t); +})("undefined" != typeof window ? window : this, document); diff --git a/docs/_static/js/theme.js b/docs/_static/js/theme.js index 1fddb6ee4..5067be622 100644 --- a/docs/_static/js/theme.js +++ b/docs/_static/js/theme.js @@ -1 +1,248 @@ -!function(n){var e={};function t(i){if(e[i])return e[i].exports;var o=e[i]={i:i,l:!1,exports:{}};return n[i].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=n,t.c=e,t.d=function(n,e,i){t.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:i})},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},t.t=function(n,e){if(1&e&&(n=t(n)),8&e)return n;if(4&e&&"object"==typeof n&&n&&n.__esModule)return n;var i=Object.create(null);if(t.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:n}),2&e&&"string"!=typeof n)for(var o in n)t.d(i,o,function(e){return n[e]}.bind(null,o));return i},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.p="",t(t.s=0)}([function(n,e,t){t(1),n.exports=t(3)},function(n,e,t){(function(){var e="undefined"!=typeof window?window.jQuery:t(2);n.exports.ThemeNav={navBar:null,win:null,winScroll:!1,winResize:!1,linkScroll:!1,winPosition:0,winHeight:null,docHeight:null,isRunning:!1,enable:function(n){var t=this;void 0===n&&(n=!0),t.isRunning||(t.isRunning=!0,e((function(e){t.init(e),t.reset(),t.win.on("hashchange",t.reset),n&&t.win.on("scroll",(function(){t.linkScroll||t.winScroll||(t.winScroll=!0,requestAnimationFrame((function(){t.onScroll()})))})),t.win.on("resize",(function(){t.winResize||(t.winResize=!0,requestAnimationFrame((function(){t.onResize()})))})),t.onResize()})))},enableSticky:function(){this.enable(!0)},init:function(n){n(document);var e=this;this.navBar=n("div.wy-side-scroll:first"),this.win=n(window),n(document).on("click","[data-toggle='wy-nav-top']",(function(){n("[data-toggle='wy-nav-shift']").toggleClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift")})).on("click",".wy-menu-vertical .current ul li a",(function(){var t=n(this);n("[data-toggle='wy-nav-shift']").removeClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift"),e.toggleCurrent(t),e.hashChange()})).on("click","[data-toggle='rst-current-version']",(function(){n("[data-toggle='rst-versions']").toggleClass("shift-up")})),n("table.docutils:not(.field-list,.footnote,.citation)").wrap("
"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each((function(){var t=n(this);expand=n(''),expand.on("click",(function(n){return e.toggleCurrent(t),n.stopPropagation(),!1})),t.prepend(expand)}))},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),t=e.find('[href="'+n+'"]');if(0===t.length){var i=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(t=e.find('[href="#'+i.attr("id")+'"]')).length&&(t=e.find('[href="#"]'))}if(t.length>0){$(".wy-menu-vertical .current").removeClass("current").attr("aria-expanded","false"),t.addClass("current").attr("aria-expanded","true"),t.closest("li.toctree-l1").parent().addClass("current").attr("aria-expanded","true");for(let n=1;n<=10;n++)t.closest("li.toctree-l"+n).addClass("current").attr("aria-expanded","true");t[0].scrollIntoView()}}catch(n){console.log("Error expanding nav for anchor",n)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,t=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(t),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",(function(){this.linkScroll=!1}))},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current").attr("aria-expanded","false"),e.siblings().find("li.current").removeClass("current").attr("aria-expanded","false");var t=e.find("> ul li");t.length&&(t.removeClass("current").attr("aria-expanded","false"),e.toggleClass("current").attr("aria-expanded",(function(n,e){return"true"==e?"false":"true"})))}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:n.exports.ThemeNav,StickyNav:n.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],t=0;t", + ), + n("table.docutils.footnote").wrap( + "
", + ), + n("table.docutils.citation").wrap( + "
", + ), + n(".wy-menu-vertical ul") + .not(".simple") + .siblings("a") + .each(function () { + var t = n(this); + (expand = n( + '', + )), + expand.on("click", function (n) { + return e.toggleCurrent(t), n.stopPropagation(), !1; + }), + t.prepend(expand); + }); + }, + reset: function () { + var n = encodeURI(window.location.hash) || "#"; + try { + var e = $(".wy-menu-vertical"), + t = e.find('[href="' + n + '"]'); + if (0 === t.length) { + var i = $('.document [id="' + n.substring(1) + '"]').closest( + "div.section", + ); + 0 === (t = e.find('[href="#' + i.attr("id") + '"]')).length && + (t = e.find('[href="#"]')); + } + if (t.length > 0) { + $(".wy-menu-vertical .current") + .removeClass("current") + .attr("aria-expanded", "false"), + t.addClass("current").attr("aria-expanded", "true"), + t + .closest("li.toctree-l1") + .parent() + .addClass("current") + .attr("aria-expanded", "true"); + for (let n = 1; n <= 10; n++) + t.closest("li.toctree-l" + n) + .addClass("current") + .attr("aria-expanded", "true"); + t[0].scrollIntoView(); + } + } catch (n) { + console.log("Error expanding nav for anchor", n); + } + }, + onScroll: function () { + this.winScroll = !1; + var n = this.win.scrollTop(), + e = n + this.winHeight, + t = this.navBar.scrollTop() + (n - this.winPosition); + n < 0 || + e > this.docHeight || + (this.navBar.scrollTop(t), (this.winPosition = n)); + }, + onResize: function () { + (this.winResize = !1), + (this.winHeight = this.win.height()), + (this.docHeight = $(document).height()); + }, + hashChange: function () { + (this.linkScroll = !0), + this.win.one("hashchange", function () { + this.linkScroll = !1; + }); + }, + toggleCurrent: function (n) { + var e = n.closest("li"); + e.siblings("li.current").removeClass("current").attr("aria-expanded", "false"), + e + .siblings() + .find("li.current") + .removeClass("current") + .attr("aria-expanded", "false"); + var t = e.find("> ul li"); + t.length && + (t.removeClass("current").attr("aria-expanded", "false"), + e.toggleClass("current").attr("aria-expanded", function (n, e) { + return "true" == e ? "false" : "true"; + })); + }, + }), + "undefined" != typeof window && + (window.SphinxRtdTheme = { + Navigation: n.exports.ThemeNav, + StickyNav: n.exports.ThemeNav, + }), + (function () { + for ( + var n = 0, e = ["ms", "moz", "webkit", "o"], t = 0; + t < e.length && !window.requestAnimationFrame; + ++t + ) + (window.requestAnimationFrame = window[e[t] + "RequestAnimationFrame"]), + (window.cancelAnimationFrame = + window[e[t] + "CancelAnimationFrame"] || + window[e[t] + "CancelRequestAnimationFrame"]); + window.requestAnimationFrame || + (window.requestAnimationFrame = function (e, t) { + var i = new Date().getTime(), + o = Math.max(0, 16 - (i - n)), + r = window.setTimeout(function () { + e(i + o); + }, o); + return (n = i + o), r; + }), + window.cancelAnimationFrame || + (window.cancelAnimationFrame = function (n) { + clearTimeout(n); + }); + })(); + }).call(window); + }, + function (n, e) { + n.exports = jQuery; + }, + function (n, e, t) {}, +]); diff --git a/docs/_static/language_data.js b/docs/_static/language_data.js index 250f5665f..aa4f723eb 100644 --- a/docs/_static/language_data.js +++ b/docs/_static/language_data.js @@ -10,190 +10,206 @@ * */ -var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; - +var stopwords = [ + "a", + "and", + "are", + "as", + "at", + "be", + "but", + "by", + "for", + "if", + "in", + "into", + "is", + "it", + "near", + "no", + "not", + "of", + "on", + "or", + "such", + "that", + "the", + "their", + "then", + "there", + "these", + "they", + "this", + "to", + "was", + "will", + "with", +]; /* Non-minified version is copied as a separate JS file, is available */ /** * Porter Stemmer */ -var Stemmer = function() { - - var step2list = { - ational: 'ate', - tional: 'tion', - enci: 'ence', - anci: 'ance', - izer: 'ize', - bli: 'ble', - alli: 'al', - entli: 'ent', - eli: 'e', - ousli: 'ous', - ization: 'ize', - ation: 'ate', - ator: 'ate', - alism: 'al', - iveness: 'ive', - fulness: 'ful', - ousness: 'ous', - aliti: 'al', - iviti: 'ive', - biliti: 'ble', - logi: 'log' - }; - - var step3list = { - icate: 'ic', - ative: '', - alize: 'al', - iciti: 'ic', - ical: 'ic', - ful: '', - ness: '' - }; - - var c = "[^aeiou]"; // consonant - var v = "[aeiouy]"; // vowel - var C = c + "[^aeiouy]*"; // consonant sequence - var V = v + "[aeiou]*"; // vowel sequence - - var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 - var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 - var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 - var s_v = "^(" + C + ")?" + v; // vowel in stem - - this.stemWord = function (w) { - var stem; - var suffix; - var firstch; - var origword = w; - - if (w.length < 3) - return w; - - var re; - var re2; - var re3; - var re4; - - firstch = w.substr(0,1); - if (firstch == "y") - w = firstch.toUpperCase() + w.substr(1); - - // Step 1a - re = /^(.+?)(ss|i)es$/; - re2 = /^(.+?)([^s])s$/; - - if (re.test(w)) - w = w.replace(re,"$1$2"); - else if (re2.test(w)) - w = w.replace(re2,"$1$2"); - - // Step 1b - re = /^(.+?)eed$/; - re2 = /^(.+?)(ed|ing)$/; - if (re.test(w)) { - var fp = re.exec(w); - re = new RegExp(mgr0); - if (re.test(fp[1])) { - re = /.$/; - w = w.replace(re,""); - } - } - else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1]; - re2 = new RegExp(s_v); - if (re2.test(stem)) { - w = stem; - re2 = /(at|bl|iz)$/; - re3 = new RegExp("([^aeiouylsz])\\1$"); - re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - if (re2.test(w)) - w = w + "e"; - else if (re3.test(w)) { - re = /.$/; - w = w.replace(re,""); +var Stemmer = function () { + var step2list = { + ational: "ate", + tional: "tion", + enci: "ence", + anci: "ance", + izer: "ize", + bli: "ble", + alli: "al", + entli: "ent", + eli: "e", + ousli: "ous", + ization: "ize", + ation: "ate", + ator: "ate", + alism: "al", + iveness: "ive", + fulness: "ful", + ousness: "ous", + aliti: "al", + iviti: "ive", + biliti: "ble", + logi: "log", + }; + + var step3list = { + icate: "ic", + ative: "", + alize: "al", + iciti: "ic", + ical: "ic", + ful: "", + ness: "", + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0, 1); + if (firstch == "y") w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) w = w.replace(re, "$1$2"); + else if (re2.test(w)) w = w.replace(re2, "$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re, ""); + } + } else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re, ""); + } else if (re4.test(w)) w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) w = stem + "i"; + } + + // Step 2 + re = + /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) w = stem; + } else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !re3.test(stem))) w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re, ""); } - else if (re4.test(w)) - w = w + "e"; - } - } - - // Step 1c - re = /^(.+?)y$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(s_v); - if (re.test(stem)) - w = stem + "i"; - } - - // Step 2 - re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = new RegExp(mgr0); - if (re.test(stem)) - w = stem + step2list[suffix]; - } - - // Step 3 - re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = new RegExp(mgr0); - if (re.test(stem)) - w = stem + step3list[suffix]; - } - - // Step 4 - re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; - re2 = /^(.+?)(s|t)(ion)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(mgr1); - if (re.test(stem)) - w = stem; - } - else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1] + fp[2]; - re2 = new RegExp(mgr1); - if (re2.test(stem)) - w = stem; - } - - // Step 5 - re = /^(.+?)e$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(mgr1); - re2 = new RegExp(meq1); - re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) - w = stem; - } - re = /ll$/; - re2 = new RegExp(mgr1); - if (re.test(w) && re2.test(w)) { - re = /.$/; - w = w.replace(re,""); - } - - // and turn initial Y back to y - if (firstch == "y") - w = firstch.toLowerCase() + w.substr(1); - return w; - } -} + // and turn initial Y back to y + if (firstch == "y") w = firstch.toLowerCase() + w.substr(1); + return w; + }; +}; diff --git a/docs/_static/searchtools.js b/docs/_static/searchtools.js index 97d56a74d..26c7c16a8 100644 --- a/docs/_static/searchtools.js +++ b/docs/_static/searchtools.js @@ -14,120 +14,106 @@ * Simple result scoring code. */ if (typeof Scorer === "undefined") { - var Scorer = { - // Implement the following function to further tweak the score for each result - // The function takes a result array [docname, title, anchor, descr, score, filename] - // and returns the new score. - /* + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* score: result => { const [docname, title, anchor, descr, score, filename] = result return score }, */ - // query matches the full name of an object - objNameMatch: 11, - // or matches in the last dotted part of the object name - objPartialMatch: 6, - // Additive scores depending on the priority of the object - objPrio: { - 0: 15, // used to be importantResults - 1: 5, // used to be objectResults - 2: -5, // used to be unimportantResults - }, - // Used when the priority is not in the mapping. - objPrioDefault: 0, - - // query found in title - title: 15, - partialTitle: 7, - // query found in terms - term: 5, - partialTerm: 2, - }; + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; } const _removeChildren = (element) => { - while (element && element.lastChild) element.removeChild(element.lastChild); + while (element && element.lastChild) element.removeChild(element.lastChild); }; /** * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping */ -const _escapeRegExp = (string) => - string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string +const _escapeRegExp = (string) => string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string const _displayItem = (item, searchTerms) => { - const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; - const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT; - const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; - const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; - const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; - - const [docName, title, anchor, descr, score, _filename] = item; - - let listItem = document.createElement("li"); - let requestUrl; - let linkUrl; - if (docBuilder === "dirhtml") { - // dirhtml builder - let dirname = docName + "/"; - if (dirname.match(/\/index\/$/)) - dirname = dirname.substring(0, dirname.length - 6); - else if (dirname === "index/") dirname = ""; - requestUrl = docUrlRoot + dirname; - linkUrl = requestUrl; - } else { - // normal html builders - requestUrl = docUrlRoot + docName + docFileSuffix; - linkUrl = docName + docLinkSuffix; - } - let linkEl = listItem.appendChild(document.createElement("a")); - linkEl.href = linkUrl + anchor; - linkEl.dataset.score = score; - linkEl.innerHTML = title; - if (descr) - listItem.appendChild(document.createElement("span")).innerHTML = - " (" + descr + ")"; - else if (showSearchSummary) - fetch(requestUrl) - .then((responseData) => responseData.text()) - .then((data) => { - if (data) - listItem.appendChild( - Search.makeSearchSummary(data, searchTerms) - ); - }); - Search.output.appendChild(listItem); + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + + const [docName, title, anchor, descr, score, _filename] = item; + + let listItem = document.createElement("li"); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = docUrlRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = docUrlRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) listItem.appendChild(document.createElement("span")).innerHTML = " (" + descr + ")"; + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) listItem.appendChild(Search.makeSearchSummary(data, searchTerms)); + }); + Search.output.appendChild(listItem); }; const _finishSearch = (resultCount) => { - Search.stopPulse(); - Search.title.innerText = _("Search Results"); - if (!resultCount) - Search.status.innerText = Documentation.gettext( - "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." - ); - else - Search.status.innerText = _( - `Search finished, found ${resultCount} page(s) matching the search query.` - ); + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.", + ); + else + Search.status.innerText = _( + `Search finished, found ${resultCount} page(s) matching the search query.`, + ); }; -const _displayNextItem = ( - results, - resultCount, - searchTerms -) => { - // results left, load the summary and display it - // this is intended to be dynamic (don't sub resultsCount) - if (results.length) { - _displayItem(results.pop(), searchTerms); - setTimeout( - () => _displayNextItem(results, resultCount, searchTerms), - 5 - ); - } - // search finished, update title and status message - else _finishSearch(resultCount); +const _displayNextItem = (results, resultCount, searchTerms) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms); + setTimeout(() => _displayNextItem(results, resultCount, searchTerms), 5); + } + // search finished, update title and status message + else _finishSearch(resultCount); }; /** @@ -139,428 +125,408 @@ const _displayNextItem = ( * This is the same as ``\W+`` in Python, preserving the surrogate pair area. */ if (typeof splitQuery === "undefined") { - var splitQuery = (query) => query - .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) - .filter(term => term) // remove remaining empty strings + var splitQuery = (query) => + query.split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu).filter((term) => term); // remove remaining empty strings } /** * Search Module */ const Search = { - _index: null, - _queued_query: null, - _pulse_status: -1, - - htmlToText: (htmlString) => { - const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); - htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() }); - const docContent = htmlElement.querySelector('[role="main"]'); - if (docContent !== undefined) return docContent.textContent; - console.warn( - "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template." - ); - return ""; - }, - - init: () => { - const query = new URLSearchParams(window.location.search).get("q"); - document - .querySelectorAll('input[name="q"]') - .forEach((el) => (el.value = query)); - if (query) Search.performSearch(query); - }, - - loadIndex: (url) => - (document.body.appendChild(document.createElement("script")).src = url), - - setIndex: (index) => { - Search._index = index; - if (Search._queued_query !== null) { - const query = Search._queued_query; - Search._queued_query = null; - Search.query(query); - } - }, + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString) => { + const htmlElement = new DOMParser().parseFromString(htmlString, "text/html"); + htmlElement.querySelectorAll(".headerlink").forEach((el) => { + el.remove(); + }); + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent !== undefined) return docContent.textContent; + console.warn( + "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template.", + ); + return ""; + }, - hasIndex: () => Search._index !== null, + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document.querySelectorAll('input[name="q"]').forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, - deferQuery: (query) => (Search._queued_query = query), + loadIndex: (url) => (document.body.appendChild(document.createElement("script")).src = url), - stopPulse: () => (Search._pulse_status = -1), + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, - startPulse: () => { - if (Search._pulse_status >= 0) return; + hasIndex: () => Search._index !== null, - const pulse = () => { - Search._pulse_status = (Search._pulse_status + 1) % 4; - Search.dots.innerText = ".".repeat(Search._pulse_status); - if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); - }; - pulse(); - }, - - /** - * perform a search for something (or wait until index is loaded) - */ - performSearch: (query) => { - // create the required interface elements - const searchText = document.createElement("h2"); - searchText.textContent = _("Searching"); - const searchSummary = document.createElement("p"); - searchSummary.classList.add("search-summary"); - searchSummary.innerText = ""; - const searchList = document.createElement("ul"); - searchList.classList.add("search"); - - const out = document.getElementById("search-results"); - Search.title = out.appendChild(searchText); - Search.dots = Search.title.appendChild(document.createElement("span")); - Search.status = out.appendChild(searchSummary); - Search.output = out.appendChild(searchList); - - const searchProgress = document.getElementById("search-progress"); - // Some themes don't use the search progress node - if (searchProgress) { - searchProgress.innerText = _("Preparing search..."); - } - Search.startPulse(); - - // index already loaded, the browser was quick! - if (Search.hasIndex()) Search.query(query); - else Search.deferQuery(query); - }, - - /** - * execute search (requires search index to be loaded) - */ - query: (query) => { - const filenames = Search._index.filenames; - const docNames = Search._index.docnames; - const titles = Search._index.titles; - const allTitles = Search._index.alltitles; - const indexEntries = Search._index.indexentries; - - // stem the search terms and add them to the correct list - const stemmer = new Stemmer(); - const searchTerms = new Set(); - const excludedTerms = new Set(); - const highlightTerms = new Set(); - const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); - splitQuery(query.trim()).forEach((queryTerm) => { - const queryTermLower = queryTerm.toLowerCase(); - - // maybe skip this "word" - // stopwords array is from language_data.js - if ( - stopwords.indexOf(queryTermLower) !== -1 || - queryTerm.match(/^\d+$/) - ) - return; - - // stem the word - let word = stemmer.stemWord(queryTermLower); - // select the correct list - if (word[0] === "-") excludedTerms.add(word.substr(1)); - else { - searchTerms.add(word); - highlightTerms.add(queryTermLower); - } - }); - - if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js - localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) - } + deferQuery: (query) => (Search._queued_query = query), - // console.debug("SEARCH: searching for:"); - // console.info("required: ", [...searchTerms]); - // console.info("excluded: ", [...excludedTerms]); - - // array of [docname, title, anchor, descr, score, filename] - let results = []; - _removeChildren(document.getElementById("search-progress")); - - const queryLower = query.toLowerCase(); - for (const [title, foundTitles] of Object.entries(allTitles)) { - if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) { - for (const [file, id] of foundTitles) { - let score = Math.round(100 * queryLower.length / title.length) - results.push([ - docNames[file], - titles[file] !== title ? `${titles[file]} > ${title}` : title, - id !== null ? "#" + id : "", - null, - score, - filenames[file], - ]); - } - } - } + stopPulse: () => (Search._pulse_status = -1), - // search for explicit entries in index directives - for (const [entry, foundEntries] of Object.entries(indexEntries)) { - if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { - for (const [file, id] of foundEntries) { - let score = Math.round(100 * queryLower.length / entry.length) - results.push([ - docNames[file], - titles[file], - id ? "#" + id : "", - null, - score, - filenames[file], - ]); + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); } - } - } + Search.startPulse(); - // lookup as object - objectTerms.forEach((term) => - results.push(...Search.performObjectSearch(term, objectTerms)) - ); - - // lookup as search terms in fulltext - results.push(...Search.performTermsSearch(searchTerms, excludedTerms)); - - // let the scorer override scores with a custom scoring function - if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item))); - - // now sort the results by score (in opposite order of appearance, since the - // display function below uses pop() to retrieve items) and then - // alphabetically - results.sort((a, b) => { - const leftScore = a[4]; - const rightScore = b[4]; - if (leftScore === rightScore) { - // same score: sort alphabetically - const leftTitle = a[1].toLowerCase(); - const rightTitle = b[1].toLowerCase(); - if (leftTitle === rightTitle) return 0; - return leftTitle > rightTitle ? -1 : 1; // inverted is intentional - } - return leftScore > rightScore ? 1 : -1; - }); - - // remove duplicate search results - // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept - let seen = new Set(); - results = results.reverse().reduce((acc, result) => { - let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); - if (!seen.has(resultStr)) { - acc.push(result); - seen.add(resultStr); - } - return acc; - }, []); - - results = results.reverse(); - - // for debugging - //Search.lastresults = results.slice(); // a copy - // console.info("search results:", Search.lastresults); - - // print the results - _displayNextItem(results, results.length, searchTerms); - }, - - /** - * search for object names - */ - performObjectSearch: (object, objectTerms) => { - const filenames = Search._index.filenames; - const docNames = Search._index.docnames; - const objects = Search._index.objects; - const objNames = Search._index.objnames; - const titles = Search._index.titles; - - const results = []; - - const objectSearchCallback = (prefix, match) => { - const name = match[4] - const fullname = (prefix ? prefix + "." : "") + name; - const fullnameLower = fullname.toLowerCase(); - if (fullnameLower.indexOf(object) < 0) return; - - let score = 0; - const parts = fullnameLower.split("."); - - // check for different match types: exact matches of full name or - // "last name" (i.e. last dotted part) - if (fullnameLower === object || parts.slice(-1)[0] === object) - score += Scorer.objNameMatch; - else if (parts.slice(-1)[0].indexOf(object) > -1) - score += Scorer.objPartialMatch; // matches in last name - - const objName = objNames[match[1]][2]; - const title = titles[match[0]]; - - // If more than one term searched for, we require other words to be - // found in the name/title/description - const otherTerms = new Set(objectTerms); - otherTerms.delete(object); - if (otherTerms.size > 0) { - const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); - if ( - [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) - ) - return; - } - - let anchor = match[3]; - if (anchor === "") anchor = fullname; - else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; - - const descr = objName + _(", in ") + title; - - // add custom score for some objects according to scorer - if (Scorer.objPrio.hasOwnProperty(match[2])) - score += Scorer.objPrio[match[2]]; - else score += Scorer.objPrioDefault; - - results.push([ - docNames[match[0]], - fullname, - "#" + anchor, - descr, - score, - filenames[match[0]], - ]); - }; - Object.keys(objects).forEach((prefix) => - objects[prefix].forEach((array) => - objectSearchCallback(prefix, array) - ) - ); - return results; - }, - - /** - * search for full-text terms in the index - */ - performTermsSearch: (searchTerms, excludedTerms) => { - // prepare search - const terms = Search._index.terms; - const titleTerms = Search._index.titleterms; - const filenames = Search._index.filenames; - const docNames = Search._index.docnames; - const titles = Search._index.titles; - - const scoreMap = new Map(); - const fileMap = new Map(); - - // perform the search on the required terms - searchTerms.forEach((word) => { - const files = []; - const arr = [ - { files: terms[word], score: Scorer.term }, - { files: titleTerms[word], score: Scorer.title }, - ]; - // add support for partial matches - if (word.length > 2) { - const escapedWord = _escapeRegExp(word); - Object.keys(terms).forEach((term) => { - if (term.match(escapedWord) && !terms[word]) - arr.push({ files: terms[term], score: Scorer.partialTerm }); - }); - Object.keys(titleTerms).forEach((term) => { - if (term.match(escapedWord) && !titleTerms[word]) - arr.push({ files: titleTerms[word], score: Scorer.partialTitle }); + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + /** + * execute search (requires search index to be loaded) + */ + query: (query) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords array is from language_data.js + if (stopwords.indexOf(queryTermLower) !== -1 || queryTerm.match(/^\d+$/)) return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } }); - } - // no match but word was a required one - if (arr.every((record) => record.files === undefined)) return; + if (SPHINX_HIGHLIGHT_ENABLED) { + // set in sphinx_highlight.js + localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")); + } - // found search word in contents - arr.forEach((record) => { - if (record.files === undefined) return; + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + // array of [docname, title, anchor, descr, score, filename] + let results = []; + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().includes(queryLower) && queryLower.length >= title.length / 2) { + for (const [file, id] of foundTitles) { + let score = Math.round((100 * queryLower.length) / title.length); + results.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } - let recordFiles = record.files; - if (recordFiles.length === undefined) recordFiles = [recordFiles]; - files.push(...recordFiles); + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && queryLower.length >= entry.length / 2) { + for (const [file, id] of foundEntries) { + let score = Math.round((100 * queryLower.length) / entry.length); + results.push([ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } - // set score for the word in each file - recordFiles.forEach((file) => { - if (!scoreMap.has(file)) scoreMap.set(file, {}); - scoreMap.get(file)[word] = record.score; + // lookup as object + objectTerms.forEach((term) => + results.push(...Search.performObjectSearch(term, objectTerms)), + ); + + // lookup as search terms in fulltext + results.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item))); + + // now sort the results by score (in opposite order of appearance, since the + // display function below uses pop() to retrieve items) and then + // alphabetically + results.sort((a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; }); - }); - - // create the mapping - files.forEach((file) => { - if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1) - fileMap.get(file).push(word); - else fileMap.set(file, [word]); - }); - }); - - // now check if the files don't contain excluded terms - const results = []; - for (const [file, wordList] of fileMap) { - // check if all requirements are matched - - // as search terms with length < 3 are discarded - const filteredTermCount = [...searchTerms].filter( - (term) => term.length > 2 - ).length; - if ( - wordList.length !== searchTerms.size && - wordList.length !== filteredTermCount - ) - continue; - - // ensure that none of the excluded terms is in the search result - if ( - [...excludedTerms].some( - (term) => - terms[term] === file || - titleTerms[term] === file || - (terms[term] || []).includes(file) || - (titleTerms[term] || []).includes(file) - ) - ) - break; - - // select one (max) score for the file. - const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); - // add result to the result list - results.push([ - docNames[file], - titles[file], - "", - null, - score, - filenames[file], - ]); - } - return results; - }, - - /** - * helper function to return a node containing the - * search summary for a given text. keywords is a list - * of stemmed words. - */ - makeSearchSummary: (htmlText, keywords) => { - const text = Search.htmlToText(htmlText); - if (text === "") return null; - - const textLower = text.toLowerCase(); - const actualStartPosition = [...keywords] - .map((k) => textLower.indexOf(k.toLowerCase())) - .filter((i) => i > -1) - .slice(-1)[0]; - const startWithContext = Math.max(actualStartPosition - 120, 0); - - const top = startWithContext === 0 ? "" : "..."; - const tail = startWithContext + 240 < text.length ? "..." : ""; - - let summary = document.createElement("p"); - summary.classList.add("context"); - summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; - - return summary; - }, + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result + .slice(0, 4) + .concat([result[5]]) + .map((v) => String(v)) + .join(","); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + results = results.reverse(); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4]; + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ([...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0)) return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => objectSearchCallback(prefix, array)), + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + const arr = [ + { files: terms[word], score: Scorer.term }, + { files: titleTerms[word], score: Scorer.title }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord) && !terms[word]) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord) && !titleTerms[word]) + arr.push({ files: titleTerms[word], score: Scorer.partialTitle }); + }); + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, {}); + scoreMap.get(file)[word] = record.score; + }); + }); + + // create the mapping + files.forEach((file) => { + if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1) + fileMap.get(file).push(word); + else fileMap.set(file, [word]); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter((term) => term.length > 2).length; + if (wordList.length !== searchTerms.size && wordList.length !== filteredTermCount) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file || + titleTerms[term] === file || + (terms[term] || []).includes(file) || + (titleTerms[term] || []).includes(file), + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); + // add result to the result list + results.push([docNames[file], titles[file], "", null, score, filenames[file]]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords) => { + const text = Search.htmlToText(htmlText); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, }; _ready(Search.init); diff --git a/docs/_static/sphinx_highlight.js b/docs/_static/sphinx_highlight.js index aae669d7e..5b6ab934c 100644 --- a/docs/_static/sphinx_highlight.js +++ b/docs/_static/sphinx_highlight.js @@ -1,143 +1,138 @@ /* Highlighting utilities for Sphinx HTML documentation. */ "use strict"; -const SPHINX_HIGHLIGHT_ENABLED = true +const SPHINX_HIGHLIGHT_ENABLED = true; /** * highlight a given string on a node by wrapping it in * span elements with the given class name. */ const _highlight = (node, addItems, text, className) => { - if (node.nodeType === Node.TEXT_NODE) { - const val = node.nodeValue; - const parent = node.parentNode; - const pos = val.toLowerCase().indexOf(text); - if ( - pos >= 0 && - !parent.classList.contains(className) && - !parent.classList.contains("nohighlight") - ) { - let span; + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; - const closestNode = parent.closest("body, svg, foreignObject"); - const isInSVG = closestNode && closestNode.matches("svg"); - if (isInSVG) { - span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); - } else { - span = document.createElement("span"); - span.classList.add(className); - } + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - parent.insertBefore( - span, - parent.insertBefore( - document.createTextNode(val.substr(pos + text.length)), - node.nextSibling - ) - ); - node.nodeValue = val.substr(0, pos); + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + parent.insertBefore( + span, + parent.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling, + ), + ); + node.nodeValue = val.substr(0, pos); - if (isInSVG) { - const rect = document.createElementNS( - "http://www.w3.org/2000/svg", - "rect" - ); - const bbox = parent.getBBox(); - rect.x.baseVal.value = bbox.x; - rect.y.baseVal.value = bbox.y; - rect.width.baseVal.value = bbox.width; - rect.height.baseVal.value = bbox.height; - rect.setAttribute("class", className); - addItems.push({ parent: parent, target: rect }); - } + if (isInSVG) { + const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); } - } else if (node.matches && !node.matches("button, select, textarea")) { - node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); - } }; const _highlightText = (thisNode, text, className) => { - let addItems = []; - _highlight(thisNode, addItems, text, className); - addItems.forEach((obj) => - obj.parent.insertAdjacentElement("beforebegin", obj.target) - ); + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => obj.parent.insertAdjacentElement("beforebegin", obj.target)); }; /** * Small JavaScript module for the documentation. */ const SphinxHighlight = { + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight - /** - * highlight the search words provided in localstorage in the text - */ - highlightSearchWords: () => { - if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight - - // get and clear terms from localstorage - const url = new URL(window.location); - const highlight = - localStorage.getItem("sphinx_highlight_terms") - || url.searchParams.get("highlight") - || ""; - localStorage.removeItem("sphinx_highlight_terms") - url.searchParams.delete("highlight"); - window.history.replaceState({}, "", url); + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") || + url.searchParams.get("highlight") || + ""; + localStorage.removeItem("sphinx_highlight_terms"); + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); - // get individual terms from highlight string - const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); - if (terms.length === 0) return; // nothing to do + // get individual terms from highlight string + const terms = highlight + .toLowerCase() + .split(/\s+/) + .filter((x) => x); + if (terms.length === 0) return; // nothing to do - // There should never be more than one element matching "div.body" - const divBody = document.querySelectorAll("div.body"); - const body = divBody.length ? divBody[0] : document.querySelector("body"); - window.setTimeout(() => { - terms.forEach((term) => _highlightText(body, term, "highlighted")); - }, 10); + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); - const searchBox = document.getElementById("searchbox"); - if (searchBox === null) return; - searchBox.appendChild( - document - .createRange() - .createContextualFragment( - '" - ) - ); - }, + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '", + ), + ); + }, - /** - * helper function to hide the search marks again - */ - hideSearchWords: () => { - document - .querySelectorAll("#searchbox .highlight-link") - .forEach((el) => el.remove()); - document - .querySelectorAll("span.highlighted") - .forEach((el) => el.classList.remove("highlighted")); - localStorage.removeItem("sphinx_highlight_terms") - }, + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document.querySelectorAll("#searchbox .highlight-link").forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms"); + }, - initEscapeListener: () => { - // only install a listener if it is really needed - if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; - document.addEventListener("keydown", (event) => { - // bail for input elements - if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; - // bail with special keys - if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; - if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { - SphinxHighlight.hideSearchWords(); - event.preventDefault(); - } - }); - }, + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && event.key === "Escape") { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, }; _ready(SphinxHighlight.highlightSearchWords); diff --git a/docs/searchindex.js b/docs/searchindex.js index 6e877ff97..383bf92cc 100644 --- a/docs/searchindex.js +++ b/docs/searchindex.js @@ -1 +1,6051 @@ -Search.setIndex({"docnames": ["_generated/cli_python_cmd_ref", "admin/general", "autoapi/datafed/CLI/index", "autoapi/datafed/CommandLib/index", "autoapi/datafed/Config/index", "autoapi/datafed/Connection/index", "autoapi/datafed/MessageLib/index", "autoapi/datafed/SDMS_Anon_pb2/index", "autoapi/datafed/SDMS_Auth_pb2/index", "autoapi/datafed/SDMS_pb2/index", "autoapi/datafed/VERSION/index", "autoapi/datafed/Version_pb2/index", "autoapi/datafed/index", "autoapi/index", "dev/design", "dev/project", "dev/release", "dev/roadmap", "index", "system/getting_started", "system/introduction", "system/overview", "system/papers", "system/usecases", "user/cli/guide", "user/cli/header", "user/cli/reference", "user/client/install", "user/python/high_level_guide", "user/python/notebooks", "user/web/portal"], "filenames": ["_generated/cli_python_cmd_ref.rst", "admin/general.rst", "autoapi/datafed/CLI/index.rst", "autoapi/datafed/CommandLib/index.rst", "autoapi/datafed/Config/index.rst", "autoapi/datafed/Connection/index.rst", "autoapi/datafed/MessageLib/index.rst", "autoapi/datafed/SDMS_Anon_pb2/index.rst", "autoapi/datafed/SDMS_Auth_pb2/index.rst", "autoapi/datafed/SDMS_pb2/index.rst", "autoapi/datafed/VERSION/index.rst", "autoapi/datafed/Version_pb2/index.rst", "autoapi/datafed/index.rst", "autoapi/index.rst", "dev/design.rst", "dev/project.rst", "dev/release.rst", "dev/roadmap.rst", "index.rst", "system/getting_started.rst", "system/introduction.rst", "system/overview.rst", "system/papers.rst", "system/usecases.rst", "user/cli/guide.rst", "user/cli/header.rst", "user/cli/reference.rst", "user/client/install.rst", "user/python/high_level_guide.rst", "user/python/notebooks.rst", "user/web/portal.rst"], "titles": ["Datafed Commands", "Administration", "datafed.CLI", "datafed.CommandLib", "datafed.Config", "datafed.Connection", "datafed.MessageLib", "datafed.SDMS_Anon_pb2", "datafed.SDMS_Auth_pb2", "datafed.SDMS_pb2", "datafed.VERSION", "datafed.Version_pb2", "datafed", "API Reference", "Architecture & Design", "Project Management", "Release Notes", "Feature Road Map", "DataFed - A Scientific Data Federation", "Getting Started", "Introduction", "System Overview", "Papers and Presentations", "Use Cases", "User Guide", "<no title>", "Command Reference", "Installation and Configuration", "Guide to High Level Interface", "Jupyter Notebooks", "Web Portal Guide"], "terms": {"i": [0, 1, 2, 3, 15, 16, 18, 19, 20, 21, 24, 25, 26, 28, 29, 30], "line": [0, 2, 19, 21, 24, 25, 26, 27, 28], "interfac": [0, 2, 3, 15, 16, 17, 20, 24, 25, 26, 27, 29, 30], "cli": [0, 3, 12, 13, 16, 17, 19, 21, 24, 25, 26, 27, 28, 30], "feder": [0, 2, 20, 21, 26], "manag": [0, 2, 3, 16, 17, 18, 19, 22, 24, 26, 30], "servic": [0, 2, 17, 20, 21, 26], "mai": [0, 1, 2, 3, 18, 19, 20, 21, 24, 26, 27, 28, 30], "us": [0, 1, 2, 3, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 30], "access": [0, 1, 2, 16, 17, 19, 20, 24, 25, 26, 27, 28, 30], "mani": [0, 2, 16, 20, 21, 26, 27, 28], "featur": [0, 2, 18, 19, 20, 21, 24, 26, 27, 30], "avail": [0, 2, 3, 16, 19, 20, 21, 24, 25, 26, 27, 28, 30], "via": [0, 1, 2, 3, 16, 19, 20, 21, 24, 25, 26, 27, 28, 30], "web": [0, 2, 16, 17, 19, 21, 26, 27, 28], "portal": [0, 2, 16, 17, 19, 21, 26, 27], "thi": [0, 1, 2, 3, 13, 16, 18, 19, 20, 21, 23, 24, 26, 27, 28, 30], "interact": [0, 1, 2, 21, 24, 25, 26, 27], "human": [0, 2, 3, 21, 24, 26, 28], "friendli": [0, 2, 21, 24, 26, 28], "output": [0, 2, 21, 24, 26, 28], "script": [0, 1, 2, 16, 19, 21, 24, 25, 26, 27, 28], "json": [0, 2, 3, 16, 21, 24, 26, 28], "specifi": [0, 2, 3, 21, 24, 26, 27, 28, 30], "": [0, 1, 2, 3, 19, 20, 21, 24, 26, 27, 28, 30], "option": [0, 1, 2, 3, 16, 19, 21, 24, 26, 27, 28, 30], "when": [0, 2, 3, 16, 19, 21, 24, 26, 27, 28, 30], "without": [0, 2, 3, 16, 20, 21, 24, 26, 28, 30], "ani": [0, 2, 3, 16, 19, 20, 21, 24, 25, 26, 27, 28, 30], "argument": [0, 2, 3, 24, 26, 28], "shell": [0, 2, 24, 25, 26, 27], "session": [0, 1, 2, 24, 26, 28], "start": [0, 1, 2, 3, 16, 18, 20, 21, 24, 26, 27], "while": [0, 2, 20, 21, 26, 28, 30], "should": [0, 1, 2, 3, 16, 19, 21, 26, 27, 28, 30], "enter": [0, 1, 2, 3, 16, 19, 21, 24, 26, 27, 28], "prefix": [0, 2, 3, 21, 26, 27, 28], "usag": [0, 16, 24, 26, 28], "arg": [0, 2, 24, 26], "descript": [0, 1, 2, 3, 19, 21, 24, 26, 30], "m": [0, 3, 24, 26], "manual": [0, 1, 2, 3, 21, 26, 27, 30], "auth": [0, 16, 26], "forc": [0, 2, 3, 26], "authent": [0, 2, 3, 17, 19, 20, 21, 24, 26, 28, 30], "non": [0, 2, 16, 17, 24, 25, 26, 27], "mode": [0, 2, 3, 16, 24, 26, 28], "intermedi": [0, 26], "o": [0, 26, 27, 28], "disabl": [0, 26, 27, 30], "certain": [0, 21, 24, 26], "client": [0, 1, 2, 3, 16, 17, 19, 21, 24, 26, 28], "side": [0, 16, 21, 26, 27, 30], "ar": [0, 1, 2, 3, 16, 18, 19, 20, 21, 24, 26, 27, 28, 30], "unavail": [0, 26], "version": [0, 1, 2, 3, 11, 12, 13, 16, 21, 24, 26, 28], "print": [0, 2, 24, 26, 28], "number": [0, 3, 16, 20, 21, 24, 26, 27, 28, 30], "server": [0, 1, 2, 3, 17, 21, 24, 26, 28], "cfg": [0, 1, 26, 27], "dir": [0, 1, 24, 26, 27, 28], "text": [0, 2, 3, 21, 24, 26, 28], "configur": [0, 2, 3, 17, 18, 19, 20, 21, 24, 26, 28, 29, 30], "directori": [0, 2, 3, 17, 21, 24, 26, 28], "file": [0, 1, 2, 3, 16, 17, 19, 20, 21, 24, 26, 28], "pub": [0, 26, 27], "kei": [0, 1, 3, 4, 18, 21, 24, 26, 28, 30], "public": [0, 1, 2, 3, 20, 26], "h": [0, 3, 24, 26, 27], "host": [0, 1, 15, 16, 19, 20, 21, 24, 26], "sever": [0, 1, 21, 24, 26, 27, 28], "name": [0, 1, 2, 3, 12, 16, 19, 21, 24, 26, 27, 28, 30], "ip": [0, 1, 26, 27], "address": [0, 1, 3, 18, 20, 26, 27, 28, 30], "p": [0, 21, 24, 26, 27, 28], "port": [0, 1, 3, 26], "integ": [0, 3, 26, 28], "priv": [0, 26, 27], "privat": [0, 1, 3, 21, 26, 28], "e": [0, 3, 16, 19, 20, 21, 26, 27, 28, 30], "globu": [0, 1, 2, 3, 16, 17, 18, 20, 21, 24, 26, 27, 28, 30], "endpoint": [0, 2, 3, 16, 17, 18, 20, 21, 24, 26, 28], "v": [0, 24, 26], "level": [0, 2, 3, 18, 21, 24, 26, 29], "0": [0, 1, 2, 3, 9, 10, 11, 18, 21, 24, 26, 28], "quiet": [0, 26], "1": [0, 1, 2, 3, 4, 7, 9, 13, 18, 20, 21, 24, 26, 28, 30], "normal": [0, 2, 16, 21, 24, 26], "2": [0, 2, 4, 8, 9, 10, 18, 20, 21, 24, 26, 28], "format": [0, 3, 20, 21, 24, 26, 27, 28], "onli": [0, 1, 2, 3, 19, 20, 21, 24, 26, 27, 28, 30], "show": [0, 2, 16, 19, 21, 24, 26, 28, 30], "messag": [0, 2, 3, 5, 16, 21, 24, 26, 27, 30], "sub": [0, 21, 24, 26, 28], "collect": [0, 1, 2, 3, 16, 18, 24, 26, 29, 30], "an": [0, 1, 2, 3, 15, 16, 18, 19, 20, 21, 24, 26, 27, 28, 29, 30], "content": [0, 21, 24, 26], "item": [0, 2, 3, 21, 24, 26, 30], "local": [0, 1, 2, 3, 16, 20, 21, 24, 26, 27, 28, 30], "credenti": [0, 2, 3, 19, 26, 27, 28, 30], "current": [0, 2, 3, 16, 17, 20, 21, 24, 26, 27, 28, 30], "displai": [0, 2, 16, 21, 26, 28, 30], "work": [0, 2, 16, 17, 18, 20, 21, 24, 26], "path": [0, 1, 2, 3, 16, 19, 21, 24, 26, 28], "record": [0, 2, 3, 16, 17, 18, 20, 26, 29, 30], "new": [0, 2, 3, 18, 20, 21, 24, 26, 28, 30], "one": [0, 1, 2, 3, 16, 19, 21, 24, 26, 27, 28, 30], "more": [0, 2, 3, 16, 21, 23, 24, 26, 28], "exist": [0, 1, 2, 3, 20, 21, 24, 26, 27, 28], "from": [0, 1, 2, 3, 16, 17, 19, 20, 21, 24, 25, 26, 27, 29, 30], "inform": [0, 1, 2, 3, 18, 19, 20, 21, 24, 26], "coll_id": [0, 2, 3, 26, 28], "destin": [0, 2, 3, 16, 19, 21, 26, 28], "item_id": [0, 2, 3, 26], "id": [0, 1, 2, 3, 7, 8, 16, 18, 21, 24, 26, 27], "alias": [0, 2, 3, 16, 18, 24, 26], "index": [0, 2, 17, 18, 20, 21, 24, 26], "valu": [0, 2, 3, 4, 16, 21, 24, 26, 27, 28], "also": [0, 1, 2, 3, 16, 19, 20, 21, 24, 26, 27, 28], "rel": [0, 2, 3, 26, 28], "x": [0, 24, 26, 28], "context": [0, 2, 3, 18, 19, 20, 21, 24, 26, 30], "alia": [0, 2, 3, 21, 24, 26], "see": [0, 1, 2, 3, 19, 21, 23, 24, 26, 27, 28], "The": [0, 1, 2, 3, 16, 18, 19, 20, 21, 24, 25, 26, 27, 28, 30], "titl": [0, 2, 3, 19, 21, 24, 26, 28, 30], "requir": [0, 1, 2, 3, 15, 16, 17, 19, 20, 21, 24, 26, 27, 28, 30], "other": [0, 2, 3, 20, 21, 24, 26, 27, 30], "attribut": [0, 21, 24, 26], "On": [0, 2, 3, 20, 24, 26, 27], "success": [0, 2, 3, 21, 24, 26, 28], "return": [0, 2, 16, 24, 26, 28, 30], "note": [0, 1, 2, 3, 18, 19, 20, 21, 24, 26, 27, 28, 30], "parent": [0, 2, 3, 16, 21, 24, 26, 30], "belong": [0, 2, 24, 26, 28], "collabor": [0, 2, 3, 18, 19, 20, 21, 24, 26, 28], "must": [0, 1, 2, 3, 16, 19, 21, 24, 26, 27, 28, 30], "have": [0, 1, 2, 3, 19, 20, 21, 24, 26, 27, 28, 30], "permiss": [0, 2, 16, 21, 24, 26, 28, 30], "write": [0, 2, 21, 24, 26, 27, 28], "d": [0, 3, 21, 24, 26, 28], "t": [0, 2, 3, 16, 24, 26, 28], "tag": [0, 2, 3, 16, 24, 26], "comma": [0, 24, 26], "separ": [0, 2, 3, 16, 21, 24, 26, 28], "topic": [0, 2, 3, 16, 21, 24, 26, 28], "publish": [0, 16, 17, 18, 20, 21, 24, 26], "provid": [0, 1, 2, 3, 16, 17, 18, 19, 20, 21, 24, 25, 26, 27, 28], "multipl": [0, 1, 2, 16, 20, 21, 24, 26, 28], "can": [0, 1, 2, 3, 16, 17, 18, 19, 20, 21, 24, 25, 26, 27, 28, 30], "By": [0, 2, 3, 26, 28, 30], "confirm": [0, 2, 26, 28], "prompt": [0, 2, 19, 24, 26, 27], "bypass": [0, 2, 16, 26], "contain": [0, 1, 2, 3, 13, 16, 18, 20, 21, 24, 26, 27, 28, 30], "howev": [0, 2, 3, 16, 19, 20, 21, 24, 26, 27, 28], "thei": [0, 1, 2, 3, 19, 21, 24, 26, 27, 28, 30], "link": [0, 2, 3, 16, 17, 19, 20, 21, 26, 27, 28, 30], "anoth": [0, 2, 3, 19, 21, 24, 26, 28, 30], "involv": [0, 2, 3, 21, 24, 26], "f": [0, 24, 26], "under": [0, 3, 16, 20, 21, 26, 28, 30], "administr": [0, 2, 17, 19, 21, 26, 27, 28, 30], "field": [0, 2, 3, 16, 19, 24, 26, 28], "identifi": [0, 2, 18, 24, 26, 28], "download": [0, 2, 3, 16, 18, 19, 21, 26, 27, 30], "raw": [0, 2, 3, 16, 18, 20, 26, 30], "upload": [0, 2, 3, 16, 18, 19, 21, 26, 27, 30], "locat": [0, 2, 16, 20, 21, 24, 26, 27, 28, 30], "absolut": [0, 2, 16, 26, 28], "input": [0, 2, 16, 19, 20, 26, 28], "filesystem": [0, 2, 26, 28], "individu": [0, 2, 3, 20, 21, 26, 27, 28], "object": [0, 2, 3, 17, 21, 24, 26], "arrai": [0, 2, 3, 16, 26, 28], "each": [0, 2, 21, 24, 26, 27, 28], "repres": [0, 2, 3, 21, 26], "compli": [0, 2, 3, 21, 26], "schema": [0, 2, 3, 16, 17, 20, 26], "onlin": [0, 2, 26], "document": [0, 2, 13, 16, 17, 19, 21, 26, 27, 28, 30], "c": [0, 2, 21, 24, 26, 28], "target": [0, 1, 21, 26], "root": [0, 1, 2, 3, 24, 26, 28, 30], "support": [0, 2, 3, 16, 17, 18, 20, 21, 24, 26, 27, 28], "conveni": [0, 2, 24, 26, 27, 28], "avoid": [0, 1, 2, 19, 21, 24, 26, 28], "dataput": [0, 2, 3, 24, 26, 28], "call": [0, 1, 2, 24, 26, 28], "r": [0, 21, 24, 26, 28], "remot": [0, 2, 17, 21, 24, 26], "none": [0, 2, 3, 5, 6, 24, 26, 28], "extens": [0, 2, 3, 21, 24, 26, 28], "overrid": [0, 3, 24, 26, 27], "auto": [0, 13, 21, 24, 26], "detect": [0, 3, 16, 24, 26], "extern": [0, 2, 3, 16, 21, 26, 27], "unmanag": [0, 3, 16, 26], "metadata": [0, 2, 3, 16, 17, 18, 20, 26, 30], "inlin": [0, 24, 26], "defin": [0, 2, 3, 16, 20, 21, 24, 26, 28], "type": [0, 3, 16, 19, 21, 24, 26, 27, 28], "cannot": [0, 2, 3, 16, 20, 21, 24, 26, 30], "enforc": [0, 3, 17, 21, 26], "fail": [0, 3, 16, 26, 28], "valid": [0, 3, 16, 21, 24, 26, 28, 30], "error": [0, 3, 16, 20, 21, 26, 27, 28], "repositori": [0, 2, 3, 17, 19, 24, 26, 27, 28], "alloc": [0, 3, 16, 18, 24, 26, 28], "dep": [0, 2, 3, 24, 26, 28], "choic": [0, 24, 26], "depend": [0, 3, 16, 18, 21, 24, 26, 27, 28, 30], "proven": [0, 17, 20, 24, 26], "per": [0, 24, 26, 27, 30], "string": [0, 2, 3, 21, 24, 26, 28], "consist": [0, 16, 21, 24, 26], "relationship": [0, 2, 3, 21, 24, 26], "der": [0, 3, 24, 26, 28], "comp": [0, 3, 24, 26, 28], "ver": [0, 3, 17, 24, 26, 28], "follw": [0, 24, 26], "referenc": [0, 21, 24, 26], "deriv": [0, 3, 16, 21, 24, 26, 28], "compon": [0, 16, 21, 24, 26, 28], "either": [0, 1, 2, 16, 19, 20, 21, 24, 26, 27, 28, 30], "full": [0, 2, 3, 17, 21, 26, 27, 28], "system": [0, 2, 3, 15, 16, 17, 18, 19, 20, 24, 25, 26, 27, 28], "If": [0, 1, 2, 3, 16, 19, 21, 24, 26, 27, 28, 30], "doesn": [0, 2, 16, 24, 26], "given": [0, 2, 3, 21, 24, 26, 27], "suffici": [0, 2, 19, 21, 26, 28, 30], "doe": [0, 2, 3, 16, 20, 21, 26, 27, 28, 30], "where": [0, 1, 2, 3, 19, 20, 21, 23, 24, 25, 26, 27, 28], "transfer": [0, 2, 3, 16, 17, 18, 19, 20, 21, 24, 26, 29], "case": [0, 1, 2, 18, 20, 21, 24, 26, 28, 30], "w": [0, 1, 3, 17, 26, 28], "wait": [0, 2, 3, 24, 26, 28], "block": [0, 26], "until": [0, 3, 16, 24, 26, 28, 30], "complet": [0, 3, 16, 19, 21, 24, 26, 28], "encrypt": [0, 1, 2, 3, 9, 16, 26, 27], "orig_fnam": [0, 2, 3, 26, 28], "origin": [0, 3, 16, 21, 26, 28], "filenam": [0, 3, 21, 26], "sourc": [0, 1, 2, 3, 15, 16, 19, 20, 21, 24, 26, 27, 28], "repli": [0, 2, 3, 16, 24, 26, 28], "further": [0, 21, 26], "replac": [0, 3, 16, 21, 24, 26], "instead": [0, 2, 3, 16, 20, 21, 24, 26, 28], "merg": [0, 3, 21, 26], "A": [0, 2, 3, 21, 24, 26, 27, 28, 30], "first": [0, 1, 2, 3, 24, 26, 27, 28], "time": [0, 2, 3, 19, 21, 24, 26, 27, 28], "rem": [0, 26], "follow": [0, 1, 3, 16, 19, 20, 21, 24, 26, 27, 28, 30], "truncat": [0, 2, 26], "shown": [0, 2, 19, 21, 24, 26, 27, 28, 30], "unless": [0, 2, 19, 26], "recent": [0, 2, 3, 21, 26, 28, 30], "activ": [0, 2, 16, 18, 20, 21, 24, 26, 28], "At": [0, 1, 2, 26, 28], "ctrl": [0, 2, 24, 26, 30], "includ": [0, 1, 2, 3, 16, 18, 20, 21, 24, 26, 27, 28, 30], "specif": [0, 1, 2, 3, 16, 18, 19, 20, 21, 24, 26, 27, 28], "omit": [0, 2, 26], "associ": [0, 2, 3, 16, 18, 20, 21, 24, 26, 28, 30], "wherea": [0, 2, 20, 26], "alwai": [0, 2, 16, 21, 24, 26, 27, 28, 30], "regardless": [0, 2, 21, 24, 26, 28], "offset": [0, 2, 3, 16, 26, 28], "count": [0, 2, 3, 16, 21, 26, 28], "limit": [0, 1, 3, 20, 26, 28], "result": [0, 3, 16, 18, 21, 24, 26, 27, 28], "own": [0, 1, 2, 3, 19, 20, 21, 26, 28, 30], "well": [0, 1, 2, 3, 20, 21, 26, 28], "were": [0, 2, 3, 16, 21, 26, 28], "member": [0, 2, 3, 17, 20, 21, 26, 28, 30], "admin": [0, 2, 3, 16, 17, 26, 28, 30], "administ": [0, 26], "membership": [0, 26], "role": [0, 2, 3, 21, 26, 30], "owner": [0, 2, 3, 16, 20, 21, 24, 26, 28, 30], "within": [0, 2, 3, 15, 18, 20, 21, 24, 25, 26, 27, 28, 30], "save": [0, 2, 3, 4, 16, 21, 26, 27, 30], "execut": [0, 2, 3, 16, 24, 26, 27], "direct": [0, 2, 21, 26], "search": [0, 2, 3, 16, 17, 18, 19, 20, 24, 26, 27, 28], "intead": [0, 26], "allow": [0, 2, 16, 20, 21, 24, 26, 27, 28, 30], "express": [0, 1, 3, 16, 21, 26, 30], "meta": [0, 2, 3, 16, 26, 28], "err": [0, 2, 26], "ha": [0, 1, 16, 21, 26, 27, 28, 30], "creator": [0, 2, 3, 16, 21, 24, 26, 28], "find": [0, 19, 21, 26, 27, 28], "date": [0, 3, 16, 21, 26, 27, 28, 30], "yyyi": [0, 3, 26], "hh": [0, 3, 26], "mm": [0, 3, 26], "up": [0, 1, 2, 3, 17, 19, 20, 21, 24, 26, 27, 28], "catalog": [0, 3, 16, 20, 26], "categori": [0, 2, 3, 16, 21, 24, 26, 30], "sort": [0, 2, 3, 16, 26], "ct": [0, 2, 21, 26, 28], "ut": [0, 2, 21, 26, 28], "rev": [0, 2, 26], "revers": [0, 26], "order": [0, 1, 19, 21, 24, 26, 27, 28], "scope": [0, 2, 3, 16, 21, 24, 26, 28, 30], "same": [0, 1, 2, 3, 16, 19, 21, 24, 26, 27, 28], "overal": [0, 2, 26], "least": [0, 2, 19, 24, 26], "term": [0, 2, 20, 21, 26], "match": [0, 2, 3, 19, 21, 26, 28, 30], "relev": [0, 2, 21, 26, 28], "rank": [0, 2, 26], "creation": [0, 2, 20, 21, 24, 26, 28], "respect": [0, 2, 24, 26, 28], "20": [0, 3, 24, 26, 28], "chang": [0, 2, 3, 16, 18, 20, 21, 24, 26, 27, 28, 30], "To": [0, 1, 2, 21, 24, 26, 28, 30], "empti": [0, 2, 16, 26], "instal": [0, 2, 3, 18, 21, 24, 26, 28, 29, 30], "subsequ": [0, 2, 3, 18, 20, 21, 24, 26, 27, 28], "read": [0, 2, 3, 21, 24, 26, 28], "u": [0, 3, 21, 24, 26, 27, 28], "statu": [0, 2, 3, 21, 24, 26, 28, 30], "filter": [0, 2, 3, 21, 26], "initi": [0, 2, 3, 21, 24, 26, 28, 30], "most": [0, 2, 3, 19, 20, 21, 24, 26, 27, 28], "period": [0, 2, 3, 19, 21, 26], "purg": [0, 2, 3, 26], "histori": [0, 2, 3, 24, 26], "30": [0, 2, 3, 24, 26], "dai": [0, 2, 3, 19, 26], "retain": [0, 2, 3, 17, 26], "sinc": [0, 2, 3, 21, 24, 26, 28], "second": [0, 3, 24, 26, 28], "suffix": [0, 3, 26, 27], "hour": [0, 3, 26], "week": [0, 3, 26], "3": [0, 1, 9, 10, 18, 20, 24, 25, 26, 28], "4": [0, 1, 4, 9, 18, 26, 27, 28, 30], "queu": [0, 26], "readi": [0, 3, 26, 28], "succeed": [0, 24, 26, 28], "latest": [0, 1, 2, 3, 26, 27], "common": [0, 1, 2, 3, 20, 21, 26], "uid": [0, 2, 3, 6, 16, 24, 26], "lowest": [0, 2, 26, 27], "highest": [0, 2, 26, 27], "previou": [0, 2, 19, 21, 24, 26, 28], "cd": [0, 1, 2, 24, 26], "switch": [0, 2, 17, 26], "differ": [0, 1, 2, 21, 26, 28], "In": [0, 1, 2, 19, 20, 21, 24, 26, 27, 28, 30], "grant": [0, 2, 21, 26, 30], "act": [0, 2, 21, 26], "indic": [0, 2, 21, 24, 26, 27], "colelct": [0, 2, 26], "deploi": [1, 20, 21], "build": 1, "third": [1, 21, 28], "parti": [1, 21], "packag": [1, 3, 16, 19, 21, 24, 25, 26], "process": [1, 3, 20, 21, 24, 28], "describ": [1, 2, 3, 21, 24, 27, 28, 30], "here": [1, 19, 21, 24, 27, 28, 29], "goal": [1, 18, 20], "eventu": [1, 18, 20, 21], "autom": [1, 19, 28], "much": [1, 28], "possibl": [1, 16, 19, 21, 24, 28], "technologi": [1, 15, 20, 21], "relat": [1, 3, 18, 20, 21, 24, 27, 28], "central": [1, 17, 21, 24], "which": [1, 2, 3, 18, 20, 21, 24, 27, 28, 30], "instanc": [1, 3], "These": [1, 3, 20, 21, 24, 27, 30], "list": [1, 2, 3, 16, 19, 21, 24, 27, 29, 30], "below": [1, 19, 20, 21, 24, 27, 28, 30], "hardwar": [1, 21], "select": [1, 16, 19, 21, 28, 30], "desir": [1, 28], "perform": [1, 16, 20, 21, 24, 27, 28, 30], "cost": [1, 21], "rang": [1, 21, 28], "singl": [1, 3, 17, 20, 21, 24, 28, 30], "node": [1, 21], "vm": 1, "dedic": [1, 20], "high": [1, 3, 18, 20, 21, 27, 29], "cluster": [1, 17, 24, 27, 28], "oper": [1, 17, 21, 24, 25, 26, 27], "linux": [1, 27], "distribut": [1, 20, 21, 24], "import": [1, 17, 21], "though": [1, 19, 21, 24, 28], "through": [1, 21, 24, 30], "test": [1, 15, 19, 21, 24], "moment": 1, "been": [1, 16, 21, 28, 30], "ubuntu": 1, "focal": [1, 30], "arango": 1, "togeth": [1, 21], "across": [1, 16, 18, 20, 21, 28], "latter": [1, 19], "chosen": [1, 3], "strongli": [1, 24], "recommend": [1, 19, 20, 24, 27, 28], "speed": [1, 21, 28], "reduc": [1, 16], "latenc": [1, 21], "need": [1, 3, 16, 18, 19, 20, 21, 24, 27, 28], "tl": [1, 17], "connect": [1, 3, 12, 13, 17, 19, 20, 21, 27], "gridftp": [1, 20, 21], "modul": [1, 18, 27, 28], "applic": [1, 18, 20, 21, 27, 28, 30], "python": [1, 3, 15, 16, 17, 19, 21, 24, 25, 26, 28, 29], "depli": 1, "built": [1, 19, 21, 24], "code": [1, 7, 8, 9, 11, 28], "github": [1, 15, 20], "prior": [1, 21, 27], "environ": [1, 18, 20, 21, 24, 25, 26, 27, 30], "properli": [1, 26], "exampl": [1, 19, 20, 21, 24, 27, 28, 30], "base": [1, 2, 15, 17, 20, 21, 24, 27, 28, 30], "debian": 1, "min": [1, 21], "max": [1, 21], "restrict": [1, 20, 21, 27], "later": [1, 16, 24, 28], "section": [1, 15, 21, 24, 27, 28, 30], "git": 1, "clone": 1, "http": [1, 3, 16, 17, 20, 21, 27, 28], "com": [1, 20], "ornl": [1, 15, 20, 21, 27, 28], "g": [1, 27], "cmake": 1, "libboost": 1, "all": [1, 2, 3, 16, 18, 20, 21, 24, 27, 28, 30], "dev": 1, "protobuf": [1, 3, 28], "compil": 1, "libzmq3": 1, "libssl": 1, "libcurl4": 1, "openssl": 1, "libglobu": 1, "libfus": 1, "nodej": 1, "npm": 1, "primarili": [1, 21, 24], "cooki": [1, 30], "parser": [1, 16], "helmet": 1, "ini": [1, 27], "protobufj": 1, "zeromq": [1, 17], "ect": 1, "oauth2": [1, 21], "done": [1, 21, 28], "helper": 1, "install_core_depend": 1, "sh": 1, "install_repo_depend": 1, "install_ws_depend": 1, "next": [1, 19, 27, 28], "step": [1, 19, 21, 27, 28], "config": [1, 3, 12, 13], "templat": 1, "you": [1, 19, 21, 24, 27, 28], "run": [1, 2, 3, 16, 21, 24, 27, 28], "generate_dataf": 1, "creat": [1, 2, 3, 13, 16, 18, 19, 20, 21, 27, 30], "datafed_default_log_path": 1, "repo": [1, 3, 16, 17, 24, 28], "datafed_database_password": 1, "datafed_zeromq_session_secret": 1, "datafed_zeromq_system_secret": 1, "datafed_lego_email": 1, "datafed_web_key_path": 1, "datafed_web_cert_path": 1, "datafed_globus_app_id": 1, "datafed_globus_app_secret": 1, "datafed_server_port": [1, 27], "datafed_domain": 1, "datafed_gcs_root_nam": 1, "gcs_collection_root_path": 1, "datafed_repo_id_and_dir": 1, "what": [1, 21, 28, 30], "variabl": [1, 27, 28], "found": [1, 21, 24], "onc": [1, 16, 19, 21, 24, 27, 30], "necessari": [1, 21, 27, 28], "seri": [1, 28], "develop": [1, 15, 20, 28, 30], "appropri": [1, 21, 24, 27], "automat": [1, 3, 17, 20, 21, 28, 30], "setup": [1, 2, 3, 18, 27, 28, 30], "default": [1, 2, 3, 21, 24, 30], "place": [1, 3, 19, 20, 21, 24, 28], "opt": [1, 2, 3, 4, 20, 21], "log": [1, 3, 5, 16, 19, 21, 27, 28, 30], "var": 1, "etc": [1, 3, 19, 20, 21, 27, 28, 30], "systemd": 1, "folder": [1, 3, 16, 21, 24, 27, 28], "grid": [1, 21], "secur": [1, 3, 20, 21, 27], "arangodb": 1, "your": [1, 19, 21, 27, 28], "7": [1, 9, 24, 27, 28], "wget": 1, "arangodb37": 1, "commun": [1, 3, 17, 19, 20, 21, 27, 28], "arangodb3_3": 1, "10": [1, 11, 24, 28], "1_amd64": 1, "deb": 1, "sudo": 1, "apt": 1, "It": [1, 19, 21, 24, 27, 28], "systemctl": 1, "arangodb3": 1, "we": [1, 24, 28], "foxx": 1, "machin": [1, 19, 21, 24, 27, 28], "arngodb": 1, "mkdir": 1, "b": [1, 24, 28], "dbuild_repo_serv": 1, "fals": [1, 2, 3, 4, 28], "dbuild_authz": 1, "dbuild_core_serv": 1, "dbuild_web_serv": 1, "dbuild_doc": 1, "dbuild_python_cli": 1, "dbuild_foxx": 1, "true": [1, 2, 3, 21, 24, 28], "parallel": [1, 24, 28], "6": [1, 9, 18, 30], "For": [1, 20, 21, 24, 26, 27, 28, 30], "befor": [1, 16, 19, 21, 24, 26, 28], "generage_core_config": 1, "generage_core_servic": 1, "9100": 1, "thread": 1, "task": [1, 2, 3, 16, 17, 18, 21, 24], "db": [1, 16, 17], "url": 1, "127": 1, "8529": 1, "_db": 1, "sdm": [1, 3, 20], "api": [1, 3, 4, 6, 16, 17, 18, 20, 21, 24, 27, 28], "user": [1, 2, 3, 15, 16, 18, 19, 20, 27, 28, 30], "pass": [1, 21, 27, 28], "password": [1, 2, 3, 6, 19, 21, 27, 28, 30], "cred": 1, "app": 1, "secret": 1, "generage_ws_config": 1, "addit": [1, 20, 21, 24, 27, 28, 30], "domain": [1, 3, 18, 20, 21], "certif": 1, "let": [1, 28], "install_lego_and_certif": 1, "look": [1, 19, 21, 24, 27, 28], "them": [1, 21, 28, 30], "exactli": 1, "open": [1, 15, 16, 19, 20, 21, 27, 28, 30], "appear": 1, "after": [1, 3, 16, 19, 20, 21, 24, 27], "command": [1, 2, 3, 16, 19, 21, 25, 27, 28, 30], "generage_ws_servic": 1, "v4": 1, "v5": 1, "curl": 1, "lo": 1, "org": [1, 16, 17, 19, 21], "toolkit": 1, "repo_latest_al": 1, "dpkg": 1, "get": [1, 2, 3, 4, 16, 17, 18, 24, 27, 30], "updat": [1, 2, 3, 16, 17, 21, 24, 28, 30], "help": [1, 2, 18, 20, 21, 28, 30], "set": [1, 2, 3, 4, 16, 18, 19, 20, 21], "correctli": [1, 28], "setup_globu": 1, "There": [1, 3, 21, 28], "instruct": [1, 19, 28], "scirpt": 1, "guest": 1, "abl": [1, 20, 21, 27, 28], "regist": [1, 18, 21, 27], "generate_repo_form": 1, "generage_repo_config": 1, "generage_repo_servic": 1, "generage_authz_config": 1, "5": [1, 9, 17, 18, 27, 28], "dglobus_vers": 1, "point": [1, 3, 16, 17, 19, 21, 27, 28, 30], "want": [1, 24, 28], "restart": 1, "gridft": 1, "ensur": [1, 3, 16, 19, 20, 21, 24, 28], "exchang": [1, 21], "_om_text": 2, "_om_json": 2, "_om_retn": 2, "_stat_ok": 2, "_stat_error": 2, "_capi": 2, "_return_v": 2, "_uid": 2, "_cur_ctx": 2, "_cur_col": 2, "_cur_coll_prefix": 2, "_cur_coll_titl": 2, "_cur_alias_prefix": 2, "_prev_col": 2, "_prev_ctx": 2, "_list_item": 2, "_interact": 2, "_verbosity_sticki": 2, "_verbos": 2, "_output_mode_sticki": 2, "_output_mod": 2, "_ctxt_set": 2, "_task_status": 2, "_task_typ": 2, "_initi": 2, "_devnul": 2, "_hdr_lev_char": 2, "init": 2, "loginbypassword": [2, 3], "loginbytoken": 2, "token": [2, 6], "_aliasedgroup": 2, "str": [2, 3, 28], "dict": [2, 3], "sequenc": [2, 28], "attr": 2, "click": [2, 19, 28, 30], "group": [2, 15, 17, 21], "subcommand": [2, 24], "attach": [2, 17, 19, 21, 28], "wai": [2, 20, 21, 28], "implement": [2, 16, 21, 28, 30], "nest": [2, 3, 24, 28], "paramet": [2, 16, 21, 28, 30], "map": [2, 18], "multicommand": 2, "basecommand": 2, "8": [2, 4, 9, 11], "commmand": 2, "get_command": 2, "ctx": 2, "cmd_name": 2, "resolve_command": 2, "_aliasedgrouproot": 2, "except": [2, 3, 16, 21, 24, 27, 28, 30], "_nocommand": 2, "kwarg": [2, 6], "exit": [2, 18, 24], "_set_script_cb": 2, "param": 2, "_set_verbosity_cb": 2, "__global_context_opt": 2, "_global_context_opt": 2, "func": 2, "__global_output_opt": 2, "_global_output_opt": 2, "_cli": 2, "data": [2, 3, 15, 16, 17, 22, 23, 25, 27, 29], "_gendoc": 2, "_gendochead": 2, "cmd": 2, "_gendoccmd": 2, "parnam": 2, "recurs": [2, 28], "_wc": 2, "project": [2, 3, 16, 17, 18, 19, 20, 24], "wc": [2, 16, 18, 24], "_wp": 2, "_data": 2, "_dataview": 2, "data_id": [2, 3], "view": [2, 3, 16, 18, 19, 20, 21, 30], "verbos": [2, 18, 24, 28], "_datacr": 2, "raw_data_fil": [2, 3], "metadata_fil": [2, 3], "schema_enforc": [2, 3], "_dataupd": 2, "metadata_set": [2, 3, 28], "deps_add": [2, 3, 28], "deps_rem": [2, 3], "_datadelet": 2, "delet": [2, 3, 16, 21, 24, 27, 28, 30], "_dataget": 2, "df_id": 2, "_dataput": 2, "put": [2, 3, 24, 27, 28, 30], "_batch": 2, "_data_batch_cr": 2, "batch": [2, 3, 17, 24], "_data_batch_upd": 2, "_list": 2, "share": [2, 3, 16, 17, 18, 19, 20, 21, 24, 27, 28], "l": [2, 16, 18, 24], "_coll": 2, "_collview": 2, "coll": [2, 3, 18, 24, 28], "_collcreat": 2, "_collupd": 2, "_colldelet": 2, "_collitemsadd": 2, "add": [2, 3, 16, 17, 20, 21, 24, 27, 30], "_coll_rem": 2, "remov": [2, 3, 16, 17, 21, 27, 30], "_queri": 2, "_querylist": 2, "queri": [2, 3, 16, 18, 20, 21, 29, 30], "_queryview": 2, "qry_id": 2, "_querycr": 2, "coll_mod": [2, 3], "meta_err": [2, 3], "time_from": [2, 3], "time_to": [2, 3], "sort_rev": [2, 3], "_queryupd": 2, "_querydelet": 2, "_queryexec": 2, "_queryrun": 2, "_user": 2, "_userlistcollab": 2, "_userlistal": 2, "_userview": 2, "_userwho": 2, "_project": 2, "_projectlist": 2, "_projectview": 2, "proj_id": 2, "_share": 2, "_task": 2, "_tasklist": 2, "_taskview": 2, "task_id": [2, 3, 28], "_ep": 2, "_epget": 2, "_epset": 2, "_eplist": 2, "_epdefault": 2, "_epdefaultget": 2, "_epdefaultset": 2, "_setup": 2, "_verbosityset": 2, "_help_cli": 2, "_exit_cli": 2, "_print_msg": 2, "_print_ack_repli": 2, "_print_list": 2, "_print_user_list": 2, "_print_proj_list": 2, "_print_endpoint": 2, "_print_data": 2, "_print_batch": 2, "_print_col": 2, "_print_dep": 2, "dr": 2, "_print_task_list": 2, "_print_task": 2, "_print_task_arrai": 2, "_print_us": 2, "_print_proj": 2, "_print_path": 2, "_print_queri": 2, "_wrap_text": 2, "indent": 2, "compact": 2, "_resolve_id": [2, 3, 28], "_resolve_coll_id": 2, "_generic_reply_handl": 2, "printfunc": 2, "_setworkingcollectiontitl": 2, "_arraytocsv": 2, "skip": [2, 27], "_arraytodot": 2, "_printjson": 2, "cur_ind": 2, "_printjson_list": 2, "_bar_adaptive_human_read": 2, "total": [2, 24, 28], "width": 2, "80": 2, "_addconfigopt": 2, "core": [3, 16, 17, 21, 27, 28], "send": [3, 5, 6, 21, 28], "request": [3, 17, 19, 21, 28], "sent": 3, "method": [3, 20, 28], "googl": [3, 17, 28], "proto": 3, "basic": [3, 21, 24, 25, 26, 28, 29], "function": [3, 16, 21, 24, 30], "th": [3, 28], "mirror": [3, 17], "capabl": [3, 16, 19, 20, 21, 24, 25, 26, 28], "expos": [3, 28], "load": [3, 16, 17, 21, 27, 28], "some": [3, 19, 21, 24, 27, 28], "suppli": [3, 28], "constructor": 3, "establish": [3, 28], "otherwis": [3, 21, 24, 28], "anonym": 3, "getauthus": 3, "check": [3, 16, 28], "construct": [3, 28], "_max_md_siz": 3, "int": [3, 27], "maximum": [3, 28], "size": [3, 20, 21, 24, 28], "byte": [3, 21], "102400": 3, "_max_payload_s": 3, "amount": [3, 21], "1048576": 3, "invalid": [3, 16, 21, 27], "present": [3, 16, 18, 20, 21, 27, 28, 30], "_endpoint_legaci": 3, "_endpoint_uuid": 3, "logout": [3, 6], "out": [3, 16, 20, 24, 27, 28, 30], "reset": [3, 5, 16, 28, 30], "underli": [3, 20, 21], "clear": [3, 16, 24, 28], "attempt": [3, 24], "generatecredenti": 3, "gener": [3, 7, 8, 9, 11, 13, 16, 18, 20, 21, 24, 26, 27, 28, 30], "msg": [3, 6, 28], "repocr": 3, "repo_id": [3, 28], "desc": [3, 21, 28], "capac": 3, "pub_kei": 3, "exp_path": 3, "home": [3, 19, 27], "intern": [3, 19, 21, 28], "detail": [3, 19, 21, 24, 26, 27, 28, 30], "fuse": 3, "so": [3, 19, 21, 28], "tcp": [3, 17, 27], "my": [3, 16, 21, 28], "cu": 3, "edu": 3, "9000": 3, "uuid": [3, 19, 28], "xxxxyyyyxxxx": 3, "xxxx": 3, "xxxxyyyi": 3, "posix": [3, 21], "seen": [3, 24, 28], "control": [3, 16, 18, 20, 30], "tony_stark": 3, "invent": 3, "could": [3, 19, 21, 23, 24, 28], "last": [3, 28], "right": [3, 19, 20, 21, 24, 28, 30], "pepper": 3, "repodatarepli": [3, 8], "respons": [3, 18, 21, 24], "repolist": 3, "list_al": 3, "bool": 3, "repodelet": 3, "ackrepli": [3, 7], "repoallocationcr": 3, "subject": [3, 21], "data_limit": [3, 28], "rec_limit": [3, 28], "repolistalloc": 3, "repoallocationdelet": 3, "dataview": [3, 28], "retriev": [3, 21], "NOT": 3, "resolut": 3, "recorddatarepli": [3, 8, 28], "datacr": [3, 28], "parent_id": [3, 28], "both": [3, 16, 20, 21, 24, 25, 26, 27, 28], "dictionari": [3, 28], "form": [3, 16, 21, 28], "compris": [3, 28], "flag": [3, 16, 21, 24, 27], "dataupd": [3, 28], "datadelet": [3, 28], "onr": 3, "dataget": [3, 28], "encrypt_avail": [3, 9], "timeout_sec": 3, "prepend": 3, "accord": [3, 28], "uniqu": [3, 20, 21, 24, 28], "overriden": 3, "take": [3, 20, 21, 27, 28], "background": [3, 16, 18, 21, 28], "asynchron": 3, "timeout": [3, 6, 27, 28], "poll": 3, "xfrdatarepli": 3, "databatchcr": [3, 28], "tupl": [3, 28], "databatchupd": [3, 28], "collectionview": [3, 28], "colldatarepli": [3, 8, 28], "collectioncr": [3, 28], "becom": [3, 21, 30], "publicli": [3, 19], "readabl": [3, 21, 28], "browser": [3, 16, 21, 30], "scientif": [3, 15, 21], "organ": [3, 17, 18, 20, 21, 24, 30], "ad": [3, 19, 20, 21, 27, 28], "collectionupd": 3, "collectiondelet": [3, 28], "OR": [3, 19, 27], "collectionitemslist": [3, 28], "page": [3, 13, 16, 19, 21, 24, 26, 27, 28, 30], "cleaner": 3, "listingrepli": [3, 8, 28], "collectionitemsupd": [3, 28], "add_id": [3, 28], "rem_id": [3, 28], "unlink": [3, 21, 30], "ancestor": 3, "grandpar": 3, "descend": [3, 28], "re": [3, 16, 30], "collectiongetpar": [3, 28], "inclus": 3, "ignor": [3, 21], "collpathrepli": [3, 8, 28], "querylist": [3, 28], "queryview": [3, 28], "query_id": [3, 28], "querydatarepli": [3, 8, 28], "querycr": [3, 28], "assign": [3, 21, 28], "queryupd": 3, "thing": [3, 28], "like": [3, 17, 21, 27, 28], "modifi": [3, 16, 20, 21], "querydelet": 3, "queryexec": [3, 28], "store": [3, 16, 17, 19, 20, 21, 27, 28, 30], "querydirect": 3, "directli": [3, 20, 21, 28], "_buildsearchrequest": 3, "userlistcollabor": 3, "userdatarepli": [3, 8], "userlistal": 3, "userview": 3, "projectlist": [3, 28], "part": [3, 28], "projectview": [3, 28], "project_id": 3, "projectdatarepli": [3, 8, 28], "projectgetrol": 3, "plai": [3, 21, 28], "sharedlist": 3, "inc_us": 3, "inc_project": 3, "sharedlistitem": 3, "owner_id": 3, "tasklist": [3, 28], "arrang": 3, "end": [3, 21, 22, 27, 28], "taskview": [3, 28], "regard": [3, 19, 28], "taskdatarepli": [3, 8, 28], "endpointlistrec": 3, "usergetrecenteprepli": [3, 8], "endpointdefaultget": 3, "endpointdefaultset": 3, "endpointget": 3, "endpointset": 3, "partial": [3, 21], "setupcredenti": 3, "setcontext": [3, 28], "resolv": [3, 16], "getcontext": [3, 28], "timestamptostr": 3, "convert": [3, 28], "timestamp": [3, 21], "standard": [3, 20, 21, 27], "struct_tim": 3, "represent": [3, 21], "strtotimestamp": 3, "time_str": 3, "y": [3, 28], "sizetostr": 3, "precis": [3, 18, 20], "metric": 3, "unit": [3, 21], "defaut": 3, "_uniquifyfilenam": 3, "alreadi": [3, 19, 21, 24, 27, 28], "pathlib": 3, "interest": [3, 28], "_resolvepathforhttp": 3, "_resolvepathforglobu": 3, "must_exist": 3, "whether": [3, 28], "_setsanedefaultopt": 3, "miss": [3, 16], "sane": 3, "determin": [3, 19, 21, 27, 30], "_opt_int": 4, "_opt_bool": 4, "_opt_path": 4, "_opt_no_env": 4, "_opt_no_cf": 4, "16": 4, "_opt_no_cl": 4, "32": [4, 24], "_opt_hid": 4, "64": 4, "_opt_eag": 4, "128": 4, "_opt_info": 4, "_processopt": 4, "_loadenvironvar": 4, "_loadconfigfil": 4, "cfg_file": 4, "prioriti": 4, "printsettinginfo": 4, "getopt": 4, "server_host": [5, 6], "server_port": [5, 6], "server_pub_kei": [5, 6], "client_pub_kei": [5, 6], "client_priv_kei": [5, 6], "zmq_ctxt": 5, "log_level": 5, "info": [5, 16], "__del__": 5, "registerprotocol": 5, "msg_modul": 5, "recv": [5, 6, 28], "a_timeout": 5, "1000": [5, 28], "ctxt": [5, 28], "makemessag": 5, "msg_name": 5, "get_latest_vers": 6, "package_nam": 6, "server_pub_key_fil": 6, "client_pub_key_fil": 6, "client_priv_key_fil": 6, "client_token": 6, "manual_auth": 6, "keysload": 6, "keysvalid": 6, "getauthstatu": 6, "manualauthbypassword": 6, "manualauthbytoken": 6, "getnackexceptionen": 6, "setnackexceptionen": 6, "enabl": [6, 16, 20, 21, 24, 27, 30], "setdefaulttimeout": 6, "getdefaulttimeout": 6, "getdailymessag": 6, "sendrecv": [6, 28], "nack_except": [6, 28], "protocol": [7, 8, 9, 11, 21, 27, 28], "buffer": [7, 8, 9, 11, 28], "_sym_db": [7, 8, 9, 11], "descriptor": [7, 8, 9, 11], "_protocol": [7, 8], "_ackrepli": 7, "_nackrepli": 7, "_versionrequest": 7, "_versionrepli": 7, "_getauthstatusrequest": 7, "_authenticatebypasswordrequest": 7, "_authenticatebytokenrequest": 7, "_authstatusrepli": 7, "_dailymessagerequest": 7, "_dailymessagerepli": 7, "nackrepli": [7, 28], "versionrequest": 7, "versionrepli": 7, "getauthstatusrequest": 7, "authenticatebypasswordrequest": 7, "authenticatebytokenrequest": 7, "authstatusrepli": 7, "dailymessagerequest": 7, "dailymessagerepli": 7, "_msg_name_to_typ": [7, 8], "_msg_type_to_nam": [7, 8], "_generatecredentialsrequest": 8, "_revokecredentialsrequest": 8, "_generatecredentialsrepli": 8, "_checkpermsrequest": 8, "_checkpermsrepli": 8, "_getpermsrequest": 8, "_getpermsrepli": 8, "_userviewrequest": 8, "_userdatarepli": 8, "_usersetaccesstokenrequest": 8, "_usergetaccesstokenrequest": 8, "_useraccesstokenrepli": 8, "_usercreaterequest": 8, "_userfindbyuuidsrequest": 8, "_userfindbynameuidrequest": 8, "_userupdaterequest": 8, "_userlistallrequest": 8, "_userlistcollabrequest": 8, "_usergetrecenteprequest": 8, "_usergetrecenteprepli": 8, "_usersetrecenteprequest": 8, "_listingrepli": 8, "_recordlistbyallocrequest": 8, "_recordviewrequest": 8, "_recorddatarepli": 8, "_recordcreaterequest": 8, "_recordcreatebatchrequest": 8, "_recordupdaterequest": 8, "_recordupdatebatchrequest": 8, "_recordexportrequest": 8, "_recordexportrepli": 8, "_recordlockrequest": 8, "_recorddeleterequest": 8, "_recordgetdependencygraphrequest": 8, "_recordallocchangerequest": 8, "_recordallocchangerepli": 8, "_recordownerchangerequest": 8, "_recordownerchangerepli": 8, "_datagetrequest": 8, "_dataputrequest": 8, "_datagetrepli": 8, "_dataputrepli": 8, "_datadeleterequest": 8, "_datapathrequest": 8, "_datapathrepli": 8, "_searchrequest": 8, "_collviewrequest": 8, "_colldatarepli": 8, "_collreadrequest": 8, "_collcreaterequest": 8, "_collupdaterequest": 8, "_colldeleterequest": 8, "_collwriterequest": 8, "_collmoverequest": 8, "_collgetparentsrequest": 8, "_collpathrepli": 8, "_collgetoffsetrequest": 8, "_collgetoffsetrepli": 8, "_colllistpublishedrequest": 8, "_groupcreaterequest": 8, "_groupupdaterequest": 8, "_groupdatarepli": 8, "_groupdeleterequest": 8, "_grouplistrequest": 8, "_groupviewrequest": 8, "_aclviewrequest": 8, "_aclupdaterequest": 8, "_aclsharedlistrequest": 8, "_aclsharedlistitemsrequest": 8, "_acldatarepli": 8, "_projectviewrequest": 8, "_projectdatarepli": 8, "_projectcreaterequest": 8, "_projectupdaterequest": 8, "_projectdeleterequest": 8, "_projectlistrequest": 8, "_projectsearchrequest": 8, "_projectgetrolerequest": 8, "_projectgetrolerepli": 8, "_repodatadeleterequest": 8, "_repodatagetsizerequest": 8, "_repodatasizerepli": 8, "_repopathcreaterequest": 8, "_repopathdeleterequest": 8, "_repolistrequest": 8, "_repoviewrequest": 8, "_repocreaterequest": 8, "_repoupdaterequest": 8, "_repodeleterequest": 8, "_repodatarepli": 8, "_repocalcsizerequest": 8, "_repocalcsizerepli": 8, "_repolistallocationsrequest": 8, "_repolistsubjectallocationsrequest": 8, "_repolistobjectallocationsrequest": 8, "_repoviewallocationrequest": 8, "_repoallocationsrepli": 8, "_repoallocationstatsrequest": 8, "_repoallocationstatsrepli": 8, "_repoallocationcreaterequest": 8, "_repoallocationsetrequest": 8, "_repoallocationsetdefaultrequest": 8, "_repoallocationdeleterequest": 8, "_repoauthzrequest": 8, "_querycreaterequest": 8, "_queryupdaterequest": 8, "_querydeleterequest": 8, "_querylistrequest": 8, "_queryviewrequest": 8, "_queryexecrequest": 8, "_querydatarepli": 8, "_notelistbysubjectrequest": 8, "_noteviewrequest": 8, "_notecreaterequest": 8, "_noteupdaterequest": 8, "_notecommenteditrequest": 8, "_notedatarepli": 8, "_taskviewrequest": 8, "_tasklistrequest": 8, "_taskdatarepli": 8, "_tagsearchrequest": 8, "_taglistbycountrequest": 8, "_tagdatarepli": 8, "_metadatavalidaterequest": 8, "_metadatavalidaterepli": 8, "_schemaviewrequest": 8, "_schemasearchrequest": 8, "_schemadatarepli": 8, "_schemacreaterequest": 8, "_schemaupdaterequest": 8, "_schemareviserequest": 8, "_schemadeleterequest": 8, "_topiclisttopicsrequest": 8, "_topicviewrequest": 8, "_topicsearchrequest": 8, "_topicdatarepli": 8, "generatecredentialsrequest": 8, "revokecredentialsrequest": 8, "generatecredentialsrepli": 8, "checkpermsrequest": 8, "checkpermsrepli": 8, "getpermsrequest": 8, "getpermsrepli": 8, "userviewrequest": 8, "usersetaccesstokenrequest": 8, "usergetaccesstokenrequest": 8, "useraccesstokenrepli": 8, "usercreaterequest": 8, "userfindbyuuidsrequest": 8, "userfindbynameuidrequest": 8, "userupdaterequest": 8, "userlistallrequest": 8, "userlistcollabrequest": 8, "usergetrecenteprequest": 8, "usersetrecenteprequest": 8, "recordlistbyallocrequest": 8, "recordviewrequest": 8, "recordcreaterequest": 8, "recordcreatebatchrequest": 8, "recordupdaterequest": 8, "recordupdatebatchrequest": 8, "recordexportrequest": 8, "recordexportrepli": 8, "recordlockrequest": 8, "recorddeleterequest": 8, "recordgetdependencygraphrequest": 8, "recordallocchangerequest": 8, "recordallocchangerepli": 8, "recordownerchangerequest": 8, "recordownerchangerepli": 8, "datagetrequest": 8, "dataputrequest": 8, "datagetrepli": [8, 28], "dataputrepli": [8, 28], "datadeleterequest": 8, "datapathrequest": 8, "datapathrepli": 8, "searchrequest": 8, "collviewrequest": 8, "collreadrequest": 8, "collcreaterequest": 8, "collupdaterequest": 8, "colldeleterequest": 8, "collwriterequest": 8, "collmoverequest": 8, "collgetparentsrequest": 8, "collgetoffsetrequest": 8, "collgetoffsetrepli": 8, "colllistpublishedrequest": 8, "groupcreaterequest": 8, "groupupdaterequest": 8, "groupdatarepli": 8, "groupdeleterequest": 8, "grouplistrequest": 8, "groupviewrequest": 8, "aclviewrequest": 8, "aclupdaterequest": 8, "aclsharedlistrequest": 8, "aclsharedlistitemsrequest": 8, "acldatarepli": 8, "projectviewrequest": 8, "projectcreaterequest": 8, "projectupdaterequest": 8, "projectdeleterequest": 8, "projectlistrequest": 8, "projectsearchrequest": 8, "projectgetrolerequest": 8, "projectgetrolerepli": 8, "repodatadeleterequest": 8, "repodatagetsizerequest": 8, "repodatasizerepli": 8, "repopathcreaterequest": 8, "repopathdeleterequest": 8, "repolistrequest": 8, "repoviewrequest": 8, "repocreaterequest": 8, "repoupdaterequest": 8, "repodeleterequest": 8, "repocalcsizerequest": 8, "repocalcsizerepli": 8, "repolistallocationsrequest": 8, "repolistsubjectallocationsrequest": 8, "repolistobjectallocationsrequest": 8, "repoviewallocationrequest": 8, "repoallocationsrepli": 8, "repoallocationstatsrequest": 8, "repoallocationstatsrepli": 8, "repoallocationcreaterequest": 8, "repoallocationsetrequest": 8, "repoallocationsetdefaultrequest": 8, "repoallocationdeleterequest": 8, "repoauthzrequest": 8, "querycreaterequest": 8, "queryupdaterequest": 8, "querydeleterequest": 8, "querylistrequest": 8, "queryviewrequest": 8, "queryexecrequest": 8, "notelistbysubjectrequest": 8, "noteviewrequest": 8, "notecreaterequest": 8, "noteupdaterequest": 8, "notecommenteditrequest": 8, "notedatarepli": 8, "taskviewrequest": 8, "tasklistrequest": 8, "tagsearchrequest": 8, "taglistbycountrequest": 8, "tagdatarepli": 8, "metadatavalidaterequest": 8, "metadatavalidaterepli": 8, "schemaviewrequest": 8, "schemasearchrequest": 8, "schemadatarepli": 8, "schemacreaterequest": 8, "schemaupdaterequest": 8, "schemareviserequest": 8, "schemadeleterequest": 8, "topiclisttopicsrequest": 8, "topicviewrequest": 8, "topicsearchrequest": 8, "topicdatarepli": 8, "_errorcod": 9, "errorcod": 9, "_servicestatu": 9, "servicestatu": 9, "_searchmod": 9, "searchmod": 9, "_dependencytyp": 9, "dependencytyp": 9, "_dependencydir": 9, "dependencydir": 9, "_sortopt": 9, "sortopt": 9, "_projectrol": 9, "projectrol": 9, "_notetyp": 9, "notetyp": 9, "_notest": 9, "notest": 9, "_tasktyp": 9, "tasktyp": 9, "_taskstatu": 9, "taskstatu": 9, "_taskcommand": 9, "taskcommand": 9, "_encrypt": 9, "id_bad_request": 9, "id_internal_error": 9, "id_client_error": 9, "id_service_error": 9, "id_authn_requir": 9, "id_authn_error": 9, "id_dest_path_error": 9, "id_dest_file_error": 9, "ss_normal": 9, "ss_degrad": 9, "ss_fail": 9, "ss_offlin": 9, "sm_data": 9, "sm_collect": 9, "dep_is_derived_from": [9, 28], "dep_is_component_of": 9, "dep_is_new_version_of": 9, "dep_type_count": 9, "dep_in": 9, "dep_out": [9, 28], "sort_id": 9, "sort_titl": 9, "sort_own": 9, "sort_time_cr": 9, "sort_time_upd": 9, "sort_relev": 9, "proj_no_rol": 9, "proj_memb": 9, "proj_manag": 9, "proj_admin": 9, "note_quest": 9, "note_info": 9, "note_warn": 9, "note_error": 9, "note_clos": 9, "note_open": 9, "note_act": 9, "tt_data_get": [9, 28], "tt_data_put": [9, 28], "tt_data_del": 9, "tt_rec_chg_alloc": 9, "tt_rec_chg_own": 9, "tt_rec_del": 9, "tt_alloc_cr": 9, "tt_alloc_del": 9, "tt_user_del": 9, "tt_proj_del": 9, "9": [9, 21], "ts_block": 9, "ts_readi": [9, 28], "ts_run": 9, "ts_succeed": [9, 28], "ts_fail": 9, "tc_stop": 9, "tc_raw_data_transf": 9, "tc_raw_data_delet": 9, "tc_raw_data_update_s": 9, "tc_alloc_cr": 9, "tc_alloc_delet": 9, "encrypt_non": 9, "encrypt_forc": 9, "_allocstatsdata": 9, "_allocdata": 9, "_dependencydata": 9, "_dependencyspecdata": 9, "_userdata": 9, "_projectdata": 9, "_listingdata": 9, "_tagdata": 9, "_pathdata": 9, "_recorddata": 9, "_recorddataloc": 9, "_reporecorddataloc": 9, "_recorddatas": 9, "_colldata": 9, "_groupdata": 9, "_aclrul": 9, "_topicdata": 9, "_repodata": 9, "_notecom": 9, "_notedata": 9, "_taskdata": 9, "_schemadata": 9, "allocstatsdata": 9, "allocdata": 9, "dependencydata": 9, "dependencyspecdata": 9, "userdata": 9, "projectdata": 9, "listingdata": 9, "tagdata": 9, "pathdata": 9, "recorddata": 9, "recorddataloc": 9, "reporecorddataloc": 9, "recorddatas": 9, "colldata": 9, "groupdata": 9, "aclrul": 9, "topicdata": 9, "repodata": 9, "notecom": 9, "notedata": 9, "taskdata": 9, "schemadata": 9, "__version__": 10, "_version": 11, "datafed_release_year": 11, "2023": 11, "datafed_release_month": 11, "datafed_release_dai": 11, "21": 11, "datafed_release_hour": 11, "datafed_release_minut": 11, "40": [11, 24], "datafed_common_protocol_api_major": 11, "datafed_common_protocol_api_minor": 11, "datafed_common_protocol_api_patch": 11, "commandlib": [12, 13, 28], "messagelib": [12, 13, 28], "sdms_anon_pb2": [12, 13], "sdms_auth_pb2": [12, 13], "sdms_pb2": [12, 13], "version_pb2": [12, 13], "dataf": [13, 15, 16, 17, 21, 22, 23, 24, 25, 27, 29, 30], "sphinx": 13, "autoapi": 13, "go": [15, 21, 27, 28], "team": [15, 20, 21, 28], "oak": [15, 20, 21], "ridg": [15, 20, 21], "nation": [15, 20, 21], "laboratori": [15, 20, 21], "advanc": [15, 16, 18, 21, 24], "ATS": 15, "leadership": [15, 20, 21], "comput": [15, 20, 21, 22, 24, 25, 26, 27, 28], "facil": [15, 17, 18, 19, 20, 27, 28], "olcf": [15, 19, 20, 21, 28], "olga": 15, "kuchar": 15, "lifecycl": [15, 18], "scalabl": [15, 18, 20, 21], "workflow": [15, 20, 28], "leader": 15, "dale": 15, "stansberri": 15, "sr": 15, "softwar": [15, 21, 28], "pi": 15, "architect": 15, "lead": [15, 16, 21], "suha": [15, 28], "somnath": [15, 24, 28], "scientist": 15, "jessica": 15, "breet": 15, "minor": 16, "two": [16, 19, 21, 24, 28], "signific": [16, 20, 21], "refer": [16, 18, 24, 28], "pypi": [16, 21], "although": 16, "wa": [16, 20, 21, 24, 27, 28], "continu": [16, 18, 21], "caus": 16, "treat": [16, 21], "stabl": 16, "abil": [16, 20, 21], "appli": [16, 20, 21], "util": [16, 20, 21, 24, 25, 26], "conform": 16, "compliant": 16, "tab": [16, 19, 21, 28, 30], "reject": [16, 21], "footer": [16, 18], "area": 16, "toggleabl": 16, "bar": [16, 30], "similar": [16, 21, 24, 28], "visibl": [16, 21, 28], "toggl": 16, "magnifi": 16, "glass": 16, "icon": 16, "toolbar": 16, "aka": 16, "dramat": 16, "overhaul": 16, "better": [16, 20], "longer": [16, 21, 28], "over": [16, 20, 21, 27, 28], "significantli": [16, 20], "due": [16, 21, 30], "fundament": 16, "how": [16, 20, 21, 23, 24, 27, 28], "structur": [16, 20, 21, 24, 28, 30], "760": [16, 28], "being": [16, 20, 21, 24, 27, 28], "wrong": 16, "759": [16, 28], "simplifi": [16, 21, 28], "758": [16, 28], "twice": 16, "757": [16, 28], "756": 16, "incomplet": 16, "755": 16, "754": 16, "753": 16, "752": 16, "751": 16, "749": 16, "acl": 16, "mishandl": [16, 21], "ownership": [16, 21], "745": 16, "744": 16, "742": 16, "aql": 16, "recogn": 16, "741": 16, "739": 16, "do": [16, 19, 21, 27, 28], "738": 16, "737": 16, "databas": [16, 17, 21], "post": [16, 21], "bodi": 16, "736": 16, "735": 16, "panel": [16, 18, 28], "light": [16, 30], "theme": [16, 30], "733": 16, "731": 16, "border": 16, "annot": 16, "730": 16, "729": 16, "close": [16, 18, 21], "727": 16, "dialog": [16, 19, 21, 27, 30], "726": 16, "hide": 16, "725": 16, "builder": [16, 21], "trigger": [16, 24], "723": 16, "highlight": 16, "color": [16, 28], "too": [16, 28], "dark": [16, 30], "722": 16, "721": 16, "neg": 16, "regular": 16, "720": 16, "713": 16, "bit": 16, "mask": 16, "conflict": 16, "712": 16, "did": [16, 24, 28], "711": 16, "709": 16, "report": 16, "actual": [16, 24, 28], "708": 16, "checksum": 16, "failur": [16, 17], "caught": 16, "707": 16, "700": 16, "revis": 16, "698": 16, "rework": 16, "tree": [16, 30], "drag": [16, 18], "drop": [16, 18], "696": 16, "ref": 16, "sync": 16, "695": 16, "694": 16, "693": 16, "691": 16, "un": 16, "track": [16, 21, 28, 30], "690": 16, "reopen": 16, "687": 16, "683": 16, "edg": 16, "681": 16, "680": 16, "break": 16, "677": 16, "expand": [16, 28, 30], "675": 16, "defer": 16, "674": 16, "673": 16, "672": 16, "duplic": 16, "671": 16, "670": 16, "668": 16, "move": [16, 20, 21, 28, 30], "trivial": [16, 24, 28], "anon": 16, "667": 16, "short": [16, 19], "666": 16, "rid": 16, "664": 16, "condit": [16, 21], "660": 16, "659": 16, "657": 16, "shall": 16, "edit": [16, 19, 21, 30], "656": 16, "definit": 16, "652": 16, "647": 16, "scroll": [16, 19], "643": 16, "605": 16, "uri": [16, 21], "602": 16, "596": [16, 17], "improv": [16, 17, 20], "570": 16, "569": 16, "handl": [16, 18, 20], "def": [16, 28], "564": 16, "563": 16, "circular": 16, "220": 16, "33": [16, 17], "strict": [16, 24], "pars": [16, 28], "rule": [16, 21], "accept": [16, 28], "float": 16, "between": [16, 20, 21, 28], "zero": 16, "25": [16, 24], "graphic": [16, 21], "editor": [16, 24], "blank": 16, "person": [16, 18, 21, 24, 27, 28], "catagori": 16, "yet": [16, 20, 21, 28], "594": 17, "597": 17, "event": [17, 20, 27], "notif": [17, 20, 21], "subscript": [17, 20, 28], "401": 17, "multimedia": 17, "12": [17, 21, 28], "571": 17, "35": 17, "affili": 17, "contact": [17, 21, 30], "sci": 17, "network": [17, 18, 20, 21], "geo": 17, "rest": 17, "altern": [17, 21, 24, 27, 28], "595": 17, "hl": 17, "598": 17, "599": 17, "600": 17, "scale": [17, 20], "resili": 17, "replic": 17, "back": [17, 28, 30], "comm": 17, "balanc": 17, "exclus": [17, 19, 21], "dynam": [17, 21], "farm": 17, "polici": [17, 20, 21], "impact": [17, 21], "rebuild": 17, "modern": [17, 21], "framework": [17, 21], "integr": [17, 21, 24], "easili": [17, 20, 21], "would": [17, 19, 21, 24, 27, 28], "ingest": [17, 20], "tool": [17, 18, 19, 20, 21, 27, 28], "extract": 17, "tar": 17, "zip": 17, "synchron": 17, "revisit": [17, 28], "peer": 17, "architectur": [17, 18], "robust": [17, 21], "still": [17, 20, 21], "think": [17, 21], "veri": [17, 19, 20, 24, 28, 30], "slow": 17, "larg": [17, 18, 20, 21, 24, 28], "critic": [18, 20, 21], "holist": [18, 20, 21], "fair": [18, 20], "principl": [18, 19, 20, 28], "big": [18, 20], "enhanc": [18, 20], "product": [18, 20], "reproduc": [18, 20, 21], "orient": [18, 20], "research": [18, 19, 20, 21], "earli": [18, 20], "stage": [18, 20], "serv": [18, 20], "eas": [18, 20], "burden": [18, 20, 21], "captur": [18, 20, 21, 28], "potenti": [18, 20, 21], "volum": [18, 20, 24], "heterogen": [18, 20], "refin": [18, 20], "prepar": [18, 20], "site": [18, 20, 28], "program": [18, 20, 21, 27, 28], "introduct": [18, 28, 29], "overview": [18, 22, 24, 28], "introduc": [18, 21, 22], "terminologi": [18, 21], "concept": [18, 24, 28], "why": 18, "cross": [18, 28], "account": [18, 27, 28], "paper": 18, "guid": [18, 19, 21, 26, 27], "action": [18, 21], "button": [18, 19, 27, 28], "header": 18, "syntax": 18, "shortcut": 18, "comment": 18, "ep": [18, 27], "wp": 18, "remark": 18, "jupyt": 18, "notebook": 18, "deploy": 18, "personnel": 18, "design": [18, 20, 21], "releas": [18, 20, 21], "28": 18, "2021": [18, 28], "road": 18, "plan": [18, 19], "pleas": [19, 21, 23, 24, 27, 28], "institut": [19, 27, 28], "left": [19, 21, 28, 30], "hand": [19, 20, 28, 29, 30], "pane": [19, 28], "ident": [19, 20, 21, 28, 30], "window": [19, 27, 28], "One": [19, 21, 28], "primari": [19, 20, 21, 24, 25, 26], "crown": 19, "your_usernam": 19, "globusid": [19, 28], "visit": [19, 27, 28], "top": [19, 20, 21, 30], "yourself": 19, "usernam": [19, 27], "dure": [19, 20], "registr": [19, 21], "As": [19, 21, 24, 28], "suggest": [19, 28], "just": [19, 24, 28], "storag": [19, 20, 21], "space": [19, 21, 24, 28], "manipul": 19, "investig": [19, 28], "IT": [19, 21], "make": [19, 21, 24, 28], "sure": [19, 28], "far": [19, 21, 24, 28], "few": [19, 20, 27, 28], "everi": [19, 28], "intend": [19, 20, 21, 24, 27, 28], "tabl": [19, 21, 27], "popular": [19, 21, 28], "summit": 19, "Andes": 19, "jupyterhub": 19, "dtn": [19, 24, 28], "alcf": [19, 24], "theta": 19, "dtn_theta": 19, "mira": 19, "coolei": 19, "dtn_mira": 19, "nersc": [19, 24], "cori": 19, "cade": [19, 24, 27, 28], "moder": 19, "mod": 19, "abov": [19, 24, 27, 28], "box": [19, 21, 28], "seem": 19, "reason": [19, 21], "those": [19, 21, 27, 28], "clearli": [19, 24, 28], "three": [19, 21, 24], "dot": 19, "signifi": 19, "about": [19, 21, 23, 24, 26, 28, 30], "down": [19, 21, 24], "till": 19, "legaci": [19, 28], "simpli": [19, 21, 24, 27, 28, 30], "portion": [19, 21], "delai": 19, "scenario": [19, 21, 28], "reactiv": 19, "expir": [19, 21], "typic": [19, 20, 21, 27, 28], "renew": 19, "inde": [19, 24, 28], "handi": [19, 28], "orchestr": [19, 21, 24, 28], "termin": [19, 24, 27, 28], "alpha": 20, "state": [20, 21, 24, 27], "qualiti": [20, 21], "artifact": 20, "uniformli": 20, "geograph": [20, 21, 24], "thought": 20, "tier": 20, "mean": [20, 21, 24, 25, 26, 28], "medium": 20, "long": [20, 21, 27, 28], "unlik": [20, 21, 28], "compromis": 20, "favor": 20, "archiv": [20, 21], "dissemin": 20, "downstream": [20, 21], "consum": [20, 21], "alert": 20, "power": [20, 21, 24, 28], "easi": [20, 21, 27, 28], "encourag": [20, 24, 27, 28], "band": 20, "hoc": [20, 21], "prone": 20, "email": [20, 21], "effici": 20, "layer": [20, 28], "permit": [20, 21, 30], "know": [20, 24, 28], "physic": [20, 21, 28], "becaus": [20, 21, 28, 30], "reli": [20, 21], "heavili": [20, 21], "familiar": [20, 21, 28], "themselv": [20, 21, 28], "tradit": [20, 21], "small": [20, 24, 28], "virtual": [20, 21, 27], "vo": 20, "predetermin": 20, "readili": 20, "static": [20, 21], "dataset": [20, 21, 28], "usual": [20, 28], "thu": [20, 21], "neither": 20, "sdmss": 20, "nor": [20, 21], "accommod": 20, "combin": [20, 21, 27], "benefit": [20, 24, 28], "unstructur": 20, "diverg": 20, "briefli": 20, "blend": 20, "uniform": [20, 21], "concis": 20, "logic": [20, 21, 24], "wide": [20, 21], "live": [20, 24, 28], "throughout": 20, "pre": [20, 21, 28], "practic": 20, "awar": [20, 21], "foundat": 20, "figur": [20, 21], "illustr": [20, 28], "analysi": 20, "proper": [20, 21], "contract": 20, "sponsor": 20, "dispers": 20, "who": [20, 24, 28], "experiment": [20, 21], "observ": [20, 21, 23, 28], "analyt": [20, 23, 24, 25, 26], "resourc": [20, 21], "depart": [20, 21], "energi": [20, 21], "agnostic": 20, "purpos": [20, 21, 24, 28], "methodologi": [20, 28], "neutral": 20, "despit": 20, "augment": 20, "complex": [20, 21, 28], "mechan": [20, 21, 27], "contrast": 20, "span": 20, "highli": [20, 24, 28], "labor": 20, "intens": 20, "beyond": 20, "understand": [20, 21, 24], "often": 20, "tightli": 20, "coupl": 20, "defacto": 20, "movement": [20, 21, 24, 28], "petabyt": 20, "govern": 20, "fund": 20, "univers": [20, 21, 24], "commerci": 20, "cloud": 20, "focus": 20, "overreach": 20, "bundl": 20, "complementari": 20, "instrument": 20, "workstat": [21, 27], "along": [21, 27, 28], "discoveri": 21, "backplan": 21, "disjoint": 21, "conceptu": 21, "agnost": 21, "aim": [21, 28], "scienc": [21, 22, 23, 28], "hpc": 21, "ti": 21, "independ": 21, "approach": [21, 28], "prevent": 21, "silo": 21, "suppress": [21, 24], "outsid": [21, 24, 28], "rather": [21, 24, 28, 30], "than": [21, 24, 28, 30], "particular": 21, "maintain": [21, 27], "protect": [21, 27], "inadvert": 21, "coordin": [21, 28], "toward": [21, 28], "unifi": 21, "inher": 21, "entropi": 21, "misidentif": 21, "loss": 21, "enclos": 21, "grai": 21, "boundari": 21, "blue": 21, "arrow": [21, 24, 28], "bu": 21, "green": 21, "cylind": 21, "label": 21, "assum": [21, 28], "lower": [21, 27], "likewis": 21, "copi": 21, "never": [21, 30], "fine": 21, "grain": 21, "undu": 21, "disrupt": 21, "perspect": 21, "behav": [21, 24], "notic": [21, 28], "increas": 21, "discuss": [21, 24], "compos": 21, "essenti": [21, 24, 27, 28], "brain": 21, "concurr": [21, 24], "deleg": 21, "pathwai": 21, "s3": 21, "inherit": 21, "reliabl": 21, "inexpens": 21, "magnet": 21, "disk": 21, "solid": 21, "drive": [21, 28], "even": [21, 24, 28], "revok": [21, 27, 30], "isol": 21, "mount": 21, "interconnect": 21, "author": 21, "identif": [21, 28], "behalf": [21, 24, 28], "low": [21, 28], "easiest": 21, "laptop": [21, 27], "issu": [21, 24], "free": [21, 28], "getting_start": 21, "assist": 21, "acquir": 21, "futur": [21, 28], "searchabl": 21, "made": 21, "begin": 21, "welcom": [21, 24], "redirect": 21, "ask": [21, 28], "explicitli": [21, 27, 28, 30], "constrain": 21, "transient": 21, "variou": [21, 27, 28], "organiz": 21, "feel": 21, "whole": 21, "upon": 21, "good": 21, "brief": [21, 28], "alphabet": 21, "greater": [21, 28], "outcom": 21, "propag": 21, "assess": 21, "fix": 21, "entiti": [21, 28], "textual": 21, "ie": 21, "confus": 21, "categor": 21, "hierarch": [21, 24], "irrevoc": 21, "alphanumer": [21, 28], "manageri": 21, "reserv": 21, "word": 21, "talli": 21, "trackabl": 21, "12345678": 21, "87654321": 21, "numer": [21, 24, 28], "consid": [21, 27], "random": [21, 28], "rememb": [21, 28], "frequent": 21, "lowercas": 21, "letter": 21, "z": 21, "special": 21, "charact": [21, 24], "_": [21, 28], "equival": [21, 24, 28], "colon": 21, "user123": [21, 24], "simul": [21, 23, 24, 28], "stf123": 21, "datafeb": 21, "brows": [21, 24], "encod": [21, 28], "especi": [21, 24, 28], "scheme": 21, "findabl": 21, "interoper": 21, "minimum": 21, "against": [21, 28], "obliqu": 21, "insid": [21, 24, 28], "reloc": 21, "similarli": 21, "again": [21, 28], "progress": [21, 28], "monitor": [21, 24], "distinct": [21, 24], "javascript": 21, "notat": 21, "arbitrari": [21, 24], "languag": [21, 28], "overwritten": 21, "unchang": 21, "insert": 21, "fulli": 21, "ietf": 21, "html": [21, 24], "rfc8259": 21, "implicitli": 21, "Of": [21, 28], "newer": 21, "statement": 21, "xyz": 21, "pqr": 21, "itself": [21, 24, 27, 28, 30], "prohibit": 21, "agent": 21, "problem": [21, 28], "forget": [21, 28], "simpl": [21, 24, 28], "equal": 21, "phrase": 21, "column": 21, "md": 21, "markdown": 21, "ext": [21, 28], "unix": [21, 28], "child": [21, 28], "constraint": 21, "prefer": [21, 27, 28], "mix": 21, "hierarchi": [21, 24], "subdirectori": 21, "schedul": 21, "u_user123_root": 21, "proj123": 21, "p_proj123_root": 21, "its": [21, 24, 28], "discover": 21, "impli": [21, 28], "lock": 21, "temporarili": [21, 27, 28], "evalu": 21, "absenc": 21, "deni": [21, 28], "unaffili": 21, "therefor": [21, 27, 28, 30], "wish": [21, 30], "gain": 21, "manner": [21, 28], "matter": 21, "proxim": 21, "pattern": 21, "custom": [21, 28], "review": 21, "2020": [21, 22, 24], "With": [21, 28], "offici": [21, 28], "reus": 21, "facet": [21, 28], "autocomplet": [21, 24], "entri": 21, "widget": 21, "question": 21, "warn": 21, "deem": 21, "suitabl": 21, "opportun": 21, "assur": 21, "produc": [21, 24, 28], "unknown": [21, 27], "notifi": 21, "wildcard": 21, "doi": 21, "2019": [22, 24], "6th": 22, "annual": 22, "conf": 22, "intellig": 22, "csci": 22, "19": [22, 24, 28], "slide": 22, "smoki": 22, "mountain": 22, "confer": 22, "smc": 22, "video": [22, 23, 28, 29], "learn": [23, 28], "model": [23, 28], "measur": 23, "cover": [24, 28], "prerequisit": 24, "navig": [24, 28, 30], "asynch": 24, "verifi": [24, 28], "binari": [24, 27, 28], "dafaf": 24, "immedi": 24, "stop": 24, "preced": 24, "interleav": 24, "convent": 24, "easier": 24, "Or": 24, "posit": 24, "sensit": 24, "abbrevi": 24, "ambigu": [24, 28], "natur": [24, 28], "experi": 24, "12351468": 24, "11801571": 24, "demo": 24, "demonstr": [24, 28], "14022631": 24, "09": 24, "02": 24, "13": 24, "07": 24, "quicker": 24, "remain": 24, "reader": 24, "knew": [24, 28], "furthermor": [24, 28], "contextu": [24, 28], "major": [24, 30], "realiz": 24, "pair": 24, "realist": [24, 28], "expect": [24, 28], "length": 24, "14": [24, 28], "now": [24, 28], "record_from_nersc": 24, "nersc_md": 24, "31030353": 24, "cnm": [24, 28], "11": 24, "08": 24, "04": 24, "31027390": 24, "record_from_alcf": 24, "29426537": 24, "from_olcf": 24, "nersc_data": 24, "txt": 24, "31030394": 24, "05": 24, "our": [24, 28], "wherev": [24, 28], "elect": [24, 28], "proceed": 24, "henc": 24, "leav": [24, 28], "unset": 24, "proce": [24, 28], "reveal": [24, 28], "37": 24, "global": 24, "u2": 24, "elsewher": [24, 28], "10314975": 24, "cln_b_1_beline_0001": 24, "mb": 24, "57230a10": 24, "7ba2": 24, "11e7": 24, "8c3b": 24, "22000b9923ef": 24, "nanophas": 24, "h5": 24, "01": 24, "54": 24, "15": 24, "31": 24, "bash": 24, "hlt": 24, "28m": 24, "rw": 24, "nov": 24, "58": 24, "400k": 24, "36": 24, "translation_compil": 24, "9m": 24, "image_02": 24, "mat": 24, "41": 24, "26m": 24, "got": [24, 28], "heavi": [24, 28], "wast": [24, 28], "preciou": [24, 28], "wall": [24, 28], "nativ": 27, "miniconda": 27, "nearli": 27, "anyth": 27, "pip": 27, "mac": 27, "And": 27, "encount": [27, 28], "machine_nam": 27, "anaconda": [27, 28], "job": 27, "conda": 27, "endpoint_name_her": 27, "inspect": 27, "suit": [27, 28], "conclud": 27, "thereof": 27, "hostnam": 27, "behind": 27, "firewal": 27, "traffic": 27, "gov": [27, 28], "7512": 27, "tailor": 27, "config_dir": 27, "usr": 27, "default_endpoint": 27, "higher": 27, "come": 27, "varieti": [27, 30], "overridden": 27, "programmat": [27, 28], "datef": 27, "kept": 27, "incid": 27, "n": [27, 28], "datafed_server_cfg_fil": 27, "datafed_server_cfg_dir": 27, "public_key_fil": 27, "datafed_server_pub_key_fil": 27, "datafed_server_host": 27, "config_fil": 27, "datafed_client_cfg_fil": 27, "datafed_client_cfg_dir": 27, "datafed_client_pub_key_fil": 27, "private_key_fil": 27, "datafed_client_priv_key_fil": 27, "datafed_default_endpoint": 27, "incorrect": [27, 28], "librari": 28, "class": 28, "meant": 28, "exhaust": 28, "tutori": [28, 29], "comprehens": 28, "youtub": [28, 29], "deal": 28, "datetim": 28, "convers": 28, "final": 28, "df_api": 28, "try": 28, "plist_resp": 28, "abc123": 28, "breetju": 28, "sn": 28, "dv": 28, "bl": 28, "11a": 28, "stansberrydv": 28, "trn001": 28, "train": 28, "respond": 28, "comfort": 28, "dig": 28, "pl_resp": 28, "len": 28, "interpret": 28, "python_messag": 28, "quick": 28, "nomin": 28, "besid": 28, "main": 28, "past": [28, 29], "denot": 28, "won": 28, "might": 28, "forward": [28, 30], "remind": 28, "peel": 28, "jump": 28, "straight": 28, "henceforth": 28, "breviti": 28, "sai": 28, "proj": 28, "1610905375": 28, "1610912585": 28, "1073741824": 28, "data_s": 28, "rec_count": 28, "data10t": 28, "kind": 28, "nonetheless": 28, "peopl": 28, "life": 28, "profession": 28, "offer": 28, "mention": 28, "earlier": 28, "among": 28, "keyword": 28, "p_trn001_root": 28, "somewhat": 28, "fact": 28, "happen": 28, "u_somnaths_root": 28, "correct": 28, "everyth": 28, "ls_resp": 28, "34559341": 28, "34559108": 28, "projshar": 28, "34558900": 28, "34559268": 28, "Not": 28, "keep": 28, "mind": 28, "traceback": 28, "ipython": 28, "acb948617f34": 28, "lib": 28, "python3": 28, "py": 28, "self": 28, "_mapi": 28, "761": 28, "299": 28, "300": 28, "_timeout": 28, "els": 28, "301": 28, "mt": 28, "302": 28, "303": 28, "343": 28, "msg_type": 28, "_nack_except": 28, "344": 28, "err_msg": 28, "345": 28, "rais": 28, "346": 28, "347": 28, "err_cod": 28, "dbget": 28, "126": 28, "1610905632": 28, "1610905667": 28, "successfulli": 28, "narrow": 28, "unnecessari": 28, "carefulli": 28, "solut": [28, 29], "hopefulli": 28, "minim": 28, "naiv": 28, "accident": 28, "tediou": 28, "instanti": 28, "clutter": 28, "dest_collect": 28, "fake": 28, "real": 28, "123": 28, "someth": 28, "dump": 28, "turn": 28, "dc_resp": 28, "unspecifi": 28, "34682319": 28, "ext_auto": 28, "1611077217": 28, "crucial": 28, "piec": 28, "Such": 28, "obtain": 28, "record_id": 28, "du_resp": 28, "my_first_dataset": 28, "appended_metadata": 28, "1611077220": 28, "deps_avail": 28, "acknowledg": 28, "dv_resp": 28, "fromtimestamp": 28, "26": 28, "57": 28, "append": 28, "q": 28, "hello": 28, "went": 28, "clean": 28, "multi": 28, "dc2_resp": 28, "cleaning_algorithm": 28, "gaussian_blur": 28, "clean_rec_id": 28, "34682715": 28, "wherein": 28, "dep_resp": 28, "1611077405": 28, "1611078386": 28, "newli": 28, "facilit": 28, "shot": 28, "colloqui": 28, "sake": 28, "file_handl": 28, "put_resp": 28, "34702491": 28, "finish": 28, "1611102437": 28, "1611102444": 28, "gpf": 28, "alpin": 28, "stf011": 28, "scratch": 28, "datafed_tutori": 28, "dest": 28, "ot": 28, "behavior": 28, "usecas": 28, "86": 28, "1611077286": 28, "dt": 28, "compar": 28, "clash": 28, "prove": 28, "whose": 28, "expected_file_nam": 28, "join": 28, "split": 28, "bug": 28, "singular": 28, "get_resp": 28, "34682556": 28, "1611077310": 28, "1611077320": 28, "renam": 28, "whatev": 28, "duplicate_paramet": 28, "task_resp": 28, "had": 28, "deliv": 28, "thousand": 28, "spread": 28, "world": 28, "contin": 28, "composit": 28, "mark": 28, "properti": 28, "exact": 28, "nomenclatur": 28, "evolv": 28, "certainli": 28, "perhap": 28, "ideal": 28, "conceiv": 28, "launch": 28, "took": 28, "computation": 28, "expens": 28, "expensive_simul": 28, "sleep": 28, "written": 28, "dat": 28, "comic": 28, "oversimplifi": 28, "accur": 28, "ye": 28, "determinist": 28, "path_to_result": 28, "esnet": 28, "cern": 28, "diskpt1": 28, "data1": 28, "5mb": 28, "tini": 28, "1kb": 28, "check_xfer_statu": 28, "instantan": 28, "status": 28, "hold": [28, 30], "this_task_id": 28, "mimic": 28, "coll_resp": 28, "sim_coll_id": 28, "imped": 28, "importantli": 28, "supercomput": 28, "xfer_task": 28, "ind": 28, "results_fil": 28, "rec_resp": 28, "simulation_": 28, "parameter_1": 28, "this_rec_id": 28, "cours": 28, "compet": 28, "vari": 28, "workload": 28, "great": 28, "vast": 28, "coll_alia": 28, "cat_dog_train": 28, "imag": 28, "classif": 28, "34683877": 28, "1611078472": 28, "ahead": 28, "gather": 28, "cat": 28, "dog": 28, "simplic": 28, "distinguish": 28, "anim": 28, "generate_animal_data": 28, "is_dog": 28, "this_anim": 28, "randint": 28, "100": 28, "teas": 28, "raw_data_path": 28, "newi": 28, "littl": 28, "realli": 28, "cat_record": 28, "dog_record": 28, "34684011": 28, "34684035": 28, "34684059": 28, "34684083": 28, "34684107": 28, "34683891": 28, "34683915": 28, "34683939": 28, "34683963": 28, "34683987": 28, "collectionitemlist": 28, "coll_list_resp": 28, "cat_22": 28, "cat_32": 28, "cat_6": 28, "cat_93": 28, "cat_96": 28, "dog_3": 28, "dog_63": 28, "dog_70": 28, "dog_71": 28, "dog_8": 28, "dozen": 28, "hundr": 28, "segreg": 28, "enumer": 28, "meaning": 28, "obvious": 28, "optim": 28, "technic": 28, "soon": 28, "screenshot": 28, "bottom": [28, 30], "uncheck": 28, "checkbox": 28, "yellow": 28, "taken": 28, "floppi": 28, "pop": 28, "give": 28, "find_all_cat": 28, "ql_resp": 28, "34684970": 28, "1611078781": 28, "query_resp": 28, "50": 28, "cat_rec_id": 28, "simplest": 28, "cat_coll_id": 28, "34685092": 28, "idea": 28, "path_resp": 28, "cup_resp": 28, "obj": 28, "outer": 28, "de": 28, "collectionsitemsupd": 28, "suboptim": 28, "accomplish": 28, "fortun": 28, "entir": [28, 30], "cat_data": 28, "34685359": 28, "pend": 28, "1611079028": 28, "recal": 28, "arbitrarili": 28, "listdir": 28, "popularli": 28, "correspond": 29, "verif": 29, "rapid": 30, "pace": 30, "element": 30, "keyboard": 30, "whereupon": 30, "receiv": 30, "shift": 30, "held": 30, "thr": 30, "collaps": 30, "write_meta": 30, "read_data": 30, "write_data": 30, "ui": 30, "mail": 30, "whenev": 30, "amd": 30}, "objects": {"": [[12, 0, 0, "-", "datafed"]], "datafed": [[2, 0, 0, "-", "CLI"], [3, 0, 0, "-", "CommandLib"], [4, 0, 0, "-", "Config"], [5, 0, 0, "-", "Connection"], [6, 0, 0, "-", "MessageLib"], [7, 0, 0, "-", "SDMS_Anon_pb2"], [8, 0, 0, "-", "SDMS_Auth_pb2"], [9, 0, 0, "-", "SDMS_pb2"], [10, 0, 0, "-", "VERSION"], [11, 0, 0, "-", "Version_pb2"], [12, 4, 1, "", "name"], [12, 4, 1, "", "version"]], "datafed.CLI": [[2, 1, 1, "", "_AliasedGroup"], [2, 1, 1, "", "_AliasedGroupRoot"], [2, 3, 1, "", "_NoCommand"], [2, 4, 1, "", "_OM_JSON"], [2, 4, 1, "", "_OM_RETN"], [2, 4, 1, "", "_OM_TEXT"], [2, 4, 1, "", "_STAT_ERROR"], [2, 4, 1, "", "_STAT_OK"], [2, 4, 1, "", "__global_context_options"], [2, 4, 1, "", "__global_output_options"], [2, 5, 1, "", "_addConfigOptions"], [2, 5, 1, "", "_arrayToCSV"], [2, 5, 1, "", "_arrayToDotted"], [2, 5, 1, "", "_bar_adaptive_human_readable"], [2, 5, 1, "", "_batch"], [2, 4, 1, "", "_capi"], [2, 5, 1, "", "_cli"], [2, 5, 1, "", "_coll"], [2, 5, 1, "", "_collCreate"], [2, 5, 1, "", "_collDelete"], [2, 5, 1, "", "_collItemsAdd"], [2, 5, 1, "", "_collUpdate"], [2, 5, 1, "", "_collView"], [2, 5, 1, "", "_coll_rem"], [2, 4, 1, "", "_ctxt_settings"], [2, 4, 1, "", "_cur_alias_prefix"], [2, 4, 1, "", "_cur_coll"], [2, 4, 1, "", "_cur_coll_prefix"], [2, 4, 1, "", "_cur_coll_title"], [2, 4, 1, "", "_cur_ctx"], [2, 5, 1, "", "_data"], [2, 5, 1, "", "_dataCreate"], [2, 5, 1, "", "_dataDelete"], [2, 5, 1, "", "_dataGet"], [2, 5, 1, "", "_dataPut"], [2, 5, 1, "", "_dataUpdate"], [2, 5, 1, "", "_dataView"], [2, 5, 1, "", "_data_batch_create"], [2, 5, 1, "", "_data_batch_update"], [2, 4, 1, "", "_devnull"], [2, 5, 1, "", "_ep"], [2, 5, 1, "", "_epDefault"], [2, 5, 1, "", "_epDefaultGet"], [2, 5, 1, "", "_epDefaultSet"], [2, 5, 1, "", "_epGet"], [2, 5, 1, "", "_epList"], [2, 5, 1, "", "_epSet"], [2, 5, 1, "", "_exit_cli"], [2, 5, 1, "", "_genDoc"], [2, 5, 1, "", "_genDocCmd"], [2, 5, 1, "", "_genDocHeader"], [2, 5, 1, "", "_generic_reply_handler"], [2, 5, 1, "", "_global_context_options"], [2, 5, 1, "", "_global_output_options"], [2, 4, 1, "", "_hdr_lev_char"], [2, 5, 1, "", "_help_cli"], [2, 5, 1, "", "_initialize"], [2, 4, 1, "", "_initialized"], [2, 4, 1, "", "_interactive"], [2, 5, 1, "", "_list"], [2, 4, 1, "", "_list_items"], [2, 4, 1, "", "_output_mode"], [2, 4, 1, "", "_output_mode_sticky"], [2, 4, 1, "", "_prev_coll"], [2, 4, 1, "", "_prev_ctx"], [2, 5, 1, "", "_printJSON"], [2, 5, 1, "", "_printJSON_List"], [2, 5, 1, "", "_print_ack_reply"], [2, 5, 1, "", "_print_batch"], [2, 5, 1, "", "_print_coll"], [2, 5, 1, "", "_print_data"], [2, 5, 1, "", "_print_deps"], [2, 5, 1, "", "_print_endpoints"], [2, 5, 1, "", "_print_listing"], [2, 5, 1, "", "_print_msg"], [2, 5, 1, "", "_print_path"], [2, 5, 1, "", "_print_proj"], [2, 5, 1, "", "_print_proj_listing"], [2, 5, 1, "", "_print_query"], [2, 5, 1, "", "_print_task"], [2, 5, 1, "", "_print_task_array"], [2, 5, 1, "", "_print_task_listing"], [2, 5, 1, "", "_print_user"], [2, 5, 1, "", "_print_user_listing"], [2, 5, 1, "", "_project"], [2, 5, 1, "", "_projectList"], [2, 5, 1, "", "_projectView"], [2, 5, 1, "", "_query"], [2, 5, 1, "", "_queryCreate"], [2, 5, 1, "", "_queryDelete"], [2, 5, 1, "", "_queryExec"], [2, 5, 1, "", "_queryList"], [2, 5, 1, "", "_queryRun"], [2, 5, 1, "", "_queryUpdate"], [2, 5, 1, "", "_queryView"], [2, 5, 1, "", "_resolve_coll_id"], [2, 5, 1, "", "_resolve_id"], [2, 4, 1, "", "_return_val"], [2, 5, 1, "", "_setWorkingCollectionTitle"], [2, 5, 1, "", "_set_script_cb"], [2, 5, 1, "", "_set_verbosity_cb"], [2, 5, 1, "", "_setup"], [2, 5, 1, "", "_shares"], [2, 5, 1, "", "_task"], [2, 5, 1, "", "_taskList"], [2, 5, 1, "", "_taskView"], [2, 4, 1, "", "_task_statuses"], [2, 4, 1, "", "_task_types"], [2, 4, 1, "", "_uid"], [2, 5, 1, "", "_user"], [2, 5, 1, "", "_userListAll"], [2, 5, 1, "", "_userListCollab"], [2, 5, 1, "", "_userView"], [2, 5, 1, "", "_userWho"], [2, 4, 1, "", "_verbosity"], [2, 5, 1, "", "_verbositySet"], [2, 4, 1, "", "_verbosity_sticky"], [2, 5, 1, "", "_wc"], [2, 5, 1, "", "_wp"], [2, 5, 1, "", "_wrap_text"], [2, 5, 1, "", "command"], [2, 5, 1, "", "init"], [2, 5, 1, "", "loginByPassword"], [2, 5, 1, "", "loginByToken"], [2, 5, 1, "", "run"]], "datafed.CLI._AliasedGroup": [[2, 2, 1, "", "get_command"], [2, 2, 1, "", "resolve_command"]], "datafed.CLI._AliasedGroupRoot": [[2, 2, 1, "", "get_command"]], "datafed.CommandLib": [[3, 1, 1, "", "API"]], "datafed.CommandLib.API": [[3, 2, 1, "", "_buildSearchRequest"], [3, 6, 1, "", "_endpoint_legacy"], [3, 6, 1, "", "_endpoint_uuid"], [3, 6, 1, "", "_max_md_size"], [3, 6, 1, "", "_max_payload_size"], [3, 2, 1, "", "_resolvePathForGlobus"], [3, 2, 1, "", "_resolvePathForHTTP"], [3, 2, 1, "", "_resolve_id"], [3, 2, 1, "", "_setSaneDefaultOptions"], [3, 2, 1, "", "_uniquifyFilename"], [3, 2, 1, "", "collectionCreate"], [3, 2, 1, "", "collectionDelete"], [3, 2, 1, "", "collectionGetParents"], [3, 2, 1, "", "collectionItemsList"], [3, 2, 1, "", "collectionItemsUpdate"], [3, 2, 1, "", "collectionUpdate"], [3, 2, 1, "", "collectionView"], [3, 2, 1, "", "dataBatchCreate"], [3, 2, 1, "", "dataBatchUpdate"], [3, 2, 1, "", "dataCreate"], [3, 2, 1, "", "dataDelete"], [3, 2, 1, "", "dataGet"], [3, 2, 1, "", "dataPut"], [3, 2, 1, "", "dataUpdate"], [3, 2, 1, "", "dataView"], [3, 2, 1, "", "endpointDefaultGet"], [3, 2, 1, "", "endpointDefaultSet"], [3, 2, 1, "", "endpointGet"], [3, 2, 1, "", "endpointListRecent"], [3, 2, 1, "", "endpointSet"], [3, 2, 1, "", "generateCredentials"], [3, 2, 1, "", "getAuthUser"], [3, 2, 1, "", "getContext"], [3, 2, 1, "", "loginByPassword"], [3, 2, 1, "", "logout"], [3, 2, 1, "", "projectGetRole"], [3, 2, 1, "", "projectList"], [3, 2, 1, "", "projectView"], [3, 2, 1, "", "queryCreate"], [3, 2, 1, "", "queryDelete"], [3, 2, 1, "", "queryDirect"], [3, 2, 1, "", "queryExec"], [3, 2, 1, "", "queryList"], [3, 2, 1, "", "queryUpdate"], [3, 2, 1, "", "queryView"], [3, 2, 1, "", "repoAllocationCreate"], [3, 2, 1, "", "repoAllocationDelete"], [3, 2, 1, "", "repoCreate"], [3, 2, 1, "", "repoDelete"], [3, 2, 1, "", "repoList"], [3, 2, 1, "", "repoListAllocations"], [3, 2, 1, "", "setContext"], [3, 2, 1, "", "setupCredentials"], [3, 2, 1, "", "sharedList"], [3, 2, 1, "", "sharedListItems"], [3, 2, 1, "", "sizeToStr"], [3, 2, 1, "", "strToTimestamp"], [3, 2, 1, "", "taskList"], [3, 2, 1, "", "taskView"], [3, 2, 1, "", "timestampToStr"], [3, 2, 1, "", "userListAll"], [3, 2, 1, "", "userListCollaborators"], [3, 2, 1, "", "userView"]], "datafed.Config": [[4, 1, 1, "", "API"], [4, 4, 1, "", "_OPT_BOOL"], [4, 4, 1, "", "_OPT_EAGER"], [4, 4, 1, "", "_OPT_HIDE"], [4, 4, 1, "", "_OPT_INT"], [4, 4, 1, "", "_OPT_NO_CF"], [4, 4, 1, "", "_OPT_NO_CL"], [4, 4, 1, "", "_OPT_NO_ENV"], [4, 4, 1, "", "_OPT_PATH"], [4, 4, 1, "", "_opt_info"]], "datafed.Config.API": [[4, 2, 1, "", "_loadConfigFile"], [4, 2, 1, "", "_loadEnvironVars"], [4, 2, 1, "", "_processOptions"], [4, 2, 1, "", "get"], [4, 2, 1, "", "getOpts"], [4, 2, 1, "", "printSettingInfo"], [4, 2, 1, "", "save"], [4, 2, 1, "", "set"]], "datafed.Connection": [[5, 1, 1, "", "Connection"]], "datafed.Connection.Connection": [[5, 2, 1, "", "__del__"], [5, 2, 1, "", "makeMessage"], [5, 2, 1, "", "recv"], [5, 2, 1, "", "registerProtocol"], [5, 2, 1, "", "reset"], [5, 2, 1, "", "send"]], "datafed.MessageLib": [[6, 1, 1, "", "API"], [6, 5, 1, "", "get_latest_version"]], "datafed.MessageLib.API": [[6, 2, 1, "", "getAuthStatus"], [6, 2, 1, "", "getDailyMessage"], [6, 2, 1, "", "getDefaultTimeout"], [6, 2, 1, "", "getNackExceptionEnabled"], [6, 2, 1, "", "keysLoaded"], [6, 2, 1, "", "keysValid"], [6, 2, 1, "", "logout"], [6, 2, 1, "", "manualAuthByPassword"], [6, 2, 1, "", "manualAuthByToken"], [6, 2, 1, "", "recv"], [6, 2, 1, "", "send"], [6, 2, 1, "", "sendRecv"], [6, 2, 1, "", "setDefaultTimeout"], [6, 2, 1, "", "setNackExceptionEnabled"]], "datafed.SDMS_Anon_pb2": [[7, 4, 1, "", "AckReply"], [7, 4, 1, "", "AuthStatusReply"], [7, 4, 1, "", "AuthenticateByPasswordRequest"], [7, 4, 1, "", "AuthenticateByTokenRequest"], [7, 4, 1, "", "DESCRIPTOR"], [7, 4, 1, "", "DailyMessageReply"], [7, 4, 1, "", "DailyMessageRequest"], [7, 4, 1, "", "GetAuthStatusRequest"], [7, 4, 1, "", "ID"], [7, 4, 1, "", "NackReply"], [7, 4, 1, "", "Protocol"], [7, 4, 1, "", "VersionReply"], [7, 4, 1, "", "VersionRequest"], [7, 4, 1, "", "_ACKREPLY"], [7, 4, 1, "", "_AUTHENTICATEBYPASSWORDREQUEST"], [7, 4, 1, "", "_AUTHENTICATEBYTOKENREQUEST"], [7, 4, 1, "", "_AUTHSTATUSREPLY"], [7, 4, 1, "", "_DAILYMESSAGEREPLY"], [7, 4, 1, "", "_DAILYMESSAGEREQUEST"], [7, 4, 1, "", "_GETAUTHSTATUSREQUEST"], [7, 4, 1, "", "_NACKREPLY"], [7, 4, 1, "", "_PROTOCOL"], [7, 4, 1, "", "_VERSIONREPLY"], [7, 4, 1, "", "_VERSIONREQUEST"], [7, 4, 1, "id30", "_msg_name_to_type"], [7, 4, 1, "id31", "_msg_type_to_name"], [7, 4, 1, "", "_sym_db"]], "datafed.SDMS_Auth_pb2": [[8, 4, 1, "", "ACLDataReply"], [8, 4, 1, "", "ACLSharedListItemsRequest"], [8, 4, 1, "", "ACLSharedListRequest"], [8, 4, 1, "", "ACLUpdateRequest"], [8, 4, 1, "", "ACLViewRequest"], [8, 4, 1, "", "CheckPermsReply"], [8, 4, 1, "", "CheckPermsRequest"], [8, 4, 1, "", "CollCreateRequest"], [8, 4, 1, "", "CollDataReply"], [8, 4, 1, "", "CollDeleteRequest"], [8, 4, 1, "", "CollGetOffsetReply"], [8, 4, 1, "", "CollGetOffsetRequest"], [8, 4, 1, "", "CollGetParentsRequest"], [8, 4, 1, "", "CollListPublishedRequest"], [8, 4, 1, "", "CollMoveRequest"], [8, 4, 1, "", "CollPathReply"], [8, 4, 1, "", "CollReadRequest"], [8, 4, 1, "", "CollUpdateRequest"], [8, 4, 1, "", "CollViewRequest"], [8, 4, 1, "", "CollWriteRequest"], [8, 4, 1, "", "DESCRIPTOR"], [8, 4, 1, "", "DataDeleteRequest"], [8, 4, 1, "", "DataGetReply"], [8, 4, 1, "", "DataGetRequest"], [8, 4, 1, "", "DataPathReply"], [8, 4, 1, "", "DataPathRequest"], [8, 4, 1, "", "DataPutReply"], [8, 4, 1, "", "DataPutRequest"], [8, 4, 1, "", "GenerateCredentialsReply"], [8, 4, 1, "", "GenerateCredentialsRequest"], [8, 4, 1, "", "GetPermsReply"], [8, 4, 1, "", "GetPermsRequest"], [8, 4, 1, "", "GroupCreateRequest"], [8, 4, 1, "", "GroupDataReply"], [8, 4, 1, "", "GroupDeleteRequest"], [8, 4, 1, "", "GroupListRequest"], [8, 4, 1, "", "GroupUpdateRequest"], [8, 4, 1, "", "GroupViewRequest"], [8, 4, 1, "", "ID"], [8, 4, 1, "", "ListingReply"], [8, 4, 1, "", "MetadataValidateReply"], [8, 4, 1, "", "MetadataValidateRequest"], [8, 4, 1, "", "NoteCommentEditRequest"], [8, 4, 1, "", "NoteCreateRequest"], [8, 4, 1, "", "NoteDataReply"], [8, 4, 1, "", "NoteListBySubjectRequest"], [8, 4, 1, "", "NoteUpdateRequest"], [8, 4, 1, "", "NoteViewRequest"], [8, 4, 1, "", "ProjectCreateRequest"], [8, 4, 1, "", "ProjectDataReply"], [8, 4, 1, "", "ProjectDeleteRequest"], [8, 4, 1, "", "ProjectGetRoleReply"], [8, 4, 1, "", "ProjectGetRoleRequest"], [8, 4, 1, "", "ProjectListRequest"], [8, 4, 1, "", "ProjectSearchRequest"], [8, 4, 1, "", "ProjectUpdateRequest"], [8, 4, 1, "", "ProjectViewRequest"], [8, 4, 1, "", "Protocol"], [8, 4, 1, "", "QueryCreateRequest"], [8, 4, 1, "", "QueryDataReply"], [8, 4, 1, "", "QueryDeleteRequest"], [8, 4, 1, "", "QueryExecRequest"], [8, 4, 1, "", "QueryListRequest"], [8, 4, 1, "", "QueryUpdateRequest"], [8, 4, 1, "", "QueryViewRequest"], [8, 4, 1, "", "RecordAllocChangeReply"], [8, 4, 1, "", "RecordAllocChangeRequest"], [8, 4, 1, "", "RecordCreateBatchRequest"], [8, 4, 1, "", "RecordCreateRequest"], [8, 4, 1, "", "RecordDataReply"], [8, 4, 1, "", "RecordDeleteRequest"], [8, 4, 1, "", "RecordExportReply"], [8, 4, 1, "", "RecordExportRequest"], [8, 4, 1, "", "RecordGetDependencyGraphRequest"], [8, 4, 1, "", "RecordListByAllocRequest"], [8, 4, 1, "", "RecordLockRequest"], [8, 4, 1, "", "RecordOwnerChangeReply"], [8, 4, 1, "", "RecordOwnerChangeRequest"], [8, 4, 1, "", "RecordUpdateBatchRequest"], [8, 4, 1, "", "RecordUpdateRequest"], [8, 4, 1, "", "RecordViewRequest"], [8, 4, 1, "", "RepoAllocationCreateRequest"], [8, 4, 1, "", "RepoAllocationDeleteRequest"], [8, 4, 1, "", "RepoAllocationSetDefaultRequest"], [8, 4, 1, "", "RepoAllocationSetRequest"], [8, 4, 1, "", "RepoAllocationStatsReply"], [8, 4, 1, "", "RepoAllocationStatsRequest"], [8, 4, 1, "", "RepoAllocationsReply"], [8, 4, 1, "", "RepoAuthzRequest"], [8, 4, 1, "", "RepoCalcSizeReply"], [8, 4, 1, "", "RepoCalcSizeRequest"], [8, 4, 1, "", "RepoCreateRequest"], [8, 4, 1, "", "RepoDataDeleteRequest"], [8, 4, 1, "", "RepoDataGetSizeRequest"], [8, 4, 1, "", "RepoDataReply"], [8, 4, 1, "", "RepoDataSizeReply"], [8, 4, 1, "", "RepoDeleteRequest"], [8, 4, 1, "", "RepoListAllocationsRequest"], [8, 4, 1, "", "RepoListObjectAllocationsRequest"], [8, 4, 1, "", "RepoListRequest"], [8, 4, 1, "", "RepoListSubjectAllocationsRequest"], [8, 4, 1, "", "RepoPathCreateRequest"], [8, 4, 1, "", "RepoPathDeleteRequest"], [8, 4, 1, "", "RepoUpdateRequest"], [8, 4, 1, "", "RepoViewAllocationRequest"], [8, 4, 1, "", "RepoViewRequest"], [8, 4, 1, "", "RevokeCredentialsRequest"], [8, 4, 1, "", "SchemaCreateRequest"], [8, 4, 1, "", "SchemaDataReply"], [8, 4, 1, "", "SchemaDeleteRequest"], [8, 4, 1, "", "SchemaReviseRequest"], [8, 4, 1, "", "SchemaSearchRequest"], [8, 4, 1, "", "SchemaUpdateRequest"], [8, 4, 1, "", "SchemaViewRequest"], [8, 4, 1, "", "SearchRequest"], [8, 4, 1, "", "TagDataReply"], [8, 4, 1, "", "TagListByCountRequest"], [8, 4, 1, "", "TagSearchRequest"], [8, 4, 1, "", "TaskDataReply"], [8, 4, 1, "", "TaskListRequest"], [8, 4, 1, "", "TaskViewRequest"], [8, 4, 1, "", "TopicDataReply"], [8, 4, 1, "", "TopicListTopicsRequest"], [8, 4, 1, "", "TopicSearchRequest"], [8, 4, 1, "", "TopicViewRequest"], [8, 4, 1, "", "UserAccessTokenReply"], [8, 4, 1, "", "UserCreateRequest"], [8, 4, 1, "", "UserDataReply"], [8, 4, 1, "", "UserFindByNameUIDRequest"], [8, 4, 1, "", "UserFindByUUIDsRequest"], [8, 4, 1, "", "UserGetAccessTokenRequest"], [8, 4, 1, "", "UserGetRecentEPReply"], [8, 4, 1, "", "UserGetRecentEPRequest"], [8, 4, 1, "", "UserListAllRequest"], [8, 4, 1, "", "UserListCollabRequest"], [8, 4, 1, "", "UserSetAccessTokenRequest"], [8, 4, 1, "", "UserSetRecentEPRequest"], [8, 4, 1, "", "UserUpdateRequest"], [8, 4, 1, "", "UserViewRequest"], [8, 4, 1, "", "_ACLDATAREPLY"], [8, 4, 1, "", "_ACLSHAREDLISTITEMSREQUEST"], [8, 4, 1, "", "_ACLSHAREDLISTREQUEST"], [8, 4, 1, "", "_ACLUPDATEREQUEST"], [8, 4, 1, "", "_ACLVIEWREQUEST"], [8, 4, 1, "", "_CHECKPERMSREPLY"], [8, 4, 1, "", "_CHECKPERMSREQUEST"], [8, 4, 1, "", "_COLLCREATEREQUEST"], [8, 4, 1, "", "_COLLDATAREPLY"], [8, 4, 1, "", "_COLLDELETEREQUEST"], [8, 4, 1, "", "_COLLGETOFFSETREPLY"], [8, 4, 1, "", "_COLLGETOFFSETREQUEST"], [8, 4, 1, "", "_COLLGETPARENTSREQUEST"], [8, 4, 1, "", "_COLLLISTPUBLISHEDREQUEST"], [8, 4, 1, "", "_COLLMOVEREQUEST"], [8, 4, 1, "", "_COLLPATHREPLY"], [8, 4, 1, "", "_COLLREADREQUEST"], [8, 4, 1, "", "_COLLUPDATEREQUEST"], [8, 4, 1, "", "_COLLVIEWREQUEST"], [8, 4, 1, "", "_COLLWRITEREQUEST"], [8, 4, 1, "", "_DATADELETEREQUEST"], [8, 4, 1, "", "_DATAGETREPLY"], [8, 4, 1, "", "_DATAGETREQUEST"], [8, 4, 1, "", "_DATAPATHREPLY"], [8, 4, 1, "", "_DATAPATHREQUEST"], [8, 4, 1, "", "_DATAPUTREPLY"], [8, 4, 1, "", "_DATAPUTREQUEST"], [8, 4, 1, "", "_GENERATECREDENTIALSREPLY"], [8, 4, 1, "", "_GENERATECREDENTIALSREQUEST"], [8, 4, 1, "", "_GETPERMSREPLY"], [8, 4, 1, "", "_GETPERMSREQUEST"], [8, 4, 1, "", "_GROUPCREATEREQUEST"], [8, 4, 1, "", "_GROUPDATAREPLY"], [8, 4, 1, "", "_GROUPDELETEREQUEST"], [8, 4, 1, "", "_GROUPLISTREQUEST"], [8, 4, 1, "", "_GROUPUPDATEREQUEST"], [8, 4, 1, "", "_GROUPVIEWREQUEST"], [8, 4, 1, "", "_LISTINGREPLY"], [8, 4, 1, "", "_METADATAVALIDATEREPLY"], [8, 4, 1, "", "_METADATAVALIDATEREQUEST"], [8, 4, 1, "", "_NOTECOMMENTEDITREQUEST"], [8, 4, 1, "", "_NOTECREATEREQUEST"], [8, 4, 1, "", "_NOTEDATAREPLY"], [8, 4, 1, "", "_NOTELISTBYSUBJECTREQUEST"], [8, 4, 1, "", "_NOTEUPDATEREQUEST"], [8, 4, 1, "", "_NOTEVIEWREQUEST"], [8, 4, 1, "", "_PROJECTCREATEREQUEST"], [8, 4, 1, "", "_PROJECTDATAREPLY"], [8, 4, 1, "", "_PROJECTDELETEREQUEST"], [8, 4, 1, "", "_PROJECTGETROLEREPLY"], [8, 4, 1, "", "_PROJECTGETROLEREQUEST"], [8, 4, 1, "", "_PROJECTLISTREQUEST"], [8, 4, 1, "", "_PROJECTSEARCHREQUEST"], [8, 4, 1, "", "_PROJECTUPDATEREQUEST"], [8, 4, 1, "", "_PROJECTVIEWREQUEST"], [8, 4, 1, "", "_PROTOCOL"], [8, 4, 1, "", "_QUERYCREATEREQUEST"], [8, 4, 1, "", "_QUERYDATAREPLY"], [8, 4, 1, "", "_QUERYDELETEREQUEST"], [8, 4, 1, "", "_QUERYEXECREQUEST"], [8, 4, 1, "", "_QUERYLISTREQUEST"], [8, 4, 1, "", "_QUERYUPDATEREQUEST"], [8, 4, 1, "", "_QUERYVIEWREQUEST"], [8, 4, 1, "", "_RECORDALLOCCHANGEREPLY"], [8, 4, 1, "", "_RECORDALLOCCHANGEREQUEST"], [8, 4, 1, "", "_RECORDCREATEBATCHREQUEST"], [8, 4, 1, "", "_RECORDCREATEREQUEST"], [8, 4, 1, "", "_RECORDDATAREPLY"], [8, 4, 1, "", "_RECORDDELETEREQUEST"], [8, 4, 1, "", "_RECORDEXPORTREPLY"], [8, 4, 1, "", "_RECORDEXPORTREQUEST"], [8, 4, 1, "", "_RECORDGETDEPENDENCYGRAPHREQUEST"], [8, 4, 1, "", "_RECORDLISTBYALLOCREQUEST"], [8, 4, 1, "", "_RECORDLOCKREQUEST"], [8, 4, 1, "", "_RECORDOWNERCHANGEREPLY"], [8, 4, 1, "", "_RECORDOWNERCHANGEREQUEST"], [8, 4, 1, "", "_RECORDUPDATEBATCHREQUEST"], [8, 4, 1, "", "_RECORDUPDATEREQUEST"], [8, 4, 1, "", "_RECORDVIEWREQUEST"], [8, 4, 1, "", "_REPOALLOCATIONCREATEREQUEST"], [8, 4, 1, "", "_REPOALLOCATIONDELETEREQUEST"], [8, 4, 1, "", "_REPOALLOCATIONSETDEFAULTREQUEST"], [8, 4, 1, "", "_REPOALLOCATIONSETREQUEST"], [8, 4, 1, "", "_REPOALLOCATIONSREPLY"], [8, 4, 1, "", "_REPOALLOCATIONSTATSREPLY"], [8, 4, 1, "", "_REPOALLOCATIONSTATSREQUEST"], [8, 4, 1, "", "_REPOAUTHZREQUEST"], [8, 4, 1, "", "_REPOCALCSIZEREPLY"], [8, 4, 1, "", "_REPOCALCSIZEREQUEST"], [8, 4, 1, "", "_REPOCREATEREQUEST"], [8, 4, 1, "", "_REPODATADELETEREQUEST"], [8, 4, 1, "", "_REPODATAGETSIZEREQUEST"], [8, 4, 1, "", "_REPODATAREPLY"], [8, 4, 1, "", "_REPODATASIZEREPLY"], [8, 4, 1, "", "_REPODELETEREQUEST"], [8, 4, 1, "", "_REPOLISTALLOCATIONSREQUEST"], [8, 4, 1, "", "_REPOLISTOBJECTALLOCATIONSREQUEST"], [8, 4, 1, "", "_REPOLISTREQUEST"], [8, 4, 1, "", "_REPOLISTSUBJECTALLOCATIONSREQUEST"], [8, 4, 1, "", "_REPOPATHCREATEREQUEST"], [8, 4, 1, "", "_REPOPATHDELETEREQUEST"], [8, 4, 1, "", "_REPOUPDATEREQUEST"], [8, 4, 1, "", "_REPOVIEWALLOCATIONREQUEST"], [8, 4, 1, "", "_REPOVIEWREQUEST"], [8, 4, 1, "", "_REVOKECREDENTIALSREQUEST"], [8, 4, 1, "", "_SCHEMACREATEREQUEST"], [8, 4, 1, "", "_SCHEMADATAREPLY"], [8, 4, 1, "", "_SCHEMADELETEREQUEST"], [8, 4, 1, "", "_SCHEMAREVISEREQUEST"], [8, 4, 1, "", "_SCHEMASEARCHREQUEST"], [8, 4, 1, "", "_SCHEMAUPDATEREQUEST"], [8, 4, 1, "", "_SCHEMAVIEWREQUEST"], [8, 4, 1, "", "_SEARCHREQUEST"], [8, 4, 1, "", "_TAGDATAREPLY"], [8, 4, 1, "", "_TAGLISTBYCOUNTREQUEST"], [8, 4, 1, "", "_TAGSEARCHREQUEST"], [8, 4, 1, "", "_TASKDATAREPLY"], [8, 4, 1, "", "_TASKLISTREQUEST"], [8, 4, 1, "", "_TASKVIEWREQUEST"], [8, 4, 1, "", "_TOPICDATAREPLY"], [8, 4, 1, "", "_TOPICLISTTOPICSREQUEST"], [8, 4, 1, "", "_TOPICSEARCHREQUEST"], [8, 4, 1, "", "_TOPICVIEWREQUEST"], [8, 4, 1, "", "_USERACCESSTOKENREPLY"], [8, 4, 1, "", "_USERCREATEREQUEST"], [8, 4, 1, "", "_USERDATAREPLY"], [8, 4, 1, "", "_USERFINDBYNAMEUIDREQUEST"], [8, 4, 1, "", "_USERFINDBYUUIDSREQUEST"], [8, 4, 1, "", "_USERGETACCESSTOKENREQUEST"], [8, 4, 1, "", "_USERGETRECENTEPREPLY"], [8, 4, 1, "", "_USERGETRECENTEPREQUEST"], [8, 4, 1, "", "_USERLISTALLREQUEST"], [8, 4, 1, "", "_USERLISTCOLLABREQUEST"], [8, 4, 1, "", "_USERSETACCESSTOKENREQUEST"], [8, 4, 1, "", "_USERSETRECENTEPREQUEST"], [8, 4, 1, "", "_USERUPDATEREQUEST"], [8, 4, 1, "", "_USERVIEWREQUEST"], [8, 4, 1, "id30", "_msg_name_to_type"], [8, 4, 1, "id31", "_msg_type_to_name"], [8, 4, 1, "", "_sym_db"]], "datafed.SDMS_pb2": [[9, 4, 1, "", "ACLRule"], [9, 4, 1, "", "AllocData"], [9, 4, 1, "", "AllocStatsData"], [9, 4, 1, "", "CollData"], [9, 4, 1, "", "DEP_IN"], [9, 4, 1, "", "DEP_IS_COMPONENT_OF"], [9, 4, 1, "", "DEP_IS_DERIVED_FROM"], [9, 4, 1, "", "DEP_IS_NEW_VERSION_OF"], [9, 4, 1, "", "DEP_OUT"], [9, 4, 1, "", "DEP_TYPE_COUNT"], [9, 4, 1, "", "DESCRIPTOR"], [9, 4, 1, "", "DependencyData"], [9, 4, 1, "", "DependencyDir"], [9, 4, 1, "", "DependencySpecData"], [9, 4, 1, "", "DependencyType"], [9, 4, 1, "", "ENCRYPT_AVAIL"], [9, 4, 1, "", "ENCRYPT_FORCE"], [9, 4, 1, "", "ENCRYPT_NONE"], [9, 4, 1, "", "Encryption"], [9, 4, 1, "", "ErrorCode"], [9, 4, 1, "", "GroupData"], [9, 4, 1, "", "ID_AUTHN_ERROR"], [9, 4, 1, "", "ID_AUTHN_REQUIRED"], [9, 4, 1, "", "ID_BAD_REQUEST"], [9, 4, 1, "", "ID_CLIENT_ERROR"], [9, 4, 1, "", "ID_DEST_FILE_ERROR"], [9, 4, 1, "", "ID_DEST_PATH_ERROR"], [9, 4, 1, "", "ID_INTERNAL_ERROR"], [9, 4, 1, "", "ID_SERVICE_ERROR"], [9, 4, 1, "", "ListingData"], [9, 4, 1, "", "NOTE_ACTIVE"], [9, 4, 1, "", "NOTE_CLOSED"], [9, 4, 1, "", "NOTE_ERROR"], [9, 4, 1, "", "NOTE_INFO"], [9, 4, 1, "", "NOTE_OPEN"], [9, 4, 1, "", "NOTE_QUESTION"], [9, 4, 1, "", "NOTE_WARN"], [9, 4, 1, "", "NoteComment"], [9, 4, 1, "", "NoteData"], [9, 4, 1, "", "NoteState"], [9, 4, 1, "", "NoteType"], [9, 4, 1, "", "PROJ_ADMIN"], [9, 4, 1, "", "PROJ_MANAGER"], [9, 4, 1, "", "PROJ_MEMBER"], [9, 4, 1, "", "PROJ_NO_ROLE"], [9, 4, 1, "", "PathData"], [9, 4, 1, "", "ProjectData"], [9, 4, 1, "", "ProjectRole"], [9, 4, 1, "", "RecordData"], [9, 4, 1, "", "RecordDataLocation"], [9, 4, 1, "", "RecordDataSize"], [9, 4, 1, "", "RepoData"], [9, 4, 1, "", "RepoRecordDataLocations"], [9, 4, 1, "", "SM_COLLECTION"], [9, 4, 1, "", "SM_DATA"], [9, 4, 1, "", "SORT_ID"], [9, 4, 1, "", "SORT_OWNER"], [9, 4, 1, "", "SORT_RELEVANCE"], [9, 4, 1, "", "SORT_TIME_CREATE"], [9, 4, 1, "", "SORT_TIME_UPDATE"], [9, 4, 1, "", "SORT_TITLE"], [9, 4, 1, "", "SS_DEGRADED"], [9, 4, 1, "", "SS_FAILED"], [9, 4, 1, "", "SS_NORMAL"], [9, 4, 1, "", "SS_OFFLINE"], [9, 4, 1, "", "SchemaData"], [9, 4, 1, "", "SearchMode"], [9, 4, 1, "", "ServiceStatus"], [9, 4, 1, "", "SortOption"], [9, 4, 1, "", "TC_ALLOC_CREATE"], [9, 4, 1, "", "TC_ALLOC_DELETE"], [9, 4, 1, "", "TC_RAW_DATA_DELETE"], [9, 4, 1, "", "TC_RAW_DATA_TRANSFER"], [9, 4, 1, "", "TC_RAW_DATA_UPDATE_SIZE"], [9, 4, 1, "", "TC_STOP"], [9, 4, 1, "", "TS_BLOCKED"], [9, 4, 1, "", "TS_FAILED"], [9, 4, 1, "", "TS_READY"], [9, 4, 1, "", "TS_RUNNING"], [9, 4, 1, "", "TS_SUCCEEDED"], [9, 4, 1, "", "TT_ALLOC_CREATE"], [9, 4, 1, "", "TT_ALLOC_DEL"], [9, 4, 1, "", "TT_DATA_DEL"], [9, 4, 1, "", "TT_DATA_GET"], [9, 4, 1, "", "TT_DATA_PUT"], [9, 4, 1, "", "TT_PROJ_DEL"], [9, 4, 1, "", "TT_REC_CHG_ALLOC"], [9, 4, 1, "", "TT_REC_CHG_OWNER"], [9, 4, 1, "", "TT_REC_DEL"], [9, 4, 1, "", "TT_USER_DEL"], [9, 4, 1, "", "TagData"], [9, 4, 1, "", "TaskCommand"], [9, 4, 1, "", "TaskData"], [9, 4, 1, "", "TaskStatus"], [9, 4, 1, "", "TaskType"], [9, 4, 1, "", "TopicData"], [9, 4, 1, "", "UserData"], [9, 4, 1, "", "_ACLRULE"], [9, 4, 1, "", "_ALLOCDATA"], [9, 4, 1, "", "_ALLOCSTATSDATA"], [9, 4, 1, "", "_COLLDATA"], [9, 4, 1, "", "_DEPENDENCYDATA"], [9, 4, 1, "", "_DEPENDENCYDIR"], [9, 4, 1, "", "_DEPENDENCYSPECDATA"], [9, 4, 1, "", "_DEPENDENCYTYPE"], [9, 4, 1, "", "_ENCRYPTION"], [9, 4, 1, "", "_ERRORCODE"], [9, 4, 1, "", "_GROUPDATA"], [9, 4, 1, "", "_LISTINGDATA"], [9, 4, 1, "", "_NOTECOMMENT"], [9, 4, 1, "", "_NOTEDATA"], [9, 4, 1, "", "_NOTESTATE"], [9, 4, 1, "", "_NOTETYPE"], [9, 4, 1, "", "_PATHDATA"], [9, 4, 1, "", "_PROJECTDATA"], [9, 4, 1, "", "_PROJECTROLE"], [9, 4, 1, "", "_RECORDDATA"], [9, 4, 1, "", "_RECORDDATALOCATION"], [9, 4, 1, "", "_RECORDDATASIZE"], [9, 4, 1, "", "_REPODATA"], [9, 4, 1, "", "_REPORECORDDATALOCATIONS"], [9, 4, 1, "", "_SCHEMADATA"], [9, 4, 1, "", "_SEARCHMODE"], [9, 4, 1, "", "_SERVICESTATUS"], [9, 4, 1, "", "_SORTOPTION"], [9, 4, 1, "", "_TAGDATA"], [9, 4, 1, "", "_TASKCOMMAND"], [9, 4, 1, "", "_TASKDATA"], [9, 4, 1, "", "_TASKSTATUS"], [9, 4, 1, "", "_TASKTYPE"], [9, 4, 1, "", "_TOPICDATA"], [9, 4, 1, "", "_USERDATA"], [9, 4, 1, "", "_sym_db"]], "datafed.VERSION": [[10, 4, 1, "", "__version__"]], "datafed.Version_pb2": [[11, 4, 1, "", "DATAFED_COMMON_PROTOCOL_API_MAJOR"], [11, 4, 1, "", "DATAFED_COMMON_PROTOCOL_API_MINOR"], [11, 4, 1, "", "DATAFED_COMMON_PROTOCOL_API_PATCH"], [11, 4, 1, "", "DATAFED_RELEASE_DAY"], [11, 4, 1, "", "DATAFED_RELEASE_HOUR"], [11, 4, 1, "", "DATAFED_RELEASE_MINUTE"], [11, 4, 1, "", "DATAFED_RELEASE_MONTH"], [11, 4, 1, "", "DATAFED_RELEASE_YEAR"], [11, 4, 1, "", "DESCRIPTOR"], [11, 4, 1, "", "Version"], [11, 4, 1, "", "_VERSION"], [11, 4, 1, "", "_sym_db"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:exception", "4": "py:data", "5": "py:function", "6": "py:attribute"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "exception", "Python exception"], "4": ["py", "data", "Python data"], "5": ["py", "function", "Python function"], "6": ["py", "attribute", "Python attribute"]}, "titleterms": {"dataf": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 18, 19, 20, 26, 28], "command": [0, 18, 24, 26], "coll": [0, 26], "add": [0, 26, 28], "creat": [0, 24, 26, 28], "delet": [0, 26], "remov": [0, 26, 28], "updat": [0, 26], "view": [0, 24, 26, 28], "data": [0, 1, 18, 19, 20, 21, 24, 26, 28, 30], "batch": [0, 26, 28], "get": [0, 19, 26, 28], "put": [0, 26], "ep": [0, 26], "default": [0, 26, 27, 28], "set": [0, 26, 27, 28, 30], "list": [0, 26, 28], "exit": [0, 26], "help": [0, 24, 26], "l": [0, 26], "project": [0, 15, 21, 26, 28, 30], "queri": [0, 26, 28], "exec": [0, 26], "run": [0, 26], "setup": [0, 26], "share": [0, 26, 30], "task": [0, 26, 28], "user": [0, 17, 21, 24, 26], "all": [0, 26], "collab": [0, 26], "who": [0, 26], "verbos": [0, 26], "wc": [0, 26], "wp": [0, 26], "administr": [1, 18], "system": [1, 21], "deploy": 1, "download": [1, 24, 28], "instal": [1, 19, 27], "depend": 1, "gener": 1, "configur": [1, 27], "databas": 1, "core": 1, "servic": 1, "web": [1, 18, 30], "repositori": [1, 21], "authz": 1, "librari": 1, "network": 1, "cli": 2, "modul": [2, 3, 4, 5, 6, 7, 8, 9, 10, 11], "content": [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 28], "class": [2, 3, 4, 5, 6], "function": [2, 6, 28], "attribut": [2, 3, 4], "commandlib": 3, "paramet": 3, "rais": 3, "return": 3, "config": [4, 27], "connect": 5, "messagelib": 6, "sdms_anon_pb2": 7, "sdms_auth_pb2": 8, "sdms_pb2": 9, "version": 10, "version_pb2": 11, "submodul": 12, "packag": [12, 18, 27, 28], "api": 13, "refer": [13, 21, 26, 27], "architectur": [14, 21], "design": 14, "manag": [15, 20, 21, 28], "personnel": 15, "releas": 16, "note": 16, "1": [16, 19, 27], "2": [16, 19, 27], "0": [16, 27], "4": [16, 19], "mai": 16, "28": 16, "2021": 16, "new": [16, 17], "featur": [16, 17], "impact": 16, "exist": 16, "enhanc": 16, "bug": 16, "fix": 16, "known": 16, "issu": 16, "road": 17, "map": 17, "plan": 17, "product": 17, "relat": 17, "chang": 17, "potenti": 17, "A": 18, "scientif": [18, 20, 24, 28], "feder": 18, "document": [18, 24], "about": 18, "portal": [18, 30], "client": [18, 27], "line": 18, "interfac": [18, 19, 21, 28], "python": [18, 27], "develop": 18, "indic": 18, "tabl": 18, "start": [19, 28], "globu": 19, "account": [19, 21], "id": [19, 28], "3": [19, 27], "regist": 19, "alloc": [19, 21], "5": 19, "identifi": [19, 21], "endpoint": [19, 27], "high": [19, 28], "perform": 19, "comput": 19, "cluster": 19, "person": [19, 30], "workstat": 19, "6": 19, "activ": 19, "program": 19, "introduct": [20, 24], "background": 20, "lifecycl": 20, "why": 20, "overview": 21, "cross": 21, "facil": 21, "concept": 21, "quick": [21, 27], "alias": [21, 28], "record": [21, 24, 28], "metadata": [21, 24, 28], "proven": [21, 28], "raw": [21, 24, 28], "field": 21, "summari": 21, "collect": [21, 28], "root": 21, "public": [21, 27], "access": 21, "control": 21, "schema": 21, "tag": 21, "annot": 21, "search": [21, 30], "catalog": 21, "paper": 22, "present": 22, "us": 23, "case": 23, "guid": [24, 28, 30], "syntax": 24, "shortcut": 24, "upload": [24, 28], "comment": 24, "prerequisit": 27, "ensur": 27, "bin": 27, "directori": 27, "i": 27, "path": 27, "basic": 27, "advanc": 27, "file": 27, "prioriti": 27, "automat": 27, "authent": 27, "server": 27, "kei": 27, "host": 27, "port": 27, "privat": 27, "level": 28, "import": 28, "instanc": 28, "respons": 28, "subcript": 28, "messag": 28, "object": 28, "iter": 28, "through": 28, "item": 28, "explor": 28, "context": 28, "per": 28, "alia": 28, "v": 28, "manual": 28, "work": 28, "prepar": 28, "extract": 28, "edit": 28, "inform": [28, 30], "replac": 28, "relationship": 28, "oper": 28, "other": 28, "transfer": [28, 30], "asynchron": 28, "popul": 28, "save": 28, "execut": 28, "continu": 28, "organ": 28, "parent": 28, "from": 28, "close": 28, "remark": 28, "jupyt": 29, "notebook": 29, "drag": 30, "drop": 30, "result": 30, "panel": 30, "action": 30, "button": 30, "header": 30, "footer": 30}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 58}, "alltitles": {"Datafed Commands": [[0, "datafed-commands"], [26, "datafed-commands"]], "Coll Commands": [[0, "coll-commands"], [26, "coll-commands"]], "Coll Add Command": [[0, "coll-add-command"], [26, "coll-add-command"]], "Coll Create Command": [[0, "coll-create-command"], [26, "coll-create-command"]], "Coll Delete Command": [[0, "coll-delete-command"], [26, "coll-delete-command"]], "Coll Remove Command": [[0, "coll-remove-command"], [26, "coll-remove-command"]], "Coll Update Command": [[0, "coll-update-command"], [26, "coll-update-command"]], "Coll View Command": [[0, "coll-view-command"], [26, "coll-view-command"]], "Data Commands": [[0, "data-commands"], [26, "data-commands"]], "Data Batch Commands": [[0, "data-batch-commands"], [26, "data-batch-commands"]], "Data Batch Create Command": [[0, "data-batch-create-command"], [26, "data-batch-create-command"]], "Data Batch Update Command": [[0, "data-batch-update-command"], [26, "data-batch-update-command"]], "Data Create Command": [[0, "data-create-command"], [26, "data-create-command"]], "Data Delete Command": [[0, "data-delete-command"], [26, "data-delete-command"]], "Data Get Command": [[0, "data-get-command"], [26, "data-get-command"]], "Data Put Command": [[0, "data-put-command"], [26, "data-put-command"]], "Data Update Command": [[0, "data-update-command"], [26, "data-update-command"]], "Data View Command": [[0, "data-view-command"], [26, "data-view-command"]], "Ep Commands": [[0, "ep-commands"], [26, "ep-commands"]], "Ep Default Commands": [[0, "ep-default-commands"], [26, "ep-default-commands"]], "Ep Default Get Command": [[0, "ep-default-get-command"], [26, "ep-default-get-command"]], "Ep Default Set Command": [[0, "ep-default-set-command"], [26, "ep-default-set-command"]], "Ep Get Command": [[0, "ep-get-command"], [26, "ep-get-command"]], "Ep List Command": [[0, "ep-list-command"], [26, "ep-list-command"]], "Ep Set Command": [[0, "ep-set-command"], [26, "ep-set-command"]], "Exit Command": [[0, "exit-command"], [26, "exit-command"]], "Help Command": [[0, "help-command"], [26, "help-command"]], "Ls Command": [[0, "ls-command"], [26, "ls-command"]], "Project Commands": [[0, "project-commands"], [26, "project-commands"]], "Project List Command": [[0, "project-list-command"], [26, "project-list-command"]], "Project View Command": [[0, "project-view-command"], [26, "project-view-command"]], "Query Commands": [[0, "query-commands"], [26, "query-commands"]], "Query Create Command": [[0, "query-create-command"], [26, "query-create-command"]], "Query Delete Command": [[0, "query-delete-command"], [26, "query-delete-command"]], "Query Exec Command": [[0, "query-exec-command"], [26, "query-exec-command"]], "Query List Command": [[0, "query-list-command"], [26, "query-list-command"]], "Query Run Command": [[0, "query-run-command"], [26, "query-run-command"]], "Query Update Command": [[0, "query-update-command"], [26, "query-update-command"]], "Query View Command": [[0, "query-view-command"], [26, "query-view-command"]], "Setup Command": [[0, "setup-command"], [26, "setup-command"]], "Shares Command": [[0, "shares-command"], [26, "shares-command"]], "Task Commands": [[0, "task-commands"], [26, "task-commands"]], "Task List Command": [[0, "task-list-command"], [26, "task-list-command"]], "Task View Command": [[0, "task-view-command"], [26, "task-view-command"]], "User Commands": [[0, "user-commands"], [26, "user-commands"]], "User All Command": [[0, "user-all-command"], [26, "user-all-command"]], "User Collab Command": [[0, "user-collab-command"], [26, "user-collab-command"]], "User View Command": [[0, "user-view-command"], [26, "user-view-command"]], "User Who Command": [[0, "user-who-command"], [26, "user-who-command"]], "Verbosity Command": [[0, "verbosity-command"], [26, "verbosity-command"]], "Wc Command": [[0, "wc-command"], [26, "wc-command"]], "Wp Command": [[0, "wp-command"], [26, "wp-command"]], "Administration": [[1, "administration"], [18, null]], "System Deployment": [[1, "system-deployment"]], "Downloading DataFed & Installing Dependencies": [[1, "downloading-datafed-installing-dependencies"]], "General Installation & Configuration": [[1, "general-installation-configuration"]], "Database": [[1, "database"]], "Core Service": [[1, "core-service"]], "Web Service": [[1, "web-service"]], "Data Repository": [[1, "data-repository"]], "Authz Library": [[1, "authz-library"]], "Networking": [[1, "networking"]], "datafed.CLI": [[2, "module-datafed.CLI"]], "Module Contents": [[2, "module-contents"], [3, "module-contents"], [4, "module-contents"], [5, "module-contents"], [6, "module-contents"], [7, "module-contents"], [8, "module-contents"], [9, "module-contents"], [10, "module-contents"], [11, "module-contents"]], "Classes": [[2, "classes"], [3, "classes"], [4, "classes"], [5, "classes"], [6, "classes"]], "Functions": [[2, "functions"], [6, "functions"]], "Attributes": [[2, "attributes"], [3, "attributes"], [4, "attributes"]], "datafed.CommandLib": [[3, "module-datafed.CommandLib"]], "Parameters": [[3, "parameters"], [3, "id2"], [3, "id7"], [3, "id10"], [3, "id13"], [3, "id16"], [3, "id19"], [3, "id22"], [3, "id25"], [3, "id28"], [3, "id31"], [3, "id34"], [3, "id37"], [3, "id40"], [3, "id43"], [3, "id46"], [3, "id49"], [3, "id52"], [3, "id55"], [3, "id58"], [3, "id61"], [3, "id64"], [3, "id67"], [3, "id70"], [3, "id73"], [3, "id76"], [3, "id79"], [3, "id82"], [3, "id85"], [3, "id88"], [3, "id91"], [3, "id94"], [3, "id97"], [3, "id100"], [3, "id103"], [3, "id106"], [3, "id112"], [3, "id114"], [3, "id117"], [3, "id121"], [3, "id123"], [3, "id125"], [3, "id127"], [3, "id129"], [3, "id131"], [3, "id133"]], "Raises": [[3, "raises"], [3, "id4"], [3, "id6"], [3, "id9"], [3, "id12"], [3, "id15"], [3, "id18"], [3, "id21"], [3, "id24"], [3, "id27"], [3, "id30"], [3, "id33"], [3, "id36"], [3, "id39"], [3, "id42"], [3, "id45"], [3, "id48"], [3, "id51"], [3, "id54"], [3, "id57"], [3, "id60"], [3, "id63"], [3, "id66"], [3, "id69"], [3, "id72"], [3, "id75"], [3, "id78"], [3, "id81"], [3, "id84"], [3, "id87"], [3, "id90"], [3, "id93"], [3, "id96"], [3, "id99"], [3, "id102"], [3, "id105"], [3, "id108"], [3, "id110"], [3, "id116"], [3, "id119"]], "Returns": [[3, "returns"], [3, "id1"], [3, "id3"], [3, "id5"], [3, "id8"], [3, "id11"], [3, "id14"], [3, "id17"], [3, "id20"], [3, "id23"], [3, "id26"], [3, "id29"], [3, "id32"], [3, "id35"], [3, "id38"], [3, "id41"], [3, "id44"], [3, "id47"], [3, "id50"], [3, "id53"], [3, "id56"], [3, "id59"], [3, "id62"], [3, "id65"], [3, "id68"], [3, "id71"], [3, "id74"], [3, "id77"], [3, "id80"], [3, "id83"], [3, "id86"], [3, "id89"], [3, "id92"], [3, "id95"], [3, "id98"], [3, "id101"], [3, "id104"], [3, "id107"], [3, "id109"], [3, "id111"], [3, "id113"], [3, "id115"], [3, "id118"], [3, "id120"], [3, "id122"], [3, "id124"], [3, "id126"], [3, "id128"], [3, "id130"], [3, "id132"], [3, "id134"], [3, "id135"]], "datafed.Config": [[4, "module-datafed.Config"]], "datafed.Connection": [[5, "module-datafed.Connection"]], "datafed.MessageLib": [[6, "module-datafed.MessageLib"]], "datafed.SDMS_Anon_pb2": [[7, "module-datafed.SDMS_Anon_pb2"]], "datafed.SDMS_Auth_pb2": [[8, "module-datafed.SDMS_Auth_pb2"]], "datafed.SDMS_pb2": [[9, "module-datafed.SDMS_pb2"]], "datafed.VERSION": [[10, "module-datafed.VERSION"]], "datafed.Version_pb2": [[11, "module-datafed.Version_pb2"]], "datafed": [[12, "module-datafed"]], "Submodules": [[12, "submodules"]], "Package Contents": [[12, "package-contents"]], "API Reference": [[13, "api-reference"]], "Architecture & Design": [[14, "architecture-design"]], "Project Management": [[15, "project-management"]], "Personnel": [[15, "personnel"]], "Release Notes": [[16, "release-notes"]], "1.2.0-4, May 28, 2021": [[16, "may-28-2021"]], "New Features": [[16, "new-features"]], "Impacts to Existing Features": [[16, "impacts-to-existing-features"]], "Enhancements and Bug Fixes": [[16, "enhancements-and-bug-fixes"]], "Known Issues": [[16, "known-issues"]], "Feature Road Map": [[17, "feature-road-map"]], "Planned Features": [[17, "planned-features"]], "New User Features": [[17, "new-user-features"]], "Production-Related Changes": [[17, "production-related-changes"]], "Potential Features / Changes": [[17, "potential-features-changes"]], "DataFed - A Scientific Data Federation": [[18, "datafed-a-scientific-data-federation"]], "DataFed Documentation": [[18, "datafed-documentation"]], "About DataFed": [[18, null]], "Web Portal": [[18, null]], "Client Package": [[18, null]], "Command Line Interface": [[18, null]], "Python Interface": [[18, null]], "Development": [[18, null]], "Indices and tables": [[18, "indices-and-tables"]], "Getting Started": [[19, "getting-started"], [28, "getting-started"]], "1. Get a Globus account": [[19, "get-a-globus-account"]], "2. Get a Globus ID": [[19, "get-a-globus-id"]], "3. Register at DataFed": [[19, "register-at-datafed"]], "4. Get data allocations": [[19, "get-data-allocations"]], "5. Install / identify Globus Endpoint": [[19, "install-identify-globus-endpoint"]], "High Performance Compute clusters": [[19, "high-performance-compute-clusters"]], "Personal Computers and Workstations": [[19, "personal-computers-and-workstations"]], "6. Activate Globus Endpoint": [[19, "activate-globus-endpoint"]], "Programming interfaces to DataFed": [[19, "programming-interfaces-to-datafed"]], "Introduction": [[20, "introduction"], [24, "introduction"]], "Background": [[20, "background"]], "Scientific Data Management": [[20, "scientific-data-management"]], "Data Lifecycle": [[20, "data-lifecycle"]], "Why DataFed?": [[20, "why-datafed"]], "System Overview": [[21, "system-overview"]], "Cross-Facility Data Management": [[21, "cross-facility-data-management"]], "System Architecture": [[21, "system-architecture"]], "Interfaces": [[21, "interfaces"]], "User Accounts": [[21, "user-accounts"]], "System Concepts": [[21, "system-concepts"]], "Quick Reference": [[21, "quick-reference"]], "Identifiers and Aliases": [[21, "identifiers-and-aliases"]], "Data Records": [[21, "data-records"], [28, "data-records"]], "Metadata": [[21, "metadata"]], "Provenance": [[21, "provenance"]], "Raw Data": [[21, "raw-data"]], "Field Summary": [[21, "field-summary"], [21, "id1"]], "Collections": [[21, "collections"], [28, "collections"]], "Root Collection": [[21, "root-collection"]], "Public Collections": [[21, "public-collections"]], "Projects": [[21, "projects"]], "Access Controls": [[21, "access-controls"]], "Repository Allocations": [[21, "repository-allocations"]], "Metadata Schemas": [[21, "metadata-schemas"]], "Tags": [[21, "tags"]], "Annotations": [[21, "annotations"]], "Data and Collection Search": [[21, "data-and-collection-search"]], "Catalog": [[21, "catalog"]], "Papers and Presentations": [[22, "papers-and-presentations"]], "Use Cases": [[23, "use-cases"]], "User Guide": [[24, "user-guide"]], "Command Syntax": [[24, "command-syntax"]], "Command Shortcuts": [[24, "command-shortcuts"]], "Help and Documentation": [[24, "help-and-documentation"]], "Scientific Metadata": [[24, "scientific-metadata"]], "Creating Records": [[24, "creating-records"]], "Uploading Raw Data": [[24, "uploading-raw-data"]], "Viewing Data Records": [[24, "viewing-data-records"]], "Downloading Raw Data": [[24, "downloading-raw-data"]], "Comments": [[24, "comments"]], "Command Reference": [[26, "command-reference"]], "Installation and Configuration": [[27, "installation-and-configuration"]], "Installation": [[27, "installation"]], "0. Prerequisites": [[27, "prerequisites"]], "1. Install python package": [[27, "install-python-package"]], "2. Ensure bin directory is in Path": [[27, "ensure-bin-directory-is-in-path"]], "3. Basic Configuration": [[27, "basic-configuration"]], "Advanced Configuration": [[27, "advanced-configuration"]], "Configuration Files": [[27, "configuration-files"]], "Configuration Priority": [[27, "configuration-priority"]], "Configuring Automatic Authentication": [[27, "configuring-automatic-authentication"]], "Configuration Settings": [[27, "configuration-settings"]], "Settings Quick Reference": [[27, "settings-quick-reference"]], "Server Configuration File": [[27, "server-configuration-file"]], "Server Configuration Directory": [[27, "server-configuration-directory"]], "Server Public Key File": [[27, "server-public-key-file"]], "Server Host": [[27, "server-host"]], "Server Port": [[27, "server-port"]], "Client Configuration File": [[27, "client-configuration-file"]], "Client Config Directory": [[27, "client-config-directory"]], "Client Public Key File": [[27, "client-public-key-file"]], "Client Private Key File": [[27, "client-private-key-file"]], "Default Endpoint": [[27, "default-endpoint"]], "Guide to High Level Interface": [[28, "guide-to-high-level-interface"]], "Import package": [[28, "import-package"]], "Create instance": [[28, "create-instance"]], "DataFed Responses & Projects": [[28, "datafed-responses-projects"]], "DataFed functions and responses": [[28, "datafed-functions-and-responses"]], "Subcripting message objects": [[28, "subcripting-message-objects"]], "Iterating through message items": [[28, "iterating-through-message-items"]], "Exploring projects": [[28, "exploring-projects"]], "Contexts, aliases & IDs": [[28, "contexts-aliases-ids"]], "Default context": [[28, "default-context"]], "Context per function": [[28, "context-per-function"]], "Contents of contexts": [[28, "contents-of-contexts"]], "Alias vs ID": [[28, "alias-vs-id"]], "Manual context management": [[28, "manual-context-management"]], "Set default context": [[28, "set-default-context"]], "Set working collection": [[28, "set-working-collection"]], "Prepare (scientific) metadata": [[28, "prepare-scientific-metadata"]], "Create Data Record": [[28, "create-data-record"]], "Extract Record ID": [[28, "extract-record-id"]], "Edit Record information": [[28, "edit-record-information"]], "View Record information": [[28, "view-record-information"]], "Extract metadata": [[28, "extract-metadata"]], "Replace metadata": [[28, "replace-metadata"]], "Relationships and provenance": [[28, "relationships-and-provenance"]], "Batch operations": [[28, "batch-operations"]], "Other functions": [[28, "other-functions"], [28, "id3"]], "Data Transfer": [[28, "data-transfer"]], "Upload raw data": [[28, "upload-raw-data"]], "Download raw data": [[28, "download-raw-data"]], "Tasks": [[28, "tasks"]], "Asynchronous transfers": [[28, "asynchronous-transfers"]], "Task list": [[28, "task-list"]], "Create collection": [[28, "create-collection"]], "Populate with Records": [[28, "populate-with-records"]], "List items in Collection": [[28, "list-items-in-collection"]], "Queries": [[28, "queries"]], "Create query": [[28, "create-query"]], "List saved queries": [[28, "list-saved-queries"]], "View query": [[28, "view-query"]], "Execute query": [[28, "execute-query"]], "Collections continued": [[28, "collections-continued"]], "Organize with Collections": [[28, "organize-with-collections"]], "Collection Parents": [[28, "collection-parents"]], "Add and remove from Collections": [[28, "add-and-remove-from-collections"]], "Download Collection": [[28, "download-collection"]], "Closing remarks": [[28, "closing-remarks"]], "Jupyter Notebooks": [[29, "jupyter-notebooks"]], "Web Portal Guide": [[30, "web-portal-guide"]], "Drag and Drop": [[30, "drag-and-drop"]], "Personal Data": [[30, "personal-data"]], "Project Data": [[30, "project-data"]], "Shared Data": [[30, "shared-data"]], "Search Results": [[30, "search-results"]], "Information Panel": [[30, "information-panel"]], "Action Buttons": [[30, "action-buttons"]], "Search": [[30, "search"]], "Transfers": [[30, "transfers"]], "Settings": [[30, "settings"]], "Header and Footer": [[30, "header-and-footer"]]}, "indexentries": {"_aliasedgroup (class in datafed.cli)": [[2, "datafed.CLI._AliasedGroup"]], "_aliasedgrouproot (class in datafed.cli)": [[2, "datafed.CLI._AliasedGroupRoot"]], "_nocommand": [[2, "datafed.CLI._NoCommand"]], "_om_json (in module datafed.cli)": [[2, "datafed.CLI._OM_JSON"]], "_om_retn (in module datafed.cli)": [[2, "datafed.CLI._OM_RETN"]], "_om_text (in module datafed.cli)": [[2, "datafed.CLI._OM_TEXT"]], "_stat_error (in module datafed.cli)": [[2, "datafed.CLI._STAT_ERROR"]], "_stat_ok (in module datafed.cli)": [[2, "datafed.CLI._STAT_OK"]], "__global_context_options (in module datafed.cli)": [[2, "datafed.CLI.__global_context_options"]], "__global_output_options (in module datafed.cli)": [[2, "datafed.CLI.__global_output_options"]], "_addconfigoptions() (in module datafed.cli)": [[2, "datafed.CLI._addConfigOptions"]], "_arraytocsv() (in module datafed.cli)": [[2, "datafed.CLI._arrayToCSV"]], "_arraytodotted() (in module datafed.cli)": [[2, "datafed.CLI._arrayToDotted"]], "_bar_adaptive_human_readable() (in module datafed.cli)": [[2, "datafed.CLI._bar_adaptive_human_readable"]], "_batch() (in module datafed.cli)": [[2, "datafed.CLI._batch"]], "_capi (in module datafed.cli)": [[2, "datafed.CLI._capi"]], "_cli() (in module datafed.cli)": [[2, "datafed.CLI._cli"]], "_coll() (in module datafed.cli)": [[2, "datafed.CLI._coll"]], "_collcreate() (in module datafed.cli)": [[2, "datafed.CLI._collCreate"]], "_colldelete() (in module datafed.cli)": [[2, "datafed.CLI._collDelete"]], "_collitemsadd() (in module datafed.cli)": [[2, "datafed.CLI._collItemsAdd"]], "_collupdate() (in module datafed.cli)": [[2, "datafed.CLI._collUpdate"]], "_collview() (in module datafed.cli)": [[2, "datafed.CLI._collView"]], "_coll_rem() (in module datafed.cli)": [[2, "datafed.CLI._coll_rem"]], "_ctxt_settings (in module datafed.cli)": [[2, "datafed.CLI._ctxt_settings"]], "_cur_alias_prefix (in module datafed.cli)": [[2, "datafed.CLI._cur_alias_prefix"]], "_cur_coll (in module datafed.cli)": [[2, "datafed.CLI._cur_coll"]], "_cur_coll_prefix (in module datafed.cli)": [[2, "datafed.CLI._cur_coll_prefix"]], "_cur_coll_title (in module datafed.cli)": [[2, "datafed.CLI._cur_coll_title"]], "_cur_ctx (in module datafed.cli)": [[2, "datafed.CLI._cur_ctx"]], "_data() (in module datafed.cli)": [[2, "datafed.CLI._data"]], "_datacreate() (in module datafed.cli)": [[2, "datafed.CLI._dataCreate"]], "_datadelete() (in module datafed.cli)": [[2, "datafed.CLI._dataDelete"]], "_dataget() (in module datafed.cli)": [[2, "datafed.CLI._dataGet"]], "_dataput() (in module datafed.cli)": [[2, "datafed.CLI._dataPut"]], "_dataupdate() (in module datafed.cli)": [[2, "datafed.CLI._dataUpdate"]], "_dataview() (in module datafed.cli)": [[2, "datafed.CLI._dataView"]], "_data_batch_create() (in module datafed.cli)": [[2, "datafed.CLI._data_batch_create"]], "_data_batch_update() (in module datafed.cli)": [[2, "datafed.CLI._data_batch_update"]], "_devnull (in module datafed.cli)": [[2, "datafed.CLI._devnull"]], "_ep() (in module datafed.cli)": [[2, "datafed.CLI._ep"]], "_epdefault() (in module datafed.cli)": [[2, "datafed.CLI._epDefault"]], "_epdefaultget() (in module datafed.cli)": [[2, "datafed.CLI._epDefaultGet"]], "_epdefaultset() (in module datafed.cli)": [[2, "datafed.CLI._epDefaultSet"]], "_epget() (in module datafed.cli)": [[2, "datafed.CLI._epGet"]], "_eplist() (in module datafed.cli)": [[2, "datafed.CLI._epList"]], "_epset() (in module datafed.cli)": [[2, "datafed.CLI._epSet"]], "_exit_cli() (in module datafed.cli)": [[2, "datafed.CLI._exit_cli"]], "_gendoc() (in module datafed.cli)": [[2, "datafed.CLI._genDoc"]], "_gendoccmd() (in module datafed.cli)": [[2, "datafed.CLI._genDocCmd"]], "_gendocheader() (in module datafed.cli)": [[2, "datafed.CLI._genDocHeader"]], "_generic_reply_handler() (in module datafed.cli)": [[2, "datafed.CLI._generic_reply_handler"]], "_global_context_options() (in module datafed.cli)": [[2, "datafed.CLI._global_context_options"]], "_global_output_options() (in module datafed.cli)": [[2, "datafed.CLI._global_output_options"]], "_hdr_lev_char (in module datafed.cli)": [[2, "datafed.CLI._hdr_lev_char"]], "_help_cli() (in module datafed.cli)": [[2, "datafed.CLI._help_cli"]], "_initialize() (in module datafed.cli)": [[2, "datafed.CLI._initialize"]], "_initialized (in module datafed.cli)": [[2, "datafed.CLI._initialized"]], "_interactive (in module datafed.cli)": [[2, "datafed.CLI._interactive"]], "_list() (in module datafed.cli)": [[2, "datafed.CLI._list"]], "_list_items (in module datafed.cli)": [[2, "datafed.CLI._list_items"]], "_output_mode (in module datafed.cli)": [[2, "datafed.CLI._output_mode"]], "_output_mode_sticky (in module datafed.cli)": [[2, "datafed.CLI._output_mode_sticky"]], "_prev_coll (in module datafed.cli)": [[2, "datafed.CLI._prev_coll"]], "_prev_ctx (in module datafed.cli)": [[2, "datafed.CLI._prev_ctx"]], "_printjson() (in module datafed.cli)": [[2, "datafed.CLI._printJSON"]], "_printjson_list() (in module datafed.cli)": [[2, "datafed.CLI._printJSON_List"]], "_print_ack_reply() (in module datafed.cli)": [[2, "datafed.CLI._print_ack_reply"]], "_print_batch() (in module datafed.cli)": [[2, "datafed.CLI._print_batch"]], "_print_coll() (in module datafed.cli)": [[2, "datafed.CLI._print_coll"]], "_print_data() (in module datafed.cli)": [[2, "datafed.CLI._print_data"]], "_print_deps() (in module datafed.cli)": [[2, "datafed.CLI._print_deps"]], "_print_endpoints() (in module datafed.cli)": [[2, "datafed.CLI._print_endpoints"]], "_print_listing() (in module datafed.cli)": [[2, "datafed.CLI._print_listing"]], "_print_msg() (in module datafed.cli)": [[2, "datafed.CLI._print_msg"]], "_print_path() (in module datafed.cli)": [[2, "datafed.CLI._print_path"]], "_print_proj() (in module datafed.cli)": [[2, "datafed.CLI._print_proj"]], "_print_proj_listing() (in module datafed.cli)": [[2, "datafed.CLI._print_proj_listing"]], "_print_query() (in module datafed.cli)": [[2, "datafed.CLI._print_query"]], "_print_task() (in module datafed.cli)": [[2, "datafed.CLI._print_task"]], "_print_task_array() (in module datafed.cli)": [[2, "datafed.CLI._print_task_array"]], "_print_task_listing() (in module datafed.cli)": [[2, "datafed.CLI._print_task_listing"]], "_print_user() (in module datafed.cli)": [[2, "datafed.CLI._print_user"]], "_print_user_listing() (in module datafed.cli)": [[2, "datafed.CLI._print_user_listing"]], "_project() (in module datafed.cli)": [[2, "datafed.CLI._project"]], "_projectlist() (in module datafed.cli)": [[2, "datafed.CLI._projectList"]], "_projectview() (in module datafed.cli)": [[2, "datafed.CLI._projectView"]], "_query() (in module datafed.cli)": [[2, "datafed.CLI._query"]], "_querycreate() (in module datafed.cli)": [[2, "datafed.CLI._queryCreate"]], "_querydelete() (in module datafed.cli)": [[2, "datafed.CLI._queryDelete"]], "_queryexec() (in module datafed.cli)": [[2, "datafed.CLI._queryExec"]], "_querylist() (in module datafed.cli)": [[2, "datafed.CLI._queryList"]], "_queryrun() (in module datafed.cli)": [[2, "datafed.CLI._queryRun"]], "_queryupdate() (in module datafed.cli)": [[2, "datafed.CLI._queryUpdate"]], "_queryview() (in module datafed.cli)": [[2, "datafed.CLI._queryView"]], "_resolve_coll_id() (in module datafed.cli)": [[2, "datafed.CLI._resolve_coll_id"]], "_resolve_id() (in module datafed.cli)": [[2, "datafed.CLI._resolve_id"]], "_return_val (in module datafed.cli)": [[2, "datafed.CLI._return_val"]], "_setworkingcollectiontitle() (in module datafed.cli)": [[2, "datafed.CLI._setWorkingCollectionTitle"]], "_set_script_cb() (in module datafed.cli)": [[2, "datafed.CLI._set_script_cb"]], "_set_verbosity_cb() (in module datafed.cli)": [[2, "datafed.CLI._set_verbosity_cb"]], "_setup() (in module datafed.cli)": [[2, "datafed.CLI._setup"]], "_shares() (in module datafed.cli)": [[2, "datafed.CLI._shares"]], "_task() (in module datafed.cli)": [[2, "datafed.CLI._task"]], "_tasklist() (in module datafed.cli)": [[2, "datafed.CLI._taskList"]], "_taskview() (in module datafed.cli)": [[2, "datafed.CLI._taskView"]], "_task_statuses (in module datafed.cli)": [[2, "datafed.CLI._task_statuses"]], "_task_types (in module datafed.cli)": [[2, "datafed.CLI._task_types"]], "_uid (in module datafed.cli)": [[2, "datafed.CLI._uid"]], "_user() (in module datafed.cli)": [[2, "datafed.CLI._user"]], "_userlistall() (in module datafed.cli)": [[2, "datafed.CLI._userListAll"]], "_userlistcollab() (in module datafed.cli)": [[2, "datafed.CLI._userListCollab"]], "_userview() (in module datafed.cli)": [[2, "datafed.CLI._userView"]], "_userwho() (in module datafed.cli)": [[2, "datafed.CLI._userWho"]], "_verbosity (in module datafed.cli)": [[2, "datafed.CLI._verbosity"]], "_verbosityset() (in module datafed.cli)": [[2, "datafed.CLI._verbositySet"]], "_verbosity_sticky (in module datafed.cli)": [[2, "datafed.CLI._verbosity_sticky"]], "_wc() (in module datafed.cli)": [[2, "datafed.CLI._wc"]], "_wp() (in module datafed.cli)": [[2, "datafed.CLI._wp"]], "_wrap_text() (in module datafed.cli)": [[2, "datafed.CLI._wrap_text"]], "command() (in module datafed.cli)": [[2, "datafed.CLI.command"]], "datafed.cli": [[2, "module-datafed.CLI"]], "get_command() (datafed.cli._aliasedgroup method)": [[2, "datafed.CLI._AliasedGroup.get_command"]], "get_command() (datafed.cli._aliasedgrouproot method)": [[2, "datafed.CLI._AliasedGroupRoot.get_command"]], "init() (in module datafed.cli)": [[2, "datafed.CLI.init"]], "loginbypassword() (in module datafed.cli)": [[2, "datafed.CLI.loginByPassword"]], "loginbytoken() (in module datafed.cli)": [[2, "datafed.CLI.loginByToken"]], "module": [[2, "module-datafed.CLI"], [3, "module-datafed.CommandLib"], [4, "module-datafed.Config"], [5, "module-datafed.Connection"], [6, "module-datafed.MessageLib"], [7, "module-datafed.SDMS_Anon_pb2"], [8, "module-datafed.SDMS_Auth_pb2"], [9, "module-datafed.SDMS_pb2"], [10, "module-datafed.VERSION"], [11, "module-datafed.Version_pb2"], [12, "module-datafed"]], "resolve_command() (datafed.cli._aliasedgroup method)": [[2, "datafed.CLI._AliasedGroup.resolve_command"]], "run() (in module datafed.cli)": [[2, "datafed.CLI.run"]], "api (class in datafed.commandlib)": [[3, "datafed.CommandLib.API"]], "_buildsearchrequest() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API._buildSearchRequest"]], "_endpoint_legacy (datafed.commandlib.api attribute)": [[3, "datafed.CommandLib.API._endpoint_legacy"]], "_endpoint_uuid (datafed.commandlib.api attribute)": [[3, "datafed.CommandLib.API._endpoint_uuid"]], "_max_md_size (datafed.commandlib.api attribute)": [[3, "datafed.CommandLib.API._max_md_size"]], "_max_payload_size (datafed.commandlib.api attribute)": [[3, "datafed.CommandLib.API._max_payload_size"]], "_resolvepathforglobus() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API._resolvePathForGlobus"]], "_resolvepathforhttp() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API._resolvePathForHTTP"]], "_resolve_id() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API._resolve_id"]], "_setsanedefaultoptions() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API._setSaneDefaultOptions"]], "_uniquifyfilename() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API._uniquifyFilename"]], "collectioncreate() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.collectionCreate"]], "collectiondelete() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.collectionDelete"]], "collectiongetparents() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.collectionGetParents"]], "collectionitemslist() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.collectionItemsList"]], "collectionitemsupdate() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.collectionItemsUpdate"]], "collectionupdate() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.collectionUpdate"]], "collectionview() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.collectionView"]], "databatchcreate() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.dataBatchCreate"]], "databatchupdate() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.dataBatchUpdate"]], "datacreate() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.dataCreate"]], "datadelete() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.dataDelete"]], "dataget() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.dataGet"]], "dataput() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.dataPut"]], "dataupdate() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.dataUpdate"]], "dataview() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.dataView"]], "datafed.commandlib": [[3, "module-datafed.CommandLib"]], "endpointdefaultget() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.endpointDefaultGet"]], "endpointdefaultset() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.endpointDefaultSet"]], "endpointget() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.endpointGet"]], "endpointlistrecent() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.endpointListRecent"]], "endpointset() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.endpointSet"]], "generatecredentials() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.generateCredentials"]], "getauthuser() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.getAuthUser"]], "getcontext() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.getContext"]], "loginbypassword() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.loginByPassword"]], "logout() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.logout"]], "projectgetrole() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.projectGetRole"]], "projectlist() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.projectList"]], "projectview() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.projectView"]], "querycreate() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.queryCreate"]], "querydelete() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.queryDelete"]], "querydirect() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.queryDirect"]], "queryexec() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.queryExec"]], "querylist() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.queryList"]], "queryupdate() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.queryUpdate"]], "queryview() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.queryView"]], "repoallocationcreate() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.repoAllocationCreate"]], "repoallocationdelete() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.repoAllocationDelete"]], "repocreate() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.repoCreate"]], "repodelete() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.repoDelete"]], "repolist() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.repoList"]], "repolistallocations() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.repoListAllocations"]], "setcontext() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.setContext"]], "setupcredentials() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.setupCredentials"]], "sharedlist() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.sharedList"]], "sharedlistitems() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.sharedListItems"]], "sizetostr() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.sizeToStr"]], "strtotimestamp() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.strToTimestamp"]], "tasklist() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.taskList"]], "taskview() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.taskView"]], "timestamptostr() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.timestampToStr"]], "userlistall() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.userListAll"]], "userlistcollaborators() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.userListCollaborators"]], "userview() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.userView"]], "api (class in datafed.config)": [[4, "datafed.Config.API"]], "_opt_bool (in module datafed.config)": [[4, "datafed.Config._OPT_BOOL"]], "_opt_eager (in module datafed.config)": [[4, "datafed.Config._OPT_EAGER"]], "_opt_hide (in module datafed.config)": [[4, "datafed.Config._OPT_HIDE"]], "_opt_int (in module datafed.config)": [[4, "datafed.Config._OPT_INT"]], "_opt_no_cf (in module datafed.config)": [[4, "datafed.Config._OPT_NO_CF"]], "_opt_no_cl (in module datafed.config)": [[4, "datafed.Config._OPT_NO_CL"]], "_opt_no_env (in module datafed.config)": [[4, "datafed.Config._OPT_NO_ENV"]], "_opt_path (in module datafed.config)": [[4, "datafed.Config._OPT_PATH"]], "_loadconfigfile() (datafed.config.api method)": [[4, "datafed.Config.API._loadConfigFile"]], "_loadenvironvars() (datafed.config.api method)": [[4, "datafed.Config.API._loadEnvironVars"]], "_opt_info (in module datafed.config)": [[4, "datafed.Config._opt_info"]], "_processoptions() (datafed.config.api method)": [[4, "datafed.Config.API._processOptions"]], "datafed.config": [[4, "module-datafed.Config"]], "get() (datafed.config.api method)": [[4, "datafed.Config.API.get"]], "getopts() (datafed.config.api method)": [[4, "datafed.Config.API.getOpts"]], "printsettinginfo() (datafed.config.api method)": [[4, "datafed.Config.API.printSettingInfo"]], "save() (datafed.config.api method)": [[4, "datafed.Config.API.save"]], "set() (datafed.config.api method)": [[4, "datafed.Config.API.set"]], "connection (class in datafed.connection)": [[5, "datafed.Connection.Connection"]], "__del__() (datafed.connection.connection method)": [[5, "datafed.Connection.Connection.__del__"]], "datafed.connection": [[5, "module-datafed.Connection"]], "makemessage() (datafed.connection.connection method)": [[5, "datafed.Connection.Connection.makeMessage"]], "recv() (datafed.connection.connection method)": [[5, "datafed.Connection.Connection.recv"]], "registerprotocol() (datafed.connection.connection method)": [[5, "datafed.Connection.Connection.registerProtocol"]], "reset() (datafed.connection.connection method)": [[5, "datafed.Connection.Connection.reset"]], "send() (datafed.connection.connection method)": [[5, "datafed.Connection.Connection.send"]], "api (class in datafed.messagelib)": [[6, "datafed.MessageLib.API"]], "datafed.messagelib": [[6, "module-datafed.MessageLib"]], "getauthstatus() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.getAuthStatus"]], "getdailymessage() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.getDailyMessage"]], "getdefaulttimeout() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.getDefaultTimeout"]], "getnackexceptionenabled() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.getNackExceptionEnabled"]], "get_latest_version() (in module datafed.messagelib)": [[6, "datafed.MessageLib.get_latest_version"]], "keysloaded() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.keysLoaded"]], "keysvalid() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.keysValid"]], "logout() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.logout"]], "manualauthbypassword() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.manualAuthByPassword"]], "manualauthbytoken() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.manualAuthByToken"]], "recv() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.recv"]], "send() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.send"]], "sendrecv() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.sendRecv"]], "setdefaulttimeout() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.setDefaultTimeout"]], "setnackexceptionenabled() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.setNackExceptionEnabled"]], "ackreply (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.AckReply"]], "authstatusreply (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.AuthStatusReply"]], "authenticatebypasswordrequest (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.AuthenticateByPasswordRequest"]], "authenticatebytokenrequest (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.AuthenticateByTokenRequest"]], "descriptor (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.DESCRIPTOR"]], "dailymessagereply (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.DailyMessageReply"]], "dailymessagerequest (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.DailyMessageRequest"]], "getauthstatusrequest (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.GetAuthStatusRequest"]], "id (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.ID"]], "nackreply (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.NackReply"]], "protocol (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.Protocol"]], "versionreply (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.VersionReply"]], "versionrequest (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.VersionRequest"]], "_ackreply (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._ACKREPLY"]], "_authenticatebypasswordrequest (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._AUTHENTICATEBYPASSWORDREQUEST"]], "_authenticatebytokenrequest (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._AUTHENTICATEBYTOKENREQUEST"]], "_authstatusreply (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._AUTHSTATUSREPLY"]], "_dailymessagereply (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._DAILYMESSAGEREPLY"]], "_dailymessagerequest (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._DAILYMESSAGEREQUEST"]], "_getauthstatusrequest (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._GETAUTHSTATUSREQUEST"]], "_nackreply (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._NACKREPLY"]], "_protocol (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._PROTOCOL"]], "_versionreply (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._VERSIONREPLY"]], "_versionrequest (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._VERSIONREQUEST"]], "_msg_name_to_type (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._msg_name_to_type"], [7, "id0"], [7, "id10"], [7, "id12"], [7, "id14"], [7, "id16"], [7, "id18"], [7, "id2"], [7, "id20"], [7, "id22"], [7, "id24"], [7, "id26"], [7, "id28"], [7, "id30"], [7, "id4"], [7, "id6"], [7, "id8"]], "_msg_type_to_name (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._msg_type_to_name"], [7, "id1"], [7, "id11"], [7, "id13"], [7, "id15"], [7, "id17"], [7, "id19"], [7, "id21"], [7, "id23"], [7, "id25"], [7, "id27"], [7, "id29"], [7, "id3"], [7, "id31"], [7, "id5"], [7, "id7"], [7, "id9"]], "_sym_db (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._sym_db"]], "datafed.sdms_anon_pb2": [[7, "module-datafed.SDMS_Anon_pb2"]], "acldatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.ACLDataReply"]], "aclsharedlistitemsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.ACLSharedListItemsRequest"]], "aclsharedlistrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.ACLSharedListRequest"]], "aclupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.ACLUpdateRequest"]], "aclviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.ACLViewRequest"]], "checkpermsreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.CheckPermsReply"]], "checkpermsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.CheckPermsRequest"]], "collcreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.CollCreateRequest"]], "colldatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.CollDataReply"]], "colldeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.CollDeleteRequest"]], "collgetoffsetreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.CollGetOffsetReply"]], "collgetoffsetrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.CollGetOffsetRequest"]], "collgetparentsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.CollGetParentsRequest"]], "colllistpublishedrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.CollListPublishedRequest"]], "collmoverequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.CollMoveRequest"]], "collpathreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.CollPathReply"]], "collreadrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.CollReadRequest"]], "collupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.CollUpdateRequest"]], "collviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.CollViewRequest"]], "collwriterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.CollWriteRequest"]], "descriptor (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.DESCRIPTOR"]], "datadeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.DataDeleteRequest"]], "datagetreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.DataGetReply"]], "datagetrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.DataGetRequest"]], "datapathreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.DataPathReply"]], "datapathrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.DataPathRequest"]], "dataputreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.DataPutReply"]], "dataputrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.DataPutRequest"]], "generatecredentialsreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.GenerateCredentialsReply"]], "generatecredentialsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.GenerateCredentialsRequest"]], "getpermsreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.GetPermsReply"]], "getpermsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.GetPermsRequest"]], "groupcreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.GroupCreateRequest"]], "groupdatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.GroupDataReply"]], "groupdeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.GroupDeleteRequest"]], "grouplistrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.GroupListRequest"]], "groupupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.GroupUpdateRequest"]], "groupviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.GroupViewRequest"]], "id (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.ID"]], "listingreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.ListingReply"]], "metadatavalidatereply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.MetadataValidateReply"]], "metadatavalidaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.MetadataValidateRequest"]], "notecommenteditrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.NoteCommentEditRequest"]], "notecreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.NoteCreateRequest"]], "notedatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.NoteDataReply"]], "notelistbysubjectrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.NoteListBySubjectRequest"]], "noteupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.NoteUpdateRequest"]], "noteviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.NoteViewRequest"]], "projectcreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.ProjectCreateRequest"]], "projectdatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.ProjectDataReply"]], "projectdeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.ProjectDeleteRequest"]], "projectgetrolereply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.ProjectGetRoleReply"]], "projectgetrolerequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.ProjectGetRoleRequest"]], "projectlistrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.ProjectListRequest"]], "projectsearchrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.ProjectSearchRequest"]], "projectupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.ProjectUpdateRequest"]], "projectviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.ProjectViewRequest"]], "protocol (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.Protocol"]], "querycreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.QueryCreateRequest"]], "querydatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.QueryDataReply"]], "querydeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.QueryDeleteRequest"]], "queryexecrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.QueryExecRequest"]], "querylistrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.QueryListRequest"]], "queryupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.QueryUpdateRequest"]], "queryviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.QueryViewRequest"]], "recordallocchangereply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RecordAllocChangeReply"]], "recordallocchangerequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RecordAllocChangeRequest"]], "recordcreatebatchrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RecordCreateBatchRequest"]], "recordcreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RecordCreateRequest"]], "recorddatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RecordDataReply"]], "recorddeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RecordDeleteRequest"]], "recordexportreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RecordExportReply"]], "recordexportrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RecordExportRequest"]], "recordgetdependencygraphrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RecordGetDependencyGraphRequest"]], "recordlistbyallocrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RecordListByAllocRequest"]], "recordlockrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RecordLockRequest"]], "recordownerchangereply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RecordOwnerChangeReply"]], "recordownerchangerequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RecordOwnerChangeRequest"]], "recordupdatebatchrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RecordUpdateBatchRequest"]], "recordupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RecordUpdateRequest"]], "recordviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RecordViewRequest"]], "repoallocationcreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoAllocationCreateRequest"]], "repoallocationdeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoAllocationDeleteRequest"]], "repoallocationsetdefaultrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoAllocationSetDefaultRequest"]], "repoallocationsetrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoAllocationSetRequest"]], "repoallocationstatsreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoAllocationStatsReply"]], "repoallocationstatsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoAllocationStatsRequest"]], "repoallocationsreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoAllocationsReply"]], "repoauthzrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoAuthzRequest"]], "repocalcsizereply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoCalcSizeReply"]], "repocalcsizerequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoCalcSizeRequest"]], "repocreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoCreateRequest"]], "repodatadeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoDataDeleteRequest"]], "repodatagetsizerequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoDataGetSizeRequest"]], "repodatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoDataReply"]], "repodatasizereply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoDataSizeReply"]], "repodeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoDeleteRequest"]], "repolistallocationsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoListAllocationsRequest"]], "repolistobjectallocationsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoListObjectAllocationsRequest"]], "repolistrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoListRequest"]], "repolistsubjectallocationsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoListSubjectAllocationsRequest"]], "repopathcreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoPathCreateRequest"]], "repopathdeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoPathDeleteRequest"]], "repoupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoUpdateRequest"]], "repoviewallocationrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoViewAllocationRequest"]], "repoviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RepoViewRequest"]], "revokecredentialsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.RevokeCredentialsRequest"]], "schemacreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.SchemaCreateRequest"]], "schemadatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.SchemaDataReply"]], "schemadeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.SchemaDeleteRequest"]], "schemareviserequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.SchemaReviseRequest"]], "schemasearchrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.SchemaSearchRequest"]], "schemaupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.SchemaUpdateRequest"]], "schemaviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.SchemaViewRequest"]], "searchrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.SearchRequest"]], "tagdatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.TagDataReply"]], "taglistbycountrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.TagListByCountRequest"]], "tagsearchrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.TagSearchRequest"]], "taskdatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.TaskDataReply"]], "tasklistrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.TaskListRequest"]], "taskviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.TaskViewRequest"]], "topicdatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.TopicDataReply"]], "topiclisttopicsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.TopicListTopicsRequest"]], "topicsearchrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.TopicSearchRequest"]], "topicviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.TopicViewRequest"]], "useraccesstokenreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.UserAccessTokenReply"]], "usercreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.UserCreateRequest"]], "userdatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.UserDataReply"]], "userfindbynameuidrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.UserFindByNameUIDRequest"]], "userfindbyuuidsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.UserFindByUUIDsRequest"]], "usergetaccesstokenrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.UserGetAccessTokenRequest"]], "usergetrecentepreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.UserGetRecentEPReply"]], "usergetrecenteprequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.UserGetRecentEPRequest"]], "userlistallrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.UserListAllRequest"]], "userlistcollabrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.UserListCollabRequest"]], "usersetaccesstokenrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.UserSetAccessTokenRequest"]], "usersetrecenteprequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.UserSetRecentEPRequest"]], "userupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.UserUpdateRequest"]], "userviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.UserViewRequest"]], "_acldatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._ACLDATAREPLY"]], "_aclsharedlistitemsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._ACLSHAREDLISTITEMSREQUEST"]], "_aclsharedlistrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._ACLSHAREDLISTREQUEST"]], "_aclupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._ACLUPDATEREQUEST"]], "_aclviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._ACLVIEWREQUEST"]], "_checkpermsreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._CHECKPERMSREPLY"]], "_checkpermsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._CHECKPERMSREQUEST"]], "_collcreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._COLLCREATEREQUEST"]], "_colldatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._COLLDATAREPLY"]], "_colldeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._COLLDELETEREQUEST"]], "_collgetoffsetreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._COLLGETOFFSETREPLY"]], "_collgetoffsetrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._COLLGETOFFSETREQUEST"]], "_collgetparentsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._COLLGETPARENTSREQUEST"]], "_colllistpublishedrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._COLLLISTPUBLISHEDREQUEST"]], "_collmoverequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._COLLMOVEREQUEST"]], "_collpathreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._COLLPATHREPLY"]], "_collreadrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._COLLREADREQUEST"]], "_collupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._COLLUPDATEREQUEST"]], "_collviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._COLLVIEWREQUEST"]], "_collwriterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._COLLWRITEREQUEST"]], "_datadeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._DATADELETEREQUEST"]], "_datagetreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._DATAGETREPLY"]], "_datagetrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._DATAGETREQUEST"]], "_datapathreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._DATAPATHREPLY"]], "_datapathrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._DATAPATHREQUEST"]], "_dataputreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._DATAPUTREPLY"]], "_dataputrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._DATAPUTREQUEST"]], "_generatecredentialsreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._GENERATECREDENTIALSREPLY"]], "_generatecredentialsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._GENERATECREDENTIALSREQUEST"]], "_getpermsreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._GETPERMSREPLY"]], "_getpermsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._GETPERMSREQUEST"]], "_groupcreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._GROUPCREATEREQUEST"]], "_groupdatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._GROUPDATAREPLY"]], "_groupdeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._GROUPDELETEREQUEST"]], "_grouplistrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._GROUPLISTREQUEST"]], "_groupupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._GROUPUPDATEREQUEST"]], "_groupviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._GROUPVIEWREQUEST"]], "_listingreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._LISTINGREPLY"]], "_metadatavalidatereply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._METADATAVALIDATEREPLY"]], "_metadatavalidaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._METADATAVALIDATEREQUEST"]], "_notecommenteditrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._NOTECOMMENTEDITREQUEST"]], "_notecreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._NOTECREATEREQUEST"]], "_notedatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._NOTEDATAREPLY"]], "_notelistbysubjectrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._NOTELISTBYSUBJECTREQUEST"]], "_noteupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._NOTEUPDATEREQUEST"]], "_noteviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._NOTEVIEWREQUEST"]], "_projectcreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._PROJECTCREATEREQUEST"]], "_projectdatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._PROJECTDATAREPLY"]], "_projectdeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._PROJECTDELETEREQUEST"]], "_projectgetrolereply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._PROJECTGETROLEREPLY"]], "_projectgetrolerequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._PROJECTGETROLEREQUEST"]], "_projectlistrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._PROJECTLISTREQUEST"]], "_projectsearchrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._PROJECTSEARCHREQUEST"]], "_projectupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._PROJECTUPDATEREQUEST"]], "_projectviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._PROJECTVIEWREQUEST"]], "_protocol (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._PROTOCOL"]], "_querycreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._QUERYCREATEREQUEST"]], "_querydatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._QUERYDATAREPLY"]], "_querydeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._QUERYDELETEREQUEST"]], "_queryexecrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._QUERYEXECREQUEST"]], "_querylistrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._QUERYLISTREQUEST"]], "_queryupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._QUERYUPDATEREQUEST"]], "_queryviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._QUERYVIEWREQUEST"]], "_recordallocchangereply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._RECORDALLOCCHANGEREPLY"]], "_recordallocchangerequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._RECORDALLOCCHANGEREQUEST"]], "_recordcreatebatchrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._RECORDCREATEBATCHREQUEST"]], "_recordcreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._RECORDCREATEREQUEST"]], "_recorddatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._RECORDDATAREPLY"]], "_recorddeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._RECORDDELETEREQUEST"]], "_recordexportreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._RECORDEXPORTREPLY"]], "_recordexportrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._RECORDEXPORTREQUEST"]], "_recordgetdependencygraphrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._RECORDGETDEPENDENCYGRAPHREQUEST"]], "_recordlistbyallocrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._RECORDLISTBYALLOCREQUEST"]], "_recordlockrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._RECORDLOCKREQUEST"]], "_recordownerchangereply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._RECORDOWNERCHANGEREPLY"]], "_recordownerchangerequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._RECORDOWNERCHANGEREQUEST"]], "_recordupdatebatchrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._RECORDUPDATEBATCHREQUEST"]], "_recordupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._RECORDUPDATEREQUEST"]], "_recordviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._RECORDVIEWREQUEST"]], "_repoallocationcreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOALLOCATIONCREATEREQUEST"]], "_repoallocationdeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOALLOCATIONDELETEREQUEST"]], "_repoallocationsetdefaultrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOALLOCATIONSETDEFAULTREQUEST"]], "_repoallocationsetrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOALLOCATIONSETREQUEST"]], "_repoallocationsreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOALLOCATIONSREPLY"]], "_repoallocationstatsreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOALLOCATIONSTATSREPLY"]], "_repoallocationstatsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOALLOCATIONSTATSREQUEST"]], "_repoauthzrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOAUTHZREQUEST"]], "_repocalcsizereply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOCALCSIZEREPLY"]], "_repocalcsizerequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOCALCSIZEREQUEST"]], "_repocreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOCREATEREQUEST"]], "_repodatadeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPODATADELETEREQUEST"]], "_repodatagetsizerequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPODATAGETSIZEREQUEST"]], "_repodatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPODATAREPLY"]], "_repodatasizereply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPODATASIZEREPLY"]], "_repodeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPODELETEREQUEST"]], "_repolistallocationsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOLISTALLOCATIONSREQUEST"]], "_repolistobjectallocationsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOLISTOBJECTALLOCATIONSREQUEST"]], "_repolistrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOLISTREQUEST"]], "_repolistsubjectallocationsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOLISTSUBJECTALLOCATIONSREQUEST"]], "_repopathcreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOPATHCREATEREQUEST"]], "_repopathdeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOPATHDELETEREQUEST"]], "_repoupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOUPDATEREQUEST"]], "_repoviewallocationrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOVIEWALLOCATIONREQUEST"]], "_repoviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REPOVIEWREQUEST"]], "_revokecredentialsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._REVOKECREDENTIALSREQUEST"]], "_schemacreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._SCHEMACREATEREQUEST"]], "_schemadatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._SCHEMADATAREPLY"]], "_schemadeleterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._SCHEMADELETEREQUEST"]], "_schemareviserequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._SCHEMAREVISEREQUEST"]], "_schemasearchrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._SCHEMASEARCHREQUEST"]], "_schemaupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._SCHEMAUPDATEREQUEST"]], "_schemaviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._SCHEMAVIEWREQUEST"]], "_searchrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._SEARCHREQUEST"]], "_tagdatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._TAGDATAREPLY"]], "_taglistbycountrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._TAGLISTBYCOUNTREQUEST"]], "_tagsearchrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._TAGSEARCHREQUEST"]], "_taskdatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._TASKDATAREPLY"]], "_tasklistrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._TASKLISTREQUEST"]], "_taskviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._TASKVIEWREQUEST"]], "_topicdatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._TOPICDATAREPLY"]], "_topiclisttopicsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._TOPICLISTTOPICSREQUEST"]], "_topicsearchrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._TOPICSEARCHREQUEST"]], "_topicviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._TOPICVIEWREQUEST"]], "_useraccesstokenreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._USERACCESSTOKENREPLY"]], "_usercreaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._USERCREATEREQUEST"]], "_userdatareply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._USERDATAREPLY"]], "_userfindbynameuidrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._USERFINDBYNAMEUIDREQUEST"]], "_userfindbyuuidsrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._USERFINDBYUUIDSREQUEST"]], "_usergetaccesstokenrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._USERGETACCESSTOKENREQUEST"]], "_usergetrecentepreply (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._USERGETRECENTEPREPLY"]], "_usergetrecenteprequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._USERGETRECENTEPREQUEST"]], "_userlistallrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._USERLISTALLREQUEST"]], "_userlistcollabrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._USERLISTCOLLABREQUEST"]], "_usersetaccesstokenrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._USERSETACCESSTOKENREQUEST"]], "_usersetrecenteprequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._USERSETRECENTEPREQUEST"]], "_userupdaterequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._USERUPDATEREQUEST"]], "_userviewrequest (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._USERVIEWREQUEST"]], "_msg_name_to_type (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._msg_name_to_type"], [8, "id0"], [8, "id10"], [8, "id12"], [8, "id14"], [8, "id16"], [8, "id18"], [8, "id2"], [8, "id20"], [8, "id22"], [8, "id24"], [8, "id26"], [8, "id28"], [8, "id30"], [8, "id4"], [8, "id6"], [8, "id8"]], "_msg_type_to_name (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._msg_type_to_name"], [8, "id1"], [8, "id11"], [8, "id13"], [8, "id15"], [8, "id17"], [8, "id19"], [8, "id21"], [8, "id23"], [8, "id25"], [8, "id27"], [8, "id29"], [8, "id3"], [8, "id31"], [8, "id5"], [8, "id7"], [8, "id9"]], "_sym_db (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._sym_db"]], "datafed.sdms_auth_pb2": [[8, "module-datafed.SDMS_Auth_pb2"]], "aclrule (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ACLRule"]], "allocdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.AllocData"]], "allocstatsdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.AllocStatsData"]], "colldata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.CollData"]], "dep_in (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DEP_IN"]], "dep_is_component_of (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DEP_IS_COMPONENT_OF"]], "dep_is_derived_from (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DEP_IS_DERIVED_FROM"]], "dep_is_new_version_of (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DEP_IS_NEW_VERSION_OF"]], "dep_out (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DEP_OUT"]], "dep_type_count (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DEP_TYPE_COUNT"]], "descriptor (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DESCRIPTOR"]], "dependencydata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DependencyData"]], "dependencydir (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DependencyDir"]], "dependencyspecdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DependencySpecData"]], "dependencytype (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DependencyType"]], "encrypt_avail (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ENCRYPT_AVAIL"]], "encrypt_force (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ENCRYPT_FORCE"]], "encrypt_none (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ENCRYPT_NONE"]], "encryption (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.Encryption"]], "errorcode (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ErrorCode"]], "groupdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.GroupData"]], "id_authn_error (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ID_AUTHN_ERROR"]], "id_authn_required (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ID_AUTHN_REQUIRED"]], "id_bad_request (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ID_BAD_REQUEST"]], "id_client_error (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ID_CLIENT_ERROR"]], "id_dest_file_error (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ID_DEST_FILE_ERROR"]], "id_dest_path_error (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ID_DEST_PATH_ERROR"]], "id_internal_error (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ID_INTERNAL_ERROR"]], "id_service_error (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ID_SERVICE_ERROR"]], "listingdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ListingData"]], "note_active (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NOTE_ACTIVE"]], "note_closed (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NOTE_CLOSED"]], "note_error (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NOTE_ERROR"]], "note_info (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NOTE_INFO"]], "note_open (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NOTE_OPEN"]], "note_question (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NOTE_QUESTION"]], "note_warn (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NOTE_WARN"]], "notecomment (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NoteComment"]], "notedata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NoteData"]], "notestate (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NoteState"]], "notetype (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NoteType"]], "proj_admin (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.PROJ_ADMIN"]], "proj_manager (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.PROJ_MANAGER"]], "proj_member (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.PROJ_MEMBER"]], "proj_no_role (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.PROJ_NO_ROLE"]], "pathdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.PathData"]], "projectdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ProjectData"]], "projectrole (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ProjectRole"]], "recorddata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.RecordData"]], "recorddatalocation (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.RecordDataLocation"]], "recorddatasize (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.RecordDataSize"]], "repodata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.RepoData"]], "reporecorddatalocations (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.RepoRecordDataLocations"]], "sm_collection (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SM_COLLECTION"]], "sm_data (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SM_DATA"]], "sort_id (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SORT_ID"]], "sort_owner (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SORT_OWNER"]], "sort_relevance (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SORT_RELEVANCE"]], "sort_time_create (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SORT_TIME_CREATE"]], "sort_time_update (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SORT_TIME_UPDATE"]], "sort_title (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SORT_TITLE"]], "ss_degraded (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SS_DEGRADED"]], "ss_failed (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SS_FAILED"]], "ss_normal (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SS_NORMAL"]], "ss_offline (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SS_OFFLINE"]], "schemadata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SchemaData"]], "searchmode (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SearchMode"]], "servicestatus (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ServiceStatus"]], "sortoption (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SortOption"]], "tc_alloc_create (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TC_ALLOC_CREATE"]], "tc_alloc_delete (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TC_ALLOC_DELETE"]], "tc_raw_data_delete (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TC_RAW_DATA_DELETE"]], "tc_raw_data_transfer (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TC_RAW_DATA_TRANSFER"]], "tc_raw_data_update_size (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TC_RAW_DATA_UPDATE_SIZE"]], "tc_stop (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TC_STOP"]], "ts_blocked (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TS_BLOCKED"]], "ts_failed (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TS_FAILED"]], "ts_ready (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TS_READY"]], "ts_running (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TS_RUNNING"]], "ts_succeeded (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TS_SUCCEEDED"]], "tt_alloc_create (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_ALLOC_CREATE"]], "tt_alloc_del (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_ALLOC_DEL"]], "tt_data_del (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_DATA_DEL"]], "tt_data_get (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_DATA_GET"]], "tt_data_put (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_DATA_PUT"]], "tt_proj_del (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_PROJ_DEL"]], "tt_rec_chg_alloc (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_REC_CHG_ALLOC"]], "tt_rec_chg_owner (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_REC_CHG_OWNER"]], "tt_rec_del (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_REC_DEL"]], "tt_user_del (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_USER_DEL"]], "tagdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TagData"]], "taskcommand (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TaskCommand"]], "taskdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TaskData"]], "taskstatus (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TaskStatus"]], "tasktype (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TaskType"]], "topicdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TopicData"]], "userdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.UserData"]], "_aclrule (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._ACLRULE"]], "_allocdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._ALLOCDATA"]], "_allocstatsdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._ALLOCSTATSDATA"]], "_colldata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._COLLDATA"]], "_dependencydata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._DEPENDENCYDATA"]], "_dependencydir (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._DEPENDENCYDIR"]], "_dependencyspecdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._DEPENDENCYSPECDATA"]], "_dependencytype (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._DEPENDENCYTYPE"]], "_encryption (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._ENCRYPTION"]], "_errorcode (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._ERRORCODE"]], "_groupdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._GROUPDATA"]], "_listingdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._LISTINGDATA"]], "_notecomment (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._NOTECOMMENT"]], "_notedata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._NOTEDATA"]], "_notestate (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._NOTESTATE"]], "_notetype (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._NOTETYPE"]], "_pathdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._PATHDATA"]], "_projectdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._PROJECTDATA"]], "_projectrole (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._PROJECTROLE"]], "_recorddata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._RECORDDATA"]], "_recorddatalocation (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._RECORDDATALOCATION"]], "_recorddatasize (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._RECORDDATASIZE"]], "_repodata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._REPODATA"]], "_reporecorddatalocations (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._REPORECORDDATALOCATIONS"]], "_schemadata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._SCHEMADATA"]], "_searchmode (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._SEARCHMODE"]], "_servicestatus (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._SERVICESTATUS"]], "_sortoption (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._SORTOPTION"]], "_tagdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._TAGDATA"]], "_taskcommand (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._TASKCOMMAND"]], "_taskdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._TASKDATA"]], "_taskstatus (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._TASKSTATUS"]], "_tasktype (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._TASKTYPE"]], "_topicdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._TOPICDATA"]], "_userdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._USERDATA"]], "_sym_db (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._sym_db"]], "datafed.sdms_pb2": [[9, "module-datafed.SDMS_pb2"]], "__version__ (in module datafed.version)": [[10, "datafed.VERSION.__version__"]], "datafed.version": [[10, "module-datafed.VERSION"]], "datafed_common_protocol_api_major (in module datafed.version_pb2)": [[11, "datafed.Version_pb2.DATAFED_COMMON_PROTOCOL_API_MAJOR"]], "datafed_common_protocol_api_minor (in module datafed.version_pb2)": [[11, "datafed.Version_pb2.DATAFED_COMMON_PROTOCOL_API_MINOR"]], "datafed_common_protocol_api_patch (in module datafed.version_pb2)": [[11, "datafed.Version_pb2.DATAFED_COMMON_PROTOCOL_API_PATCH"]], "datafed_release_day (in module datafed.version_pb2)": [[11, "datafed.Version_pb2.DATAFED_RELEASE_DAY"]], "datafed_release_hour (in module datafed.version_pb2)": [[11, "datafed.Version_pb2.DATAFED_RELEASE_HOUR"]], "datafed_release_minute (in module datafed.version_pb2)": [[11, "datafed.Version_pb2.DATAFED_RELEASE_MINUTE"]], "datafed_release_month (in module datafed.version_pb2)": [[11, "datafed.Version_pb2.DATAFED_RELEASE_MONTH"]], "datafed_release_year (in module datafed.version_pb2)": [[11, "datafed.Version_pb2.DATAFED_RELEASE_YEAR"]], "descriptor (in module datafed.version_pb2)": [[11, "datafed.Version_pb2.DESCRIPTOR"]], "version (in module datafed.version_pb2)": [[11, "datafed.Version_pb2.Version"]], "_version (in module datafed.version_pb2)": [[11, "datafed.Version_pb2._VERSION"]], "_sym_db (in module datafed.version_pb2)": [[11, "datafed.Version_pb2._sym_db"]], "datafed.version_pb2": [[11, "module-datafed.Version_pb2"]], "datafed": [[12, "module-datafed"]], "name (in module datafed)": [[12, "datafed.name"]], "version (in module datafed)": [[12, "datafed.version"]]}}) \ No newline at end of file +Search.setIndex({ + docnames: [ + "_generated/cli_python_cmd_ref", + "admin/general", + "autoapi/datafed/CLI/index", + "autoapi/datafed/CommandLib/index", + "autoapi/datafed/Config/index", + "autoapi/datafed/Connection/index", + "autoapi/datafed/MessageLib/index", + "autoapi/datafed/SDMS_Anon_pb2/index", + "autoapi/datafed/SDMS_Auth_pb2/index", + "autoapi/datafed/SDMS_pb2/index", + "autoapi/datafed/VERSION/index", + "autoapi/datafed/Version_pb2/index", + "autoapi/datafed/index", + "autoapi/index", + "dev/design", + "dev/project", + "dev/release", + "dev/roadmap", + "index", + "system/getting_started", + "system/introduction", + "system/overview", + "system/papers", + "system/usecases", + "user/cli/guide", + "user/cli/header", + "user/cli/reference", + "user/client/install", + "user/python/high_level_guide", + "user/python/notebooks", + "user/web/portal", + ], + filenames: [ + "_generated/cli_python_cmd_ref.rst", + "admin/general.rst", + "autoapi/datafed/CLI/index.rst", + "autoapi/datafed/CommandLib/index.rst", + "autoapi/datafed/Config/index.rst", + "autoapi/datafed/Connection/index.rst", + "autoapi/datafed/MessageLib/index.rst", + "autoapi/datafed/SDMS_Anon_pb2/index.rst", + "autoapi/datafed/SDMS_Auth_pb2/index.rst", + "autoapi/datafed/SDMS_pb2/index.rst", + "autoapi/datafed/VERSION/index.rst", + "autoapi/datafed/Version_pb2/index.rst", + "autoapi/datafed/index.rst", + "autoapi/index.rst", + "dev/design.rst", + "dev/project.rst", + "dev/release.rst", + "dev/roadmap.rst", + "index.rst", + "system/getting_started.rst", + "system/introduction.rst", + "system/overview.rst", + "system/papers.rst", + "system/usecases.rst", + "user/cli/guide.rst", + "user/cli/header.rst", + "user/cli/reference.rst", + "user/client/install.rst", + "user/python/high_level_guide.rst", + "user/python/notebooks.rst", + "user/web/portal.rst", + ], + titles: [ + "Datafed Commands", + "Administration", + 'datafed.CLI', + 'datafed.CommandLib', + 'datafed.Config', + 'datafed.Connection', + 'datafed.MessageLib', + 'datafed.SDMS_Anon_pb2', + 'datafed.SDMS_Auth_pb2', + 'datafed.SDMS_pb2', + 'datafed.VERSION', + 'datafed.Version_pb2', + 'datafed', + "API Reference", + "Architecture & Design", + "Project Management", + "Release Notes", + "Feature Road Map", + "DataFed - A Scientific Data Federation", + "Getting Started", + "Introduction", + "System Overview", + "Papers and Presentations", + "Use Cases", + "User Guide", + "<no title>", + "Command Reference", + "Installation and Configuration", + "Guide to High Level Interface", + "Jupyter Notebooks", + "Web Portal Guide", + ], + terms: { + i: [0, 1, 2, 3, 15, 16, 18, 19, 20, 21, 24, 25, 26, 28, 29, 30], + line: [0, 2, 19, 21, 24, 25, 26, 27, 28], + interfac: [0, 2, 3, 15, 16, 17, 20, 24, 25, 26, 27, 29, 30], + cli: [0, 3, 12, 13, 16, 17, 19, 21, 24, 25, 26, 27, 28, 30], + feder: [0, 2, 20, 21, 26], + manag: [0, 2, 3, 16, 17, 18, 19, 22, 24, 26, 30], + servic: [0, 2, 17, 20, 21, 26], + mai: [0, 1, 2, 3, 18, 19, 20, 21, 24, 26, 27, 28, 30], + us: [0, 1, 2, 3, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 30], + access: [0, 1, 2, 16, 17, 19, 20, 24, 25, 26, 27, 28, 30], + mani: [0, 2, 16, 20, 21, 26, 27, 28], + featur: [0, 2, 18, 19, 20, 21, 24, 26, 27, 30], + avail: [0, 2, 3, 16, 19, 20, 21, 24, 25, 26, 27, 28, 30], + via: [0, 1, 2, 3, 16, 19, 20, 21, 24, 25, 26, 27, 28, 30], + web: [0, 2, 16, 17, 19, 21, 26, 27, 28], + portal: [0, 2, 16, 17, 19, 21, 26, 27], + thi: [0, 1, 2, 3, 13, 16, 18, 19, 20, 21, 23, 24, 26, 27, 28, 30], + interact: [0, 1, 2, 21, 24, 25, 26, 27], + human: [0, 2, 3, 21, 24, 26, 28], + friendli: [0, 2, 21, 24, 26, 28], + output: [0, 2, 21, 24, 26, 28], + script: [0, 1, 2, 16, 19, 21, 24, 25, 26, 27, 28], + json: [0, 2, 3, 16, 21, 24, 26, 28], + specifi: [0, 2, 3, 21, 24, 26, 27, 28, 30], + "": [0, 1, 2, 3, 19, 20, 21, 24, 26, 27, 28, 30], + option: [0, 1, 2, 3, 16, 19, 21, 24, 26, 27, 28, 30], + when: [0, 2, 3, 16, 19, 21, 24, 26, 27, 28, 30], + without: [0, 2, 3, 16, 20, 21, 24, 26, 28, 30], + ani: [0, 2, 3, 16, 19, 20, 21, 24, 25, 26, 27, 28, 30], + argument: [0, 2, 3, 24, 26, 28], + shell: [0, 2, 24, 25, 26, 27], + session: [0, 1, 2, 24, 26, 28], + start: [0, 1, 2, 3, 16, 18, 20, 21, 24, 26, 27], + while: [0, 2, 20, 21, 26, 28, 30], + should: [0, 1, 2, 3, 16, 19, 21, 26, 27, 28, 30], + enter: [0, 1, 2, 3, 16, 19, 21, 24, 26, 27, 28], + prefix: [0, 2, 3, 21, 26, 27, 28], + usag: [0, 16, 24, 26, 28], + arg: [0, 2, 24, 26], + descript: [0, 1, 2, 3, 19, 21, 24, 26, 30], + m: [0, 3, 24, 26], + manual: [0, 1, 2, 3, 21, 26, 27, 30], + auth: [0, 16, 26], + forc: [0, 2, 3, 26], + authent: [0, 2, 3, 17, 19, 20, 21, 24, 26, 28, 30], + non: [0, 2, 16, 17, 24, 25, 26, 27], + mode: [0, 2, 3, 16, 24, 26, 28], + intermedi: [0, 26], + o: [0, 26, 27, 28], + disabl: [0, 26, 27, 30], + certain: [0, 21, 24, 26], + client: [0, 1, 2, 3, 16, 17, 19, 21, 24, 26, 28], + side: [0, 16, 21, 26, 27, 30], + ar: [0, 1, 2, 3, 16, 18, 19, 20, 21, 24, 26, 27, 28, 30], + unavail: [0, 26], + version: [0, 1, 2, 3, 11, 12, 13, 16, 21, 24, 26, 28], + print: [0, 2, 24, 26, 28], + number: [0, 3, 16, 20, 21, 24, 26, 27, 28, 30], + server: [0, 1, 2, 3, 17, 21, 24, 26, 28], + cfg: [0, 1, 26, 27], + dir: [0, 1, 24, 26, 27, 28], + text: [0, 2, 3, 21, 24, 26, 28], + configur: [0, 2, 3, 17, 18, 19, 20, 21, 24, 26, 28, 29, 30], + directori: [0, 2, 3, 17, 21, 24, 26, 28], + file: [0, 1, 2, 3, 16, 17, 19, 20, 21, 24, 26, 28], + pub: [0, 26, 27], + kei: [0, 1, 3, 4, 18, 21, 24, 26, 28, 30], + public: [0, 1, 2, 3, 20, 26], + h: [0, 3, 24, 26, 27], + host: [0, 1, 15, 16, 19, 20, 21, 24, 26], + sever: [0, 1, 21, 24, 26, 27, 28], + name: [0, 1, 2, 3, 12, 16, 19, 21, 24, 26, 27, 28, 30], + ip: [0, 1, 26, 27], + address: [0, 1, 3, 18, 20, 26, 27, 28, 30], + p: [0, 21, 24, 26, 27, 28], + port: [0, 1, 3, 26], + integ: [0, 3, 26, 28], + priv: [0, 26, 27], + privat: [0, 1, 3, 21, 26, 28], + e: [0, 3, 16, 19, 20, 21, 26, 27, 28, 30], + globu: [0, 1, 2, 3, 16, 17, 18, 20, 21, 24, 26, 27, 28, 30], + endpoint: [0, 2, 3, 16, 17, 18, 20, 21, 24, 26, 28], + v: [0, 24, 26], + level: [0, 2, 3, 18, 21, 24, 26, 29], + 0: [0, 1, 2, 3, 9, 10, 11, 18, 21, 24, 26, 28], + quiet: [0, 26], + 1: [0, 1, 2, 3, 4, 7, 9, 13, 18, 20, 21, 24, 26, 28, 30], + normal: [0, 2, 16, 21, 24, 26], + 2: [0, 2, 4, 8, 9, 10, 18, 20, 21, 24, 26, 28], + format: [0, 3, 20, 21, 24, 26, 27, 28], + onli: [0, 1, 2, 3, 19, 20, 21, 24, 26, 27, 28, 30], + show: [0, 2, 16, 19, 21, 24, 26, 28, 30], + messag: [0, 2, 3, 5, 16, 21, 24, 26, 27, 30], + sub: [0, 21, 24, 26, 28], + collect: [0, 1, 2, 3, 16, 18, 24, 26, 29, 30], + an: [0, 1, 2, 3, 15, 16, 18, 19, 20, 21, 24, 26, 27, 28, 29, 30], + content: [0, 21, 24, 26], + item: [0, 2, 3, 21, 24, 26, 30], + local: [0, 1, 2, 3, 16, 20, 21, 24, 26, 27, 28, 30], + credenti: [0, 2, 3, 19, 26, 27, 28, 30], + current: [0, 2, 3, 16, 17, 20, 21, 24, 26, 27, 28, 30], + displai: [0, 2, 16, 21, 26, 28, 30], + work: [0, 2, 16, 17, 18, 20, 21, 24, 26], + path: [0, 1, 2, 3, 16, 19, 21, 24, 26, 28], + record: [0, 2, 3, 16, 17, 18, 20, 26, 29, 30], + new: [0, 2, 3, 18, 20, 21, 24, 26, 28, 30], + one: [0, 1, 2, 3, 16, 19, 21, 24, 26, 27, 28, 30], + more: [0, 2, 3, 16, 21, 23, 24, 26, 28], + exist: [0, 1, 2, 3, 20, 21, 24, 26, 27, 28], + from: [0, 1, 2, 3, 16, 17, 19, 20, 21, 24, 25, 26, 27, 29, 30], + inform: [0, 1, 2, 3, 18, 19, 20, 21, 24, 26], + coll_id: [0, 2, 3, 26, 28], + destin: [0, 2, 3, 16, 19, 21, 26, 28], + item_id: [0, 2, 3, 26], + id: [0, 1, 2, 3, 7, 8, 16, 18, 21, 24, 26, 27], + alias: [0, 2, 3, 16, 18, 24, 26], + index: [0, 2, 17, 18, 20, 21, 24, 26], + valu: [0, 2, 3, 4, 16, 21, 24, 26, 27, 28], + also: [0, 1, 2, 3, 16, 19, 20, 21, 24, 26, 27, 28], + rel: [0, 2, 3, 26, 28], + x: [0, 24, 26, 28], + context: [0, 2, 3, 18, 19, 20, 21, 24, 26, 30], + alia: [0, 2, 3, 21, 24, 26], + see: [0, 1, 2, 3, 19, 21, 23, 24, 26, 27, 28], + The: [0, 1, 2, 3, 16, 18, 19, 20, 21, 24, 25, 26, 27, 28, 30], + titl: [0, 2, 3, 19, 21, 24, 26, 28, 30], + requir: [0, 1, 2, 3, 15, 16, 17, 19, 20, 21, 24, 26, 27, 28, 30], + other: [0, 2, 3, 20, 21, 24, 26, 27, 30], + attribut: [0, 21, 24, 26], + On: [0, 2, 3, 20, 24, 26, 27], + success: [0, 2, 3, 21, 24, 26, 28], + return: [0, 2, 16, 24, 26, 28, 30], + note: [0, 1, 2, 3, 18, 19, 20, 21, 24, 26, 27, 28, 30], + parent: [0, 2, 3, 16, 21, 24, 26, 30], + belong: [0, 2, 24, 26, 28], + collabor: [0, 2, 3, 18, 19, 20, 21, 24, 26, 28], + must: [0, 1, 2, 3, 16, 19, 21, 24, 26, 27, 28, 30], + have: [0, 1, 2, 3, 19, 20, 21, 24, 26, 27, 28, 30], + permiss: [0, 2, 16, 21, 24, 26, 28, 30], + write: [0, 2, 21, 24, 26, 27, 28], + d: [0, 3, 21, 24, 26, 28], + t: [0, 2, 3, 16, 24, 26, 28], + tag: [0, 2, 3, 16, 24, 26], + comma: [0, 24, 26], + separ: [0, 2, 3, 16, 21, 24, 26, 28], + topic: [0, 2, 3, 16, 21, 24, 26, 28], + publish: [0, 16, 17, 18, 20, 21, 24, 26], + provid: [0, 1, 2, 3, 16, 17, 18, 19, 20, 21, 24, 25, 26, 27, 28], + multipl: [0, 1, 2, 16, 20, 21, 24, 26, 28], + can: [0, 1, 2, 3, 16, 17, 18, 19, 20, 21, 24, 25, 26, 27, 28, 30], + By: [0, 2, 3, 26, 28, 30], + confirm: [0, 2, 26, 28], + prompt: [0, 2, 19, 24, 26, 27], + bypass: [0, 2, 16, 26], + contain: [0, 1, 2, 3, 13, 16, 18, 20, 21, 24, 26, 27, 28, 30], + howev: [0, 2, 3, 16, 19, 20, 21, 24, 26, 27, 28], + thei: [0, 1, 2, 3, 19, 21, 24, 26, 27, 28, 30], + link: [0, 2, 3, 16, 17, 19, 20, 21, 26, 27, 28, 30], + anoth: [0, 2, 3, 19, 21, 24, 26, 28, 30], + involv: [0, 2, 3, 21, 24, 26], + f: [0, 24, 26], + under: [0, 3, 16, 20, 21, 26, 28, 30], + administr: [0, 2, 17, 19, 21, 26, 27, 28, 30], + field: [0, 2, 3, 16, 19, 24, 26, 28], + identifi: [0, 2, 18, 24, 26, 28], + download: [0, 2, 3, 16, 18, 19, 21, 26, 27, 30], + raw: [0, 2, 3, 16, 18, 20, 26, 30], + upload: [0, 2, 3, 16, 18, 19, 21, 26, 27, 30], + locat: [0, 2, 16, 20, 21, 24, 26, 27, 28, 30], + absolut: [0, 2, 16, 26, 28], + input: [0, 2, 16, 19, 20, 26, 28], + filesystem: [0, 2, 26, 28], + individu: [0, 2, 3, 20, 21, 26, 27, 28], + object: [0, 2, 3, 17, 21, 24, 26], + arrai: [0, 2, 3, 16, 26, 28], + each: [0, 2, 21, 24, 26, 27, 28], + repres: [0, 2, 3, 21, 26], + compli: [0, 2, 3, 21, 26], + schema: [0, 2, 3, 16, 17, 20, 26], + onlin: [0, 2, 26], + document: [0, 2, 13, 16, 17, 19, 21, 26, 27, 28, 30], + c: [0, 2, 21, 24, 26, 28], + target: [0, 1, 21, 26], + root: [0, 1, 2, 3, 24, 26, 28, 30], + support: [0, 2, 3, 16, 17, 18, 20, 21, 24, 26, 27, 28], + conveni: [0, 2, 24, 26, 27, 28], + avoid: [0, 1, 2, 19, 21, 24, 26, 28], + dataput: [0, 2, 3, 24, 26, 28], + call: [0, 1, 2, 24, 26, 28], + r: [0, 21, 24, 26, 28], + remot: [0, 2, 17, 21, 24, 26], + none: [0, 2, 3, 5, 6, 24, 26, 28], + extens: [0, 2, 3, 21, 24, 26, 28], + overrid: [0, 3, 24, 26, 27], + auto: [0, 13, 21, 24, 26], + detect: [0, 3, 16, 24, 26], + extern: [0, 2, 3, 16, 21, 26, 27], + unmanag: [0, 3, 16, 26], + metadata: [0, 2, 3, 16, 17, 18, 20, 26, 30], + inlin: [0, 24, 26], + defin: [0, 2, 3, 16, 20, 21, 24, 26, 28], + type: [0, 3, 16, 19, 21, 24, 26, 27, 28], + cannot: [0, 2, 3, 16, 20, 21, 24, 26, 30], + enforc: [0, 3, 17, 21, 26], + fail: [0, 3, 16, 26, 28], + valid: [0, 3, 16, 21, 24, 26, 28, 30], + error: [0, 3, 16, 20, 21, 26, 27, 28], + repositori: [0, 2, 3, 17, 19, 24, 26, 27, 28], + alloc: [0, 3, 16, 18, 24, 26, 28], + dep: [0, 2, 3, 24, 26, 28], + choic: [0, 24, 26], + depend: [0, 3, 16, 18, 21, 24, 26, 27, 28, 30], + proven: [0, 17, 20, 24, 26], + per: [0, 24, 26, 27, 30], + string: [0, 2, 3, 21, 24, 26, 28], + consist: [0, 16, 21, 24, 26], + relationship: [0, 2, 3, 21, 24, 26], + der: [0, 3, 24, 26, 28], + comp: [0, 3, 24, 26, 28], + ver: [0, 3, 17, 24, 26, 28], + follw: [0, 24, 26], + referenc: [0, 21, 24, 26], + deriv: [0, 3, 16, 21, 24, 26, 28], + compon: [0, 16, 21, 24, 26, 28], + either: [0, 1, 2, 16, 19, 20, 21, 24, 26, 27, 28, 30], + full: [0, 2, 3, 17, 21, 26, 27, 28], + system: [0, 2, 3, 15, 16, 17, 18, 19, 20, 24, 25, 26, 27, 28], + If: [0, 1, 2, 3, 16, 19, 21, 24, 26, 27, 28, 30], + doesn: [0, 2, 16, 24, 26], + given: [0, 2, 3, 21, 24, 26, 27], + suffici: [0, 2, 19, 21, 26, 28, 30], + doe: [0, 2, 3, 16, 20, 21, 26, 27, 28, 30], + where: [0, 1, 2, 3, 19, 20, 21, 23, 24, 25, 26, 27, 28], + transfer: [0, 2, 3, 16, 17, 18, 19, 20, 21, 24, 26, 29], + case: [0, 1, 2, 18, 20, 21, 24, 26, 28, 30], + w: [0, 1, 3, 17, 26, 28], + wait: [0, 2, 3, 24, 26, 28], + block: [0, 26], + until: [0, 3, 16, 24, 26, 28, 30], + complet: [0, 3, 16, 19, 21, 24, 26, 28], + encrypt: [0, 1, 2, 3, 9, 16, 26, 27], + orig_fnam: [0, 2, 3, 26, 28], + origin: [0, 3, 16, 21, 26, 28], + filenam: [0, 3, 21, 26], + sourc: [0, 1, 2, 3, 15, 16, 19, 20, 21, 24, 26, 27, 28], + repli: [0, 2, 3, 16, 24, 26, 28], + further: [0, 21, 26], + replac: [0, 3, 16, 21, 24, 26], + instead: [0, 2, 3, 16, 20, 21, 24, 26, 28], + merg: [0, 3, 21, 26], + A: [0, 2, 3, 21, 24, 26, 27, 28, 30], + first: [0, 1, 2, 3, 24, 26, 27, 28], + time: [0, 2, 3, 19, 21, 24, 26, 27, 28], + rem: [0, 26], + follow: [0, 1, 3, 16, 19, 20, 21, 24, 26, 27, 28, 30], + truncat: [0, 2, 26], + shown: [0, 2, 19, 21, 24, 26, 27, 28, 30], + unless: [0, 2, 19, 26], + recent: [0, 2, 3, 21, 26, 28, 30], + activ: [0, 2, 16, 18, 20, 21, 24, 26, 28], + At: [0, 1, 2, 26, 28], + ctrl: [0, 2, 24, 26, 30], + includ: [0, 1, 2, 3, 16, 18, 20, 21, 24, 26, 27, 28, 30], + specif: [0, 1, 2, 3, 16, 18, 19, 20, 21, 24, 26, 27, 28], + omit: [0, 2, 26], + associ: [0, 2, 3, 16, 18, 20, 21, 24, 26, 28, 30], + wherea: [0, 2, 20, 26], + alwai: [0, 2, 16, 21, 24, 26, 27, 28, 30], + regardless: [0, 2, 21, 24, 26, 28], + offset: [0, 2, 3, 16, 26, 28], + count: [0, 2, 3, 16, 21, 26, 28], + limit: [0, 1, 3, 20, 26, 28], + result: [0, 3, 16, 18, 21, 24, 26, 27, 28], + own: [0, 1, 2, 3, 19, 20, 21, 26, 28, 30], + well: [0, 1, 2, 3, 20, 21, 26, 28], + were: [0, 2, 3, 16, 21, 26, 28], + member: [0, 2, 3, 17, 20, 21, 26, 28, 30], + admin: [0, 2, 3, 16, 17, 26, 28, 30], + administ: [0, 26], + membership: [0, 26], + role: [0, 2, 3, 21, 26, 30], + owner: [0, 2, 3, 16, 20, 21, 24, 26, 28, 30], + within: [0, 2, 3, 15, 18, 20, 21, 24, 25, 26, 27, 28, 30], + save: [0, 2, 3, 4, 16, 21, 26, 27, 30], + execut: [0, 2, 3, 16, 24, 26, 27], + direct: [0, 2, 21, 26], + search: [0, 2, 3, 16, 17, 18, 19, 20, 24, 26, 27, 28], + intead: [0, 26], + allow: [0, 2, 16, 20, 21, 24, 26, 27, 28, 30], + express: [0, 1, 3, 16, 21, 26, 30], + meta: [0, 2, 3, 16, 26, 28], + err: [0, 2, 26], + ha: [0, 1, 16, 21, 26, 27, 28, 30], + creator: [0, 2, 3, 16, 21, 24, 26, 28], + find: [0, 19, 21, 26, 27, 28], + date: [0, 3, 16, 21, 26, 27, 28, 30], + yyyi: [0, 3, 26], + hh: [0, 3, 26], + mm: [0, 3, 26], + up: [0, 1, 2, 3, 17, 19, 20, 21, 24, 26, 27, 28], + catalog: [0, 3, 16, 20, 26], + categori: [0, 2, 3, 16, 21, 24, 26, 30], + sort: [0, 2, 3, 16, 26], + ct: [0, 2, 21, 26, 28], + ut: [0, 2, 21, 26, 28], + rev: [0, 2, 26], + revers: [0, 26], + order: [0, 1, 19, 21, 24, 26, 27, 28], + scope: [0, 2, 3, 16, 21, 24, 26, 28, 30], + same: [0, 1, 2, 3, 16, 19, 21, 24, 26, 27, 28], + overal: [0, 2, 26], + least: [0, 2, 19, 24, 26], + term: [0, 2, 20, 21, 26], + match: [0, 2, 3, 19, 21, 26, 28, 30], + relev: [0, 2, 21, 26, 28], + rank: [0, 2, 26], + creation: [0, 2, 20, 21, 24, 26, 28], + respect: [0, 2, 24, 26, 28], + 20: [0, 3, 24, 26, 28], + chang: [0, 2, 3, 16, 18, 20, 21, 24, 26, 27, 28, 30], + To: [0, 1, 2, 21, 24, 26, 28, 30], + empti: [0, 2, 16, 26], + instal: [0, 2, 3, 18, 21, 24, 26, 28, 29, 30], + subsequ: [0, 2, 3, 18, 20, 21, 24, 26, 27, 28], + read: [0, 2, 3, 21, 24, 26, 28], + u: [0, 3, 21, 24, 26, 27, 28], + statu: [0, 2, 3, 21, 24, 26, 28, 30], + filter: [0, 2, 3, 21, 26], + initi: [0, 2, 3, 21, 24, 26, 28, 30], + most: [0, 2, 3, 19, 20, 21, 24, 26, 27, 28], + period: [0, 2, 3, 19, 21, 26], + purg: [0, 2, 3, 26], + histori: [0, 2, 3, 24, 26], + 30: [0, 2, 3, 24, 26], + dai: [0, 2, 3, 19, 26], + retain: [0, 2, 3, 17, 26], + sinc: [0, 2, 3, 21, 24, 26, 28], + second: [0, 3, 24, 26, 28], + suffix: [0, 3, 26, 27], + hour: [0, 3, 26], + week: [0, 3, 26], + 3: [0, 1, 9, 10, 18, 20, 24, 25, 26, 28], + 4: [0, 1, 4, 9, 18, 26, 27, 28, 30], + queu: [0, 26], + readi: [0, 3, 26, 28], + succeed: [0, 24, 26, 28], + latest: [0, 1, 2, 3, 26, 27], + common: [0, 1, 2, 3, 20, 21, 26], + uid: [0, 2, 3, 6, 16, 24, 26], + lowest: [0, 2, 26, 27], + highest: [0, 2, 26, 27], + previou: [0, 2, 19, 21, 24, 26, 28], + cd: [0, 1, 2, 24, 26], + switch: [0, 2, 17, 26], + differ: [0, 1, 2, 21, 26, 28], + In: [0, 1, 2, 19, 20, 21, 24, 26, 27, 28, 30], + grant: [0, 2, 21, 26, 30], + act: [0, 2, 21, 26], + indic: [0, 2, 21, 24, 26, 27], + colelct: [0, 2, 26], + deploi: [1, 20, 21], + build: 1, + third: [1, 21, 28], + parti: [1, 21], + packag: [1, 3, 16, 19, 21, 24, 25, 26], + process: [1, 3, 20, 21, 24, 28], + describ: [1, 2, 3, 21, 24, 27, 28, 30], + here: [1, 19, 21, 24, 27, 28, 29], + goal: [1, 18, 20], + eventu: [1, 18, 20, 21], + autom: [1, 19, 28], + much: [1, 28], + possibl: [1, 16, 19, 21, 24, 28], + technologi: [1, 15, 20, 21], + relat: [1, 3, 18, 20, 21, 24, 27, 28], + central: [1, 17, 21, 24], + which: [1, 2, 3, 18, 20, 21, 24, 27, 28, 30], + instanc: [1, 3], + These: [1, 3, 20, 21, 24, 27, 30], + list: [1, 2, 3, 16, 19, 21, 24, 27, 29, 30], + below: [1, 19, 20, 21, 24, 27, 28, 30], + hardwar: [1, 21], + select: [1, 16, 19, 21, 28, 30], + desir: [1, 28], + perform: [1, 16, 20, 21, 24, 27, 28, 30], + cost: [1, 21], + rang: [1, 21, 28], + singl: [1, 3, 17, 20, 21, 24, 28, 30], + node: [1, 21], + vm: 1, + dedic: [1, 20], + high: [1, 3, 18, 20, 21, 27, 29], + cluster: [1, 17, 24, 27, 28], + oper: [1, 17, 21, 24, 25, 26, 27], + linux: [1, 27], + distribut: [1, 20, 21, 24], + import: [1, 17, 21], + though: [1, 19, 21, 24, 28], + through: [1, 21, 24, 30], + test: [1, 15, 19, 21, 24], + moment: 1, + been: [1, 16, 21, 28, 30], + ubuntu: 1, + focal: [1, 30], + arango: 1, + togeth: [1, 21], + across: [1, 16, 18, 20, 21, 28], + latter: [1, 19], + chosen: [1, 3], + strongli: [1, 24], + recommend: [1, 19, 20, 24, 27, 28], + speed: [1, 21, 28], + reduc: [1, 16], + latenc: [1, 21], + need: [1, 3, 16, 18, 19, 20, 21, 24, 27, 28], + tl: [1, 17], + connect: [1, 3, 12, 13, 17, 19, 20, 21, 27], + gridftp: [1, 20, 21], + modul: [1, 18, 27, 28], + applic: [1, 18, 20, 21, 27, 28, 30], + python: [1, 3, 15, 16, 17, 19, 21, 24, 25, 26, 28, 29], + depli: 1, + built: [1, 19, 21, 24], + code: [1, 7, 8, 9, 11, 28], + github: [1, 15, 20], + prior: [1, 21, 27], + environ: [1, 18, 20, 21, 24, 25, 26, 27, 30], + properli: [1, 26], + exampl: [1, 19, 20, 21, 24, 27, 28, 30], + base: [1, 2, 15, 17, 20, 21, 24, 27, 28, 30], + debian: 1, + min: [1, 21], + max: [1, 21], + restrict: [1, 20, 21, 27], + later: [1, 16, 24, 28], + section: [1, 15, 21, 24, 27, 28, 30], + git: 1, + clone: 1, + http: [1, 3, 16, 17, 20, 21, 27, 28], + com: [1, 20], + ornl: [1, 15, 20, 21, 27, 28], + g: [1, 27], + cmake: 1, + libboost: 1, + all: [1, 2, 3, 16, 18, 20, 21, 24, 27, 28, 30], + dev: 1, + protobuf: [1, 3, 28], + compil: 1, + libzmq3: 1, + libssl: 1, + libcurl4: 1, + openssl: 1, + libglobu: 1, + libfus: 1, + nodej: 1, + npm: 1, + primarili: [1, 21, 24], + cooki: [1, 30], + parser: [1, 16], + helmet: 1, + ini: [1, 27], + protobufj: 1, + zeromq: [1, 17], + ect: 1, + oauth2: [1, 21], + done: [1, 21, 28], + helper: 1, + install_core_depend: 1, + sh: 1, + install_repo_depend: 1, + install_ws_depend: 1, + next: [1, 19, 27, 28], + step: [1, 19, 21, 27, 28], + config: [1, 3, 12, 13], + templat: 1, + you: [1, 19, 21, 24, 27, 28], + run: [1, 2, 3, 16, 21, 24, 27, 28], + generate_dataf: 1, + creat: [1, 2, 3, 13, 16, 18, 19, 20, 21, 27, 30], + datafed_default_log_path: 1, + repo: [1, 3, 16, 17, 24, 28], + datafed_database_password: 1, + datafed_zeromq_session_secret: 1, + datafed_zeromq_system_secret: 1, + datafed_lego_email: 1, + datafed_web_key_path: 1, + datafed_web_cert_path: 1, + datafed_globus_app_id: 1, + datafed_globus_app_secret: 1, + datafed_server_port: [1, 27], + datafed_domain: 1, + datafed_gcs_root_nam: 1, + gcs_collection_root_path: 1, + datafed_repo_id_and_dir: 1, + what: [1, 21, 28, 30], + variabl: [1, 27, 28], + found: [1, 21, 24], + onc: [1, 16, 19, 21, 24, 27, 30], + necessari: [1, 21, 27, 28], + seri: [1, 28], + develop: [1, 15, 20, 28, 30], + appropri: [1, 21, 24, 27], + automat: [1, 3, 17, 20, 21, 28, 30], + setup: [1, 2, 3, 18, 27, 28, 30], + default: [1, 2, 3, 21, 24, 30], + place: [1, 3, 19, 20, 21, 24, 28], + opt: [1, 2, 3, 4, 20, 21], + log: [1, 3, 5, 16, 19, 21, 27, 28, 30], + var: 1, + etc: [1, 3, 19, 20, 21, 27, 28, 30], + systemd: 1, + folder: [1, 3, 16, 21, 24, 27, 28], + grid: [1, 21], + secur: [1, 3, 20, 21, 27], + arangodb: 1, + your: [1, 19, 21, 27, 28], + 7: [1, 9, 24, 27, 28], + wget: 1, + arangodb37: 1, + commun: [1, 3, 17, 19, 20, 21, 27, 28], + arangodb3_3: 1, + 10: [1, 11, 24, 28], + "1_amd64": 1, + deb: 1, + sudo: 1, + apt: 1, + It: [1, 19, 21, 24, 27, 28], + systemctl: 1, + arangodb3: 1, + we: [1, 24, 28], + foxx: 1, + machin: [1, 19, 21, 24, 27, 28], + arngodb: 1, + mkdir: 1, + b: [1, 24, 28], + dbuild_repo_serv: 1, + fals: [1, 2, 3, 4, 28], + dbuild_authz: 1, + dbuild_core_serv: 1, + dbuild_web_serv: 1, + dbuild_doc: 1, + dbuild_python_cli: 1, + dbuild_foxx: 1, + true: [1, 2, 3, 21, 24, 28], + parallel: [1, 24, 28], + 6: [1, 9, 18, 30], + For: [1, 20, 21, 24, 26, 27, 28, 30], + befor: [1, 16, 19, 21, 24, 26, 28], + generage_core_config: 1, + generage_core_servic: 1, + 9100: 1, + thread: 1, + task: [1, 2, 3, 16, 17, 18, 21, 24], + db: [1, 16, 17], + url: 1, + 127: 1, + 8529: 1, + _db: 1, + sdm: [1, 3, 20], + api: [1, 3, 4, 6, 16, 17, 18, 20, 21, 24, 27, 28], + user: [1, 2, 3, 15, 16, 18, 19, 20, 27, 28, 30], + pass: [1, 21, 27, 28], + password: [1, 2, 3, 6, 19, 21, 27, 28, 30], + cred: 1, + app: 1, + secret: 1, + generage_ws_config: 1, + addit: [1, 20, 21, 24, 27, 28, 30], + domain: [1, 3, 18, 20, 21], + certif: 1, + let: [1, 28], + install_lego_and_certif: 1, + look: [1, 19, 21, 24, 27, 28], + them: [1, 21, 28, 30], + exactli: 1, + open: [1, 15, 16, 19, 20, 21, 27, 28, 30], + appear: 1, + after: [1, 3, 16, 19, 20, 21, 24, 27], + command: [1, 2, 3, 16, 19, 21, 25, 27, 28, 30], + generage_ws_servic: 1, + v4: 1, + v5: 1, + curl: 1, + lo: 1, + org: [1, 16, 17, 19, 21], + toolkit: 1, + repo_latest_al: 1, + dpkg: 1, + get: [1, 2, 3, 4, 16, 17, 18, 24, 27, 30], + updat: [1, 2, 3, 16, 17, 21, 24, 28, 30], + help: [1, 2, 18, 20, 21, 28, 30], + set: [1, 2, 3, 4, 16, 18, 19, 20, 21], + correctli: [1, 28], + setup_globu: 1, + There: [1, 3, 21, 28], + instruct: [1, 19, 28], + scirpt: 1, + guest: 1, + abl: [1, 20, 21, 27, 28], + regist: [1, 18, 21, 27], + generate_repo_form: 1, + generage_repo_config: 1, + generage_repo_servic: 1, + generage_authz_config: 1, + 5: [1, 9, 17, 18, 27, 28], + dglobus_vers: 1, + point: [1, 3, 16, 17, 19, 21, 27, 28, 30], + want: [1, 24, 28], + restart: 1, + gridft: 1, + ensur: [1, 3, 16, 19, 20, 21, 24, 28], + exchang: [1, 21], + _om_text: 2, + _om_json: 2, + _om_retn: 2, + _stat_ok: 2, + _stat_error: 2, + _capi: 2, + _return_v: 2, + _uid: 2, + _cur_ctx: 2, + _cur_col: 2, + _cur_coll_prefix: 2, + _cur_coll_titl: 2, + _cur_alias_prefix: 2, + _prev_col: 2, + _prev_ctx: 2, + _list_item: 2, + _interact: 2, + _verbosity_sticki: 2, + _verbos: 2, + _output_mode_sticki: 2, + _output_mod: 2, + _ctxt_set: 2, + _task_status: 2, + _task_typ: 2, + _initi: 2, + _devnul: 2, + _hdr_lev_char: 2, + init: 2, + loginbypassword: [2, 3], + loginbytoken: 2, + token: [2, 6], + _aliasedgroup: 2, + str: [2, 3, 28], + dict: [2, 3], + sequenc: [2, 28], + attr: 2, + click: [2, 19, 28, 30], + group: [2, 15, 17, 21], + subcommand: [2, 24], + attach: [2, 17, 19, 21, 28], + wai: [2, 20, 21, 28], + implement: [2, 16, 21, 28, 30], + nest: [2, 3, 24, 28], + paramet: [2, 16, 21, 28, 30], + map: [2, 18], + multicommand: 2, + basecommand: 2, + 8: [2, 4, 9, 11], + commmand: 2, + get_command: 2, + ctx: 2, + cmd_name: 2, + resolve_command: 2, + _aliasedgrouproot: 2, + except: [2, 3, 16, 21, 24, 27, 28, 30], + _nocommand: 2, + kwarg: [2, 6], + exit: [2, 18, 24], + _set_script_cb: 2, + param: 2, + _set_verbosity_cb: 2, + __global_context_opt: 2, + _global_context_opt: 2, + func: 2, + __global_output_opt: 2, + _global_output_opt: 2, + _cli: 2, + data: [2, 3, 15, 16, 17, 22, 23, 25, 27, 29], + _gendoc: 2, + _gendochead: 2, + cmd: 2, + _gendoccmd: 2, + parnam: 2, + recurs: [2, 28], + _wc: 2, + project: [2, 3, 16, 17, 18, 19, 20, 24], + wc: [2, 16, 18, 24], + _wp: 2, + _data: 2, + _dataview: 2, + data_id: [2, 3], + view: [2, 3, 16, 18, 19, 20, 21, 30], + verbos: [2, 18, 24, 28], + _datacr: 2, + raw_data_fil: [2, 3], + metadata_fil: [2, 3], + schema_enforc: [2, 3], + _dataupd: 2, + metadata_set: [2, 3, 28], + deps_add: [2, 3, 28], + deps_rem: [2, 3], + _datadelet: 2, + delet: [2, 3, 16, 21, 24, 27, 28, 30], + _dataget: 2, + df_id: 2, + _dataput: 2, + put: [2, 3, 24, 27, 28, 30], + _batch: 2, + _data_batch_cr: 2, + batch: [2, 3, 17, 24], + _data_batch_upd: 2, + _list: 2, + share: [2, 3, 16, 17, 18, 19, 20, 21, 24, 27, 28], + l: [2, 16, 18, 24], + _coll: 2, + _collview: 2, + coll: [2, 3, 18, 24, 28], + _collcreat: 2, + _collupd: 2, + _colldelet: 2, + _collitemsadd: 2, + add: [2, 3, 16, 17, 20, 21, 24, 27, 30], + _coll_rem: 2, + remov: [2, 3, 16, 17, 21, 27, 30], + _queri: 2, + _querylist: 2, + queri: [2, 3, 16, 18, 20, 21, 29, 30], + _queryview: 2, + qry_id: 2, + _querycr: 2, + coll_mod: [2, 3], + meta_err: [2, 3], + time_from: [2, 3], + time_to: [2, 3], + sort_rev: [2, 3], + _queryupd: 2, + _querydelet: 2, + _queryexec: 2, + _queryrun: 2, + _user: 2, + _userlistcollab: 2, + _userlistal: 2, + _userview: 2, + _userwho: 2, + _project: 2, + _projectlist: 2, + _projectview: 2, + proj_id: 2, + _share: 2, + _task: 2, + _tasklist: 2, + _taskview: 2, + task_id: [2, 3, 28], + _ep: 2, + _epget: 2, + _epset: 2, + _eplist: 2, + _epdefault: 2, + _epdefaultget: 2, + _epdefaultset: 2, + _setup: 2, + _verbosityset: 2, + _help_cli: 2, + _exit_cli: 2, + _print_msg: 2, + _print_ack_repli: 2, + _print_list: 2, + _print_user_list: 2, + _print_proj_list: 2, + _print_endpoint: 2, + _print_data: 2, + _print_batch: 2, + _print_col: 2, + _print_dep: 2, + dr: 2, + _print_task_list: 2, + _print_task: 2, + _print_task_arrai: 2, + _print_us: 2, + _print_proj: 2, + _print_path: 2, + _print_queri: 2, + _wrap_text: 2, + indent: 2, + compact: 2, + _resolve_id: [2, 3, 28], + _resolve_coll_id: 2, + _generic_reply_handl: 2, + printfunc: 2, + _setworkingcollectiontitl: 2, + _arraytocsv: 2, + skip: [2, 27], + _arraytodot: 2, + _printjson: 2, + cur_ind: 2, + _printjson_list: 2, + _bar_adaptive_human_read: 2, + total: [2, 24, 28], + width: 2, + 80: 2, + _addconfigopt: 2, + core: [3, 16, 17, 21, 27, 28], + send: [3, 5, 6, 21, 28], + request: [3, 17, 19, 21, 28], + sent: 3, + method: [3, 20, 28], + googl: [3, 17, 28], + proto: 3, + basic: [3, 21, 24, 25, 26, 28, 29], + function: [3, 16, 21, 24, 30], + th: [3, 28], + mirror: [3, 17], + capabl: [3, 16, 19, 20, 21, 24, 25, 26, 28], + expos: [3, 28], + load: [3, 16, 17, 21, 27, 28], + some: [3, 19, 21, 24, 27, 28], + suppli: [3, 28], + constructor: 3, + establish: [3, 28], + otherwis: [3, 21, 24, 28], + anonym: 3, + getauthus: 3, + check: [3, 16, 28], + construct: [3, 28], + _max_md_siz: 3, + int: [3, 27], + maximum: [3, 28], + size: [3, 20, 21, 24, 28], + byte: [3, 21], + 102400: 3, + _max_payload_s: 3, + amount: [3, 21], + 1048576: 3, + invalid: [3, 16, 21, 27], + present: [3, 16, 18, 20, 21, 27, 28, 30], + _endpoint_legaci: 3, + _endpoint_uuid: 3, + logout: [3, 6], + out: [3, 16, 20, 24, 27, 28, 30], + reset: [3, 5, 16, 28, 30], + underli: [3, 20, 21], + clear: [3, 16, 24, 28], + attempt: [3, 24], + generatecredenti: 3, + gener: [3, 7, 8, 9, 11, 13, 16, 18, 20, 21, 24, 26, 27, 28, 30], + msg: [3, 6, 28], + repocr: 3, + repo_id: [3, 28], + desc: [3, 21, 28], + capac: 3, + pub_kei: 3, + exp_path: 3, + home: [3, 19, 27], + intern: [3, 19, 21, 28], + detail: [3, 19, 21, 24, 26, 27, 28, 30], + fuse: 3, + so: [3, 19, 21, 28], + tcp: [3, 17, 27], + my: [3, 16, 21, 28], + cu: 3, + edu: 3, + 9000: 3, + uuid: [3, 19, 28], + xxxxyyyyxxxx: 3, + xxxx: 3, + xxxxyyyi: 3, + posix: [3, 21], + seen: [3, 24, 28], + control: [3, 16, 18, 20, 30], + tony_stark: 3, + invent: 3, + could: [3, 19, 21, 23, 24, 28], + last: [3, 28], + right: [3, 19, 20, 21, 24, 28, 30], + pepper: 3, + repodatarepli: [3, 8], + respons: [3, 18, 21, 24], + repolist: 3, + list_al: 3, + bool: 3, + repodelet: 3, + ackrepli: [3, 7], + repoallocationcr: 3, + subject: [3, 21], + data_limit: [3, 28], + rec_limit: [3, 28], + repolistalloc: 3, + repoallocationdelet: 3, + dataview: [3, 28], + retriev: [3, 21], + NOT: 3, + resolut: 3, + recorddatarepli: [3, 8, 28], + datacr: [3, 28], + parent_id: [3, 28], + both: [3, 16, 20, 21, 24, 25, 26, 27, 28], + dictionari: [3, 28], + form: [3, 16, 21, 28], + compris: [3, 28], + flag: [3, 16, 21, 24, 27], + dataupd: [3, 28], + datadelet: [3, 28], + onr: 3, + dataget: [3, 28], + encrypt_avail: [3, 9], + timeout_sec: 3, + prepend: 3, + accord: [3, 28], + uniqu: [3, 20, 21, 24, 28], + overriden: 3, + take: [3, 20, 21, 27, 28], + background: [3, 16, 18, 21, 28], + asynchron: 3, + timeout: [3, 6, 27, 28], + poll: 3, + xfrdatarepli: 3, + databatchcr: [3, 28], + tupl: [3, 28], + databatchupd: [3, 28], + collectionview: [3, 28], + colldatarepli: [3, 8, 28], + collectioncr: [3, 28], + becom: [3, 21, 30], + publicli: [3, 19], + readabl: [3, 21, 28], + browser: [3, 16, 21, 30], + scientif: [3, 15, 21], + organ: [3, 17, 18, 20, 21, 24, 30], + ad: [3, 19, 20, 21, 27, 28], + collectionupd: 3, + collectiondelet: [3, 28], + OR: [3, 19, 27], + collectionitemslist: [3, 28], + page: [3, 13, 16, 19, 21, 24, 26, 27, 28, 30], + cleaner: 3, + listingrepli: [3, 8, 28], + collectionitemsupd: [3, 28], + add_id: [3, 28], + rem_id: [3, 28], + unlink: [3, 21, 30], + ancestor: 3, + grandpar: 3, + descend: [3, 28], + re: [3, 16, 30], + collectiongetpar: [3, 28], + inclus: 3, + ignor: [3, 21], + collpathrepli: [3, 8, 28], + querylist: [3, 28], + queryview: [3, 28], + query_id: [3, 28], + querydatarepli: [3, 8, 28], + querycr: [3, 28], + assign: [3, 21, 28], + queryupd: 3, + thing: [3, 28], + like: [3, 17, 21, 27, 28], + modifi: [3, 16, 20, 21], + querydelet: 3, + queryexec: [3, 28], + store: [3, 16, 17, 19, 20, 21, 27, 28, 30], + querydirect: 3, + directli: [3, 20, 21, 28], + _buildsearchrequest: 3, + userlistcollabor: 3, + userdatarepli: [3, 8], + userlistal: 3, + userview: 3, + projectlist: [3, 28], + part: [3, 28], + projectview: [3, 28], + project_id: 3, + projectdatarepli: [3, 8, 28], + projectgetrol: 3, + plai: [3, 21, 28], + sharedlist: 3, + inc_us: 3, + inc_project: 3, + sharedlistitem: 3, + owner_id: 3, + tasklist: [3, 28], + arrang: 3, + end: [3, 21, 22, 27, 28], + taskview: [3, 28], + regard: [3, 19, 28], + taskdatarepli: [3, 8, 28], + endpointlistrec: 3, + usergetrecenteprepli: [3, 8], + endpointdefaultget: 3, + endpointdefaultset: 3, + endpointget: 3, + endpointset: 3, + partial: [3, 21], + setupcredenti: 3, + setcontext: [3, 28], + resolv: [3, 16], + getcontext: [3, 28], + timestamptostr: 3, + convert: [3, 28], + timestamp: [3, 21], + standard: [3, 20, 21, 27], + struct_tim: 3, + represent: [3, 21], + strtotimestamp: 3, + time_str: 3, + y: [3, 28], + sizetostr: 3, + precis: [3, 18, 20], + metric: 3, + unit: [3, 21], + defaut: 3, + _uniquifyfilenam: 3, + alreadi: [3, 19, 21, 24, 27, 28], + pathlib: 3, + interest: [3, 28], + _resolvepathforhttp: 3, + _resolvepathforglobu: 3, + must_exist: 3, + whether: [3, 28], + _setsanedefaultopt: 3, + miss: [3, 16], + sane: 3, + determin: [3, 19, 21, 27, 30], + _opt_int: 4, + _opt_bool: 4, + _opt_path: 4, + _opt_no_env: 4, + _opt_no_cf: 4, + 16: 4, + _opt_no_cl: 4, + 32: [4, 24], + _opt_hid: 4, + 64: 4, + _opt_eag: 4, + 128: 4, + _opt_info: 4, + _processopt: 4, + _loadenvironvar: 4, + _loadconfigfil: 4, + cfg_file: 4, + prioriti: 4, + printsettinginfo: 4, + getopt: 4, + server_host: [5, 6], + server_port: [5, 6], + server_pub_kei: [5, 6], + client_pub_kei: [5, 6], + client_priv_kei: [5, 6], + zmq_ctxt: 5, + log_level: 5, + info: [5, 16], + __del__: 5, + registerprotocol: 5, + msg_modul: 5, + recv: [5, 6, 28], + a_timeout: 5, + 1000: [5, 28], + ctxt: [5, 28], + makemessag: 5, + msg_name: 5, + get_latest_vers: 6, + package_nam: 6, + server_pub_key_fil: 6, + client_pub_key_fil: 6, + client_priv_key_fil: 6, + client_token: 6, + manual_auth: 6, + keysload: 6, + keysvalid: 6, + getauthstatu: 6, + manualauthbypassword: 6, + manualauthbytoken: 6, + getnackexceptionen: 6, + setnackexceptionen: 6, + enabl: [6, 16, 20, 21, 24, 27, 30], + setdefaulttimeout: 6, + getdefaulttimeout: 6, + getdailymessag: 6, + sendrecv: [6, 28], + nack_except: [6, 28], + protocol: [7, 8, 9, 11, 21, 27, 28], + buffer: [7, 8, 9, 11, 28], + _sym_db: [7, 8, 9, 11], + descriptor: [7, 8, 9, 11], + _protocol: [7, 8], + _ackrepli: 7, + _nackrepli: 7, + _versionrequest: 7, + _versionrepli: 7, + _getauthstatusrequest: 7, + _authenticatebypasswordrequest: 7, + _authenticatebytokenrequest: 7, + _authstatusrepli: 7, + _dailymessagerequest: 7, + _dailymessagerepli: 7, + nackrepli: [7, 28], + versionrequest: 7, + versionrepli: 7, + getauthstatusrequest: 7, + authenticatebypasswordrequest: 7, + authenticatebytokenrequest: 7, + authstatusrepli: 7, + dailymessagerequest: 7, + dailymessagerepli: 7, + _msg_name_to_typ: [7, 8], + _msg_type_to_nam: [7, 8], + _generatecredentialsrequest: 8, + _revokecredentialsrequest: 8, + _generatecredentialsrepli: 8, + _checkpermsrequest: 8, + _checkpermsrepli: 8, + _getpermsrequest: 8, + _getpermsrepli: 8, + _userviewrequest: 8, + _userdatarepli: 8, + _usersetaccesstokenrequest: 8, + _usergetaccesstokenrequest: 8, + _useraccesstokenrepli: 8, + _usercreaterequest: 8, + _userfindbyuuidsrequest: 8, + _userfindbynameuidrequest: 8, + _userupdaterequest: 8, + _userlistallrequest: 8, + _userlistcollabrequest: 8, + _usergetrecenteprequest: 8, + _usergetrecenteprepli: 8, + _usersetrecenteprequest: 8, + _listingrepli: 8, + _recordlistbyallocrequest: 8, + _recordviewrequest: 8, + _recorddatarepli: 8, + _recordcreaterequest: 8, + _recordcreatebatchrequest: 8, + _recordupdaterequest: 8, + _recordupdatebatchrequest: 8, + _recordexportrequest: 8, + _recordexportrepli: 8, + _recordlockrequest: 8, + _recorddeleterequest: 8, + _recordgetdependencygraphrequest: 8, + _recordallocchangerequest: 8, + _recordallocchangerepli: 8, + _recordownerchangerequest: 8, + _recordownerchangerepli: 8, + _datagetrequest: 8, + _dataputrequest: 8, + _datagetrepli: 8, + _dataputrepli: 8, + _datadeleterequest: 8, + _datapathrequest: 8, + _datapathrepli: 8, + _searchrequest: 8, + _collviewrequest: 8, + _colldatarepli: 8, + _collreadrequest: 8, + _collcreaterequest: 8, + _collupdaterequest: 8, + _colldeleterequest: 8, + _collwriterequest: 8, + _collmoverequest: 8, + _collgetparentsrequest: 8, + _collpathrepli: 8, + _collgetoffsetrequest: 8, + _collgetoffsetrepli: 8, + _colllistpublishedrequest: 8, + _groupcreaterequest: 8, + _groupupdaterequest: 8, + _groupdatarepli: 8, + _groupdeleterequest: 8, + _grouplistrequest: 8, + _groupviewrequest: 8, + _aclviewrequest: 8, + _aclupdaterequest: 8, + _aclsharedlistrequest: 8, + _aclsharedlistitemsrequest: 8, + _acldatarepli: 8, + _projectviewrequest: 8, + _projectdatarepli: 8, + _projectcreaterequest: 8, + _projectupdaterequest: 8, + _projectdeleterequest: 8, + _projectlistrequest: 8, + _projectsearchrequest: 8, + _projectgetrolerequest: 8, + _projectgetrolerepli: 8, + _repodatadeleterequest: 8, + _repodatagetsizerequest: 8, + _repodatasizerepli: 8, + _repopathcreaterequest: 8, + _repopathdeleterequest: 8, + _repolistrequest: 8, + _repoviewrequest: 8, + _repocreaterequest: 8, + _repoupdaterequest: 8, + _repodeleterequest: 8, + _repodatarepli: 8, + _repocalcsizerequest: 8, + _repocalcsizerepli: 8, + _repolistallocationsrequest: 8, + _repolistsubjectallocationsrequest: 8, + _repolistobjectallocationsrequest: 8, + _repoviewallocationrequest: 8, + _repoallocationsrepli: 8, + _repoallocationstatsrequest: 8, + _repoallocationstatsrepli: 8, + _repoallocationcreaterequest: 8, + _repoallocationsetrequest: 8, + _repoallocationsetdefaultrequest: 8, + _repoallocationdeleterequest: 8, + _repoauthzrequest: 8, + _querycreaterequest: 8, + _queryupdaterequest: 8, + _querydeleterequest: 8, + _querylistrequest: 8, + _queryviewrequest: 8, + _queryexecrequest: 8, + _querydatarepli: 8, + _notelistbysubjectrequest: 8, + _noteviewrequest: 8, + _notecreaterequest: 8, + _noteupdaterequest: 8, + _notecommenteditrequest: 8, + _notedatarepli: 8, + _taskviewrequest: 8, + _tasklistrequest: 8, + _taskdatarepli: 8, + _tagsearchrequest: 8, + _taglistbycountrequest: 8, + _tagdatarepli: 8, + _metadatavalidaterequest: 8, + _metadatavalidaterepli: 8, + _schemaviewrequest: 8, + _schemasearchrequest: 8, + _schemadatarepli: 8, + _schemacreaterequest: 8, + _schemaupdaterequest: 8, + _schemareviserequest: 8, + _schemadeleterequest: 8, + _topiclisttopicsrequest: 8, + _topicviewrequest: 8, + _topicsearchrequest: 8, + _topicdatarepli: 8, + generatecredentialsrequest: 8, + revokecredentialsrequest: 8, + generatecredentialsrepli: 8, + checkpermsrequest: 8, + checkpermsrepli: 8, + getpermsrequest: 8, + getpermsrepli: 8, + userviewrequest: 8, + usersetaccesstokenrequest: 8, + usergetaccesstokenrequest: 8, + useraccesstokenrepli: 8, + usercreaterequest: 8, + userfindbyuuidsrequest: 8, + userfindbynameuidrequest: 8, + userupdaterequest: 8, + userlistallrequest: 8, + userlistcollabrequest: 8, + usergetrecenteprequest: 8, + usersetrecenteprequest: 8, + recordlistbyallocrequest: 8, + recordviewrequest: 8, + recordcreaterequest: 8, + recordcreatebatchrequest: 8, + recordupdaterequest: 8, + recordupdatebatchrequest: 8, + recordexportrequest: 8, + recordexportrepli: 8, + recordlockrequest: 8, + recorddeleterequest: 8, + recordgetdependencygraphrequest: 8, + recordallocchangerequest: 8, + recordallocchangerepli: 8, + recordownerchangerequest: 8, + recordownerchangerepli: 8, + datagetrequest: 8, + dataputrequest: 8, + datagetrepli: [8, 28], + dataputrepli: [8, 28], + datadeleterequest: 8, + datapathrequest: 8, + datapathrepli: 8, + searchrequest: 8, + collviewrequest: 8, + collreadrequest: 8, + collcreaterequest: 8, + collupdaterequest: 8, + colldeleterequest: 8, + collwriterequest: 8, + collmoverequest: 8, + collgetparentsrequest: 8, + collgetoffsetrequest: 8, + collgetoffsetrepli: 8, + colllistpublishedrequest: 8, + groupcreaterequest: 8, + groupupdaterequest: 8, + groupdatarepli: 8, + groupdeleterequest: 8, + grouplistrequest: 8, + groupviewrequest: 8, + aclviewrequest: 8, + aclupdaterequest: 8, + aclsharedlistrequest: 8, + aclsharedlistitemsrequest: 8, + acldatarepli: 8, + projectviewrequest: 8, + projectcreaterequest: 8, + projectupdaterequest: 8, + projectdeleterequest: 8, + projectlistrequest: 8, + projectsearchrequest: 8, + projectgetrolerequest: 8, + projectgetrolerepli: 8, + repodatadeleterequest: 8, + repodatagetsizerequest: 8, + repodatasizerepli: 8, + repopathcreaterequest: 8, + repopathdeleterequest: 8, + repolistrequest: 8, + repoviewrequest: 8, + repocreaterequest: 8, + repoupdaterequest: 8, + repodeleterequest: 8, + repocalcsizerequest: 8, + repocalcsizerepli: 8, + repolistallocationsrequest: 8, + repolistsubjectallocationsrequest: 8, + repolistobjectallocationsrequest: 8, + repoviewallocationrequest: 8, + repoallocationsrepli: 8, + repoallocationstatsrequest: 8, + repoallocationstatsrepli: 8, + repoallocationcreaterequest: 8, + repoallocationsetrequest: 8, + repoallocationsetdefaultrequest: 8, + repoallocationdeleterequest: 8, + repoauthzrequest: 8, + querycreaterequest: 8, + queryupdaterequest: 8, + querydeleterequest: 8, + querylistrequest: 8, + queryviewrequest: 8, + queryexecrequest: 8, + notelistbysubjectrequest: 8, + noteviewrequest: 8, + notecreaterequest: 8, + noteupdaterequest: 8, + notecommenteditrequest: 8, + notedatarepli: 8, + taskviewrequest: 8, + tasklistrequest: 8, + tagsearchrequest: 8, + taglistbycountrequest: 8, + tagdatarepli: 8, + metadatavalidaterequest: 8, + metadatavalidaterepli: 8, + schemaviewrequest: 8, + schemasearchrequest: 8, + schemadatarepli: 8, + schemacreaterequest: 8, + schemaupdaterequest: 8, + schemareviserequest: 8, + schemadeleterequest: 8, + topiclisttopicsrequest: 8, + topicviewrequest: 8, + topicsearchrequest: 8, + topicdatarepli: 8, + _errorcod: 9, + errorcod: 9, + _servicestatu: 9, + servicestatu: 9, + _searchmod: 9, + searchmod: 9, + _dependencytyp: 9, + dependencytyp: 9, + _dependencydir: 9, + dependencydir: 9, + _sortopt: 9, + sortopt: 9, + _projectrol: 9, + projectrol: 9, + _notetyp: 9, + notetyp: 9, + _notest: 9, + notest: 9, + _tasktyp: 9, + tasktyp: 9, + _taskstatu: 9, + taskstatu: 9, + _taskcommand: 9, + taskcommand: 9, + _encrypt: 9, + id_bad_request: 9, + id_internal_error: 9, + id_client_error: 9, + id_service_error: 9, + id_authn_requir: 9, + id_authn_error: 9, + id_dest_path_error: 9, + id_dest_file_error: 9, + ss_normal: 9, + ss_degrad: 9, + ss_fail: 9, + ss_offlin: 9, + sm_data: 9, + sm_collect: 9, + dep_is_derived_from: [9, 28], + dep_is_component_of: 9, + dep_is_new_version_of: 9, + dep_type_count: 9, + dep_in: 9, + dep_out: [9, 28], + sort_id: 9, + sort_titl: 9, + sort_own: 9, + sort_time_cr: 9, + sort_time_upd: 9, + sort_relev: 9, + proj_no_rol: 9, + proj_memb: 9, + proj_manag: 9, + proj_admin: 9, + note_quest: 9, + note_info: 9, + note_warn: 9, + note_error: 9, + note_clos: 9, + note_open: 9, + note_act: 9, + tt_data_get: [9, 28], + tt_data_put: [9, 28], + tt_data_del: 9, + tt_rec_chg_alloc: 9, + tt_rec_chg_own: 9, + tt_rec_del: 9, + tt_alloc_cr: 9, + tt_alloc_del: 9, + tt_user_del: 9, + tt_proj_del: 9, + 9: [9, 21], + ts_block: 9, + ts_readi: [9, 28], + ts_run: 9, + ts_succeed: [9, 28], + ts_fail: 9, + tc_stop: 9, + tc_raw_data_transf: 9, + tc_raw_data_delet: 9, + tc_raw_data_update_s: 9, + tc_alloc_cr: 9, + tc_alloc_delet: 9, + encrypt_non: 9, + encrypt_forc: 9, + _allocstatsdata: 9, + _allocdata: 9, + _dependencydata: 9, + _dependencyspecdata: 9, + _userdata: 9, + _projectdata: 9, + _listingdata: 9, + _tagdata: 9, + _pathdata: 9, + _recorddata: 9, + _recorddataloc: 9, + _reporecorddataloc: 9, + _recorddatas: 9, + _colldata: 9, + _groupdata: 9, + _aclrul: 9, + _topicdata: 9, + _repodata: 9, + _notecom: 9, + _notedata: 9, + _taskdata: 9, + _schemadata: 9, + allocstatsdata: 9, + allocdata: 9, + dependencydata: 9, + dependencyspecdata: 9, + userdata: 9, + projectdata: 9, + listingdata: 9, + tagdata: 9, + pathdata: 9, + recorddata: 9, + recorddataloc: 9, + reporecorddataloc: 9, + recorddatas: 9, + colldata: 9, + groupdata: 9, + aclrul: 9, + topicdata: 9, + repodata: 9, + notecom: 9, + notedata: 9, + taskdata: 9, + schemadata: 9, + __version__: 10, + _version: 11, + datafed_release_year: 11, + 2023: 11, + datafed_release_month: 11, + datafed_release_dai: 11, + 21: 11, + datafed_release_hour: 11, + datafed_release_minut: 11, + 40: [11, 24], + datafed_common_protocol_api_major: 11, + datafed_common_protocol_api_minor: 11, + datafed_common_protocol_api_patch: 11, + commandlib: [12, 13, 28], + messagelib: [12, 13, 28], + sdms_anon_pb2: [12, 13], + sdms_auth_pb2: [12, 13], + sdms_pb2: [12, 13], + version_pb2: [12, 13], + dataf: [13, 15, 16, 17, 21, 22, 23, 24, 25, 27, 29, 30], + sphinx: 13, + autoapi: 13, + go: [15, 21, 27, 28], + team: [15, 20, 21, 28], + oak: [15, 20, 21], + ridg: [15, 20, 21], + nation: [15, 20, 21], + laboratori: [15, 20, 21], + advanc: [15, 16, 18, 21, 24], + ATS: 15, + leadership: [15, 20, 21], + comput: [15, 20, 21, 22, 24, 25, 26, 27, 28], + facil: [15, 17, 18, 19, 20, 27, 28], + olcf: [15, 19, 20, 21, 28], + olga: 15, + kuchar: 15, + lifecycl: [15, 18], + scalabl: [15, 18, 20, 21], + workflow: [15, 20, 28], + leader: 15, + dale: 15, + stansberri: 15, + sr: 15, + softwar: [15, 21, 28], + pi: 15, + architect: 15, + lead: [15, 16, 21], + suha: [15, 28], + somnath: [15, 24, 28], + scientist: 15, + jessica: 15, + breet: 15, + minor: 16, + two: [16, 19, 21, 24, 28], + signific: [16, 20, 21], + refer: [16, 18, 24, 28], + pypi: [16, 21], + although: 16, + wa: [16, 20, 21, 24, 27, 28], + continu: [16, 18, 21], + caus: 16, + treat: [16, 21], + stabl: 16, + abil: [16, 20, 21], + appli: [16, 20, 21], + util: [16, 20, 21, 24, 25, 26], + conform: 16, + compliant: 16, + tab: [16, 19, 21, 28, 30], + reject: [16, 21], + footer: [16, 18], + area: 16, + toggleabl: 16, + bar: [16, 30], + similar: [16, 21, 24, 28], + visibl: [16, 21, 28], + toggl: 16, + magnifi: 16, + glass: 16, + icon: 16, + toolbar: 16, + aka: 16, + dramat: 16, + overhaul: 16, + better: [16, 20], + longer: [16, 21, 28], + over: [16, 20, 21, 27, 28], + significantli: [16, 20], + due: [16, 21, 30], + fundament: 16, + how: [16, 20, 21, 23, 24, 27, 28], + structur: [16, 20, 21, 24, 28, 30], + 760: [16, 28], + being: [16, 20, 21, 24, 27, 28], + wrong: 16, + 759: [16, 28], + simplifi: [16, 21, 28], + 758: [16, 28], + twice: 16, + 757: [16, 28], + 756: 16, + incomplet: 16, + 755: 16, + 754: 16, + 753: 16, + 752: 16, + 751: 16, + 749: 16, + acl: 16, + mishandl: [16, 21], + ownership: [16, 21], + 745: 16, + 744: 16, + 742: 16, + aql: 16, + recogn: 16, + 741: 16, + 739: 16, + do: [16, 19, 21, 27, 28], + 738: 16, + 737: 16, + databas: [16, 17, 21], + post: [16, 21], + bodi: 16, + 736: 16, + 735: 16, + panel: [16, 18, 28], + light: [16, 30], + theme: [16, 30], + 733: 16, + 731: 16, + border: 16, + annot: 16, + 730: 16, + 729: 16, + close: [16, 18, 21], + 727: 16, + dialog: [16, 19, 21, 27, 30], + 726: 16, + hide: 16, + 725: 16, + builder: [16, 21], + trigger: [16, 24], + 723: 16, + highlight: 16, + color: [16, 28], + too: [16, 28], + dark: [16, 30], + 722: 16, + 721: 16, + neg: 16, + regular: 16, + 720: 16, + 713: 16, + bit: 16, + mask: 16, + conflict: 16, + 712: 16, + did: [16, 24, 28], + 711: 16, + 709: 16, + report: 16, + actual: [16, 24, 28], + 708: 16, + checksum: 16, + failur: [16, 17], + caught: 16, + 707: 16, + 700: 16, + revis: 16, + 698: 16, + rework: 16, + tree: [16, 30], + drag: [16, 18], + drop: [16, 18], + 696: 16, + ref: 16, + sync: 16, + 695: 16, + 694: 16, + 693: 16, + 691: 16, + un: 16, + track: [16, 21, 28, 30], + 690: 16, + reopen: 16, + 687: 16, + 683: 16, + edg: 16, + 681: 16, + 680: 16, + break: 16, + 677: 16, + expand: [16, 28, 30], + 675: 16, + defer: 16, + 674: 16, + 673: 16, + 672: 16, + duplic: 16, + 671: 16, + 670: 16, + 668: 16, + move: [16, 20, 21, 28, 30], + trivial: [16, 24, 28], + anon: 16, + 667: 16, + short: [16, 19], + 666: 16, + rid: 16, + 664: 16, + condit: [16, 21], + 660: 16, + 659: 16, + 657: 16, + shall: 16, + edit: [16, 19, 21, 30], + 656: 16, + definit: 16, + 652: 16, + 647: 16, + scroll: [16, 19], + 643: 16, + 605: 16, + uri: [16, 21], + 602: 16, + 596: [16, 17], + improv: [16, 17, 20], + 570: 16, + 569: 16, + handl: [16, 18, 20], + def: [16, 28], + 564: 16, + 563: 16, + circular: 16, + 220: 16, + 33: [16, 17], + strict: [16, 24], + pars: [16, 28], + rule: [16, 21], + accept: [16, 28], + float: 16, + between: [16, 20, 21, 28], + zero: 16, + 25: [16, 24], + graphic: [16, 21], + editor: [16, 24], + blank: 16, + person: [16, 18, 21, 24, 27, 28], + catagori: 16, + yet: [16, 20, 21, 28], + 594: 17, + 597: 17, + event: [17, 20, 27], + notif: [17, 20, 21], + subscript: [17, 20, 28], + 401: 17, + multimedia: 17, + 12: [17, 21, 28], + 571: 17, + 35: 17, + affili: 17, + contact: [17, 21, 30], + sci: 17, + network: [17, 18, 20, 21], + geo: 17, + rest: 17, + altern: [17, 21, 24, 27, 28], + 595: 17, + hl: 17, + 598: 17, + 599: 17, + 600: 17, + scale: [17, 20], + resili: 17, + replic: 17, + back: [17, 28, 30], + comm: 17, + balanc: 17, + exclus: [17, 19, 21], + dynam: [17, 21], + farm: 17, + polici: [17, 20, 21], + impact: [17, 21], + rebuild: 17, + modern: [17, 21], + framework: [17, 21], + integr: [17, 21, 24], + easili: [17, 20, 21], + would: [17, 19, 21, 24, 27, 28], + ingest: [17, 20], + tool: [17, 18, 19, 20, 21, 27, 28], + extract: 17, + tar: 17, + zip: 17, + synchron: 17, + revisit: [17, 28], + peer: 17, + architectur: [17, 18], + robust: [17, 21], + still: [17, 20, 21], + think: [17, 21], + veri: [17, 19, 20, 24, 28, 30], + slow: 17, + larg: [17, 18, 20, 21, 24, 28], + critic: [18, 20, 21], + holist: [18, 20, 21], + fair: [18, 20], + principl: [18, 19, 20, 28], + big: [18, 20], + enhanc: [18, 20], + product: [18, 20], + reproduc: [18, 20, 21], + orient: [18, 20], + research: [18, 19, 20, 21], + earli: [18, 20], + stage: [18, 20], + serv: [18, 20], + eas: [18, 20], + burden: [18, 20, 21], + captur: [18, 20, 21, 28], + potenti: [18, 20, 21], + volum: [18, 20, 24], + heterogen: [18, 20], + refin: [18, 20], + prepar: [18, 20], + site: [18, 20, 28], + program: [18, 20, 21, 27, 28], + introduct: [18, 28, 29], + overview: [18, 22, 24, 28], + introduc: [18, 21, 22], + terminologi: [18, 21], + concept: [18, 24, 28], + why: 18, + cross: [18, 28], + account: [18, 27, 28], + paper: 18, + guid: [18, 19, 21, 26, 27], + action: [18, 21], + button: [18, 19, 27, 28], + header: 18, + syntax: 18, + shortcut: 18, + comment: 18, + ep: [18, 27], + wp: 18, + remark: 18, + jupyt: 18, + notebook: 18, + deploy: 18, + personnel: 18, + design: [18, 20, 21], + releas: [18, 20, 21], + 28: 18, + 2021: [18, 28], + road: 18, + plan: [18, 19], + pleas: [19, 21, 23, 24, 27, 28], + institut: [19, 27, 28], + left: [19, 21, 28, 30], + hand: [19, 20, 28, 29, 30], + pane: [19, 28], + ident: [19, 20, 21, 28, 30], + window: [19, 27, 28], + One: [19, 21, 28], + primari: [19, 20, 21, 24, 25, 26], + crown: 19, + your_usernam: 19, + globusid: [19, 28], + visit: [19, 27, 28], + top: [19, 20, 21, 30], + yourself: 19, + usernam: [19, 27], + dure: [19, 20], + registr: [19, 21], + As: [19, 21, 24, 28], + suggest: [19, 28], + just: [19, 24, 28], + storag: [19, 20, 21], + space: [19, 21, 24, 28], + manipul: 19, + investig: [19, 28], + IT: [19, 21], + make: [19, 21, 24, 28], + sure: [19, 28], + far: [19, 21, 24, 28], + few: [19, 20, 27, 28], + everi: [19, 28], + intend: [19, 20, 21, 24, 27, 28], + tabl: [19, 21, 27], + popular: [19, 21, 28], + summit: 19, + Andes: 19, + jupyterhub: 19, + dtn: [19, 24, 28], + alcf: [19, 24], + theta: 19, + dtn_theta: 19, + mira: 19, + coolei: 19, + dtn_mira: 19, + nersc: [19, 24], + cori: 19, + cade: [19, 24, 27, 28], + moder: 19, + mod: 19, + abov: [19, 24, 27, 28], + box: [19, 21, 28], + seem: 19, + reason: [19, 21], + those: [19, 21, 27, 28], + clearli: [19, 24, 28], + three: [19, 21, 24], + dot: 19, + signifi: 19, + about: [19, 21, 23, 24, 26, 28, 30], + down: [19, 21, 24], + till: 19, + legaci: [19, 28], + simpli: [19, 21, 24, 27, 28, 30], + portion: [19, 21], + delai: 19, + scenario: [19, 21, 28], + reactiv: 19, + expir: [19, 21], + typic: [19, 20, 21, 27, 28], + renew: 19, + inde: [19, 24, 28], + handi: [19, 28], + orchestr: [19, 21, 24, 28], + termin: [19, 24, 27, 28], + alpha: 20, + state: [20, 21, 24, 27], + qualiti: [20, 21], + artifact: 20, + uniformli: 20, + geograph: [20, 21, 24], + thought: 20, + tier: 20, + mean: [20, 21, 24, 25, 26, 28], + medium: 20, + long: [20, 21, 27, 28], + unlik: [20, 21, 28], + compromis: 20, + favor: 20, + archiv: [20, 21], + dissemin: 20, + downstream: [20, 21], + consum: [20, 21], + alert: 20, + power: [20, 21, 24, 28], + easi: [20, 21, 27, 28], + encourag: [20, 24, 27, 28], + band: 20, + hoc: [20, 21], + prone: 20, + email: [20, 21], + effici: 20, + layer: [20, 28], + permit: [20, 21, 30], + know: [20, 24, 28], + physic: [20, 21, 28], + becaus: [20, 21, 28, 30], + reli: [20, 21], + heavili: [20, 21], + familiar: [20, 21, 28], + themselv: [20, 21, 28], + tradit: [20, 21], + small: [20, 24, 28], + virtual: [20, 21, 27], + vo: 20, + predetermin: 20, + readili: 20, + static: [20, 21], + dataset: [20, 21, 28], + usual: [20, 28], + thu: [20, 21], + neither: 20, + sdmss: 20, + nor: [20, 21], + accommod: 20, + combin: [20, 21, 27], + benefit: [20, 24, 28], + unstructur: 20, + diverg: 20, + briefli: 20, + blend: 20, + uniform: [20, 21], + concis: 20, + logic: [20, 21, 24], + wide: [20, 21], + live: [20, 24, 28], + throughout: 20, + pre: [20, 21, 28], + practic: 20, + awar: [20, 21], + foundat: 20, + figur: [20, 21], + illustr: [20, 28], + analysi: 20, + proper: [20, 21], + contract: 20, + sponsor: 20, + dispers: 20, + who: [20, 24, 28], + experiment: [20, 21], + observ: [20, 21, 23, 28], + analyt: [20, 23, 24, 25, 26], + resourc: [20, 21], + depart: [20, 21], + energi: [20, 21], + agnostic: 20, + purpos: [20, 21, 24, 28], + methodologi: [20, 28], + neutral: 20, + despit: 20, + augment: 20, + complex: [20, 21, 28], + mechan: [20, 21, 27], + contrast: 20, + span: 20, + highli: [20, 24, 28], + labor: 20, + intens: 20, + beyond: 20, + understand: [20, 21, 24], + often: 20, + tightli: 20, + coupl: 20, + defacto: 20, + movement: [20, 21, 24, 28], + petabyt: 20, + govern: 20, + fund: 20, + univers: [20, 21, 24], + commerci: 20, + cloud: 20, + focus: 20, + overreach: 20, + bundl: 20, + complementari: 20, + instrument: 20, + workstat: [21, 27], + along: [21, 27, 28], + discoveri: 21, + backplan: 21, + disjoint: 21, + conceptu: 21, + agnost: 21, + aim: [21, 28], + scienc: [21, 22, 23, 28], + hpc: 21, + ti: 21, + independ: 21, + approach: [21, 28], + prevent: 21, + silo: 21, + suppress: [21, 24], + outsid: [21, 24, 28], + rather: [21, 24, 28, 30], + than: [21, 24, 28, 30], + particular: 21, + maintain: [21, 27], + protect: [21, 27], + inadvert: 21, + coordin: [21, 28], + toward: [21, 28], + unifi: 21, + inher: 21, + entropi: 21, + misidentif: 21, + loss: 21, + enclos: 21, + grai: 21, + boundari: 21, + blue: 21, + arrow: [21, 24, 28], + bu: 21, + green: 21, + cylind: 21, + label: 21, + assum: [21, 28], + lower: [21, 27], + likewis: 21, + copi: 21, + never: [21, 30], + fine: 21, + grain: 21, + undu: 21, + disrupt: 21, + perspect: 21, + behav: [21, 24], + notic: [21, 28], + increas: 21, + discuss: [21, 24], + compos: 21, + essenti: [21, 24, 27, 28], + brain: 21, + concurr: [21, 24], + deleg: 21, + pathwai: 21, + s3: 21, + inherit: 21, + reliabl: 21, + inexpens: 21, + magnet: 21, + disk: 21, + solid: 21, + drive: [21, 28], + even: [21, 24, 28], + revok: [21, 27, 30], + isol: 21, + mount: 21, + interconnect: 21, + author: 21, + identif: [21, 28], + behalf: [21, 24, 28], + low: [21, 28], + easiest: 21, + laptop: [21, 27], + issu: [21, 24], + free: [21, 28], + getting_start: 21, + assist: 21, + acquir: 21, + futur: [21, 28], + searchabl: 21, + made: 21, + begin: 21, + welcom: [21, 24], + redirect: 21, + ask: [21, 28], + explicitli: [21, 27, 28, 30], + constrain: 21, + transient: 21, + variou: [21, 27, 28], + organiz: 21, + feel: 21, + whole: 21, + upon: 21, + good: 21, + brief: [21, 28], + alphabet: 21, + greater: [21, 28], + outcom: 21, + propag: 21, + assess: 21, + fix: 21, + entiti: [21, 28], + textual: 21, + ie: 21, + confus: 21, + categor: 21, + hierarch: [21, 24], + irrevoc: 21, + alphanumer: [21, 28], + manageri: 21, + reserv: 21, + word: 21, + talli: 21, + trackabl: 21, + 12345678: 21, + 87654321: 21, + numer: [21, 24, 28], + consid: [21, 27], + random: [21, 28], + rememb: [21, 28], + frequent: 21, + lowercas: 21, + letter: 21, + z: 21, + special: 21, + charact: [21, 24], + _: [21, 28], + equival: [21, 24, 28], + colon: 21, + user123: [21, 24], + simul: [21, 23, 24, 28], + stf123: 21, + datafeb: 21, + brows: [21, 24], + encod: [21, 28], + especi: [21, 24, 28], + scheme: 21, + findabl: 21, + interoper: 21, + minimum: 21, + against: [21, 28], + obliqu: 21, + insid: [21, 24, 28], + reloc: 21, + similarli: 21, + again: [21, 28], + progress: [21, 28], + monitor: [21, 24], + distinct: [21, 24], + javascript: 21, + notat: 21, + arbitrari: [21, 24], + languag: [21, 28], + overwritten: 21, + unchang: 21, + insert: 21, + fulli: 21, + ietf: 21, + html: [21, 24], + rfc8259: 21, + implicitli: 21, + Of: [21, 28], + newer: 21, + statement: 21, + xyz: 21, + pqr: 21, + itself: [21, 24, 27, 28, 30], + prohibit: 21, + agent: 21, + problem: [21, 28], + forget: [21, 28], + simpl: [21, 24, 28], + equal: 21, + phrase: 21, + column: 21, + md: 21, + markdown: 21, + ext: [21, 28], + unix: [21, 28], + child: [21, 28], + constraint: 21, + prefer: [21, 27, 28], + mix: 21, + hierarchi: [21, 24], + subdirectori: 21, + schedul: 21, + u_user123_root: 21, + proj123: 21, + p_proj123_root: 21, + its: [21, 24, 28], + discover: 21, + impli: [21, 28], + lock: 21, + temporarili: [21, 27, 28], + evalu: 21, + absenc: 21, + deni: [21, 28], + unaffili: 21, + therefor: [21, 27, 28, 30], + wish: [21, 30], + gain: 21, + manner: [21, 28], + matter: 21, + proxim: 21, + pattern: 21, + custom: [21, 28], + review: 21, + 2020: [21, 22, 24], + With: [21, 28], + offici: [21, 28], + reus: 21, + facet: [21, 28], + autocomplet: [21, 24], + entri: 21, + widget: 21, + question: 21, + warn: 21, + deem: 21, + suitabl: 21, + opportun: 21, + assur: 21, + produc: [21, 24, 28], + unknown: [21, 27], + notifi: 21, + wildcard: 21, + doi: 21, + 2019: [22, 24], + "6th": 22, + annual: 22, + conf: 22, + intellig: 22, + csci: 22, + 19: [22, 24, 28], + slide: 22, + smoki: 22, + mountain: 22, + confer: 22, + smc: 22, + video: [22, 23, 28, 29], + learn: [23, 28], + model: [23, 28], + measur: 23, + cover: [24, 28], + prerequisit: 24, + navig: [24, 28, 30], + asynch: 24, + verifi: [24, 28], + binari: [24, 27, 28], + dafaf: 24, + immedi: 24, + stop: 24, + preced: 24, + interleav: 24, + convent: 24, + easier: 24, + Or: 24, + posit: 24, + sensit: 24, + abbrevi: 24, + ambigu: [24, 28], + natur: [24, 28], + experi: 24, + 12351468: 24, + 11801571: 24, + demo: 24, + demonstr: [24, 28], + 14022631: 24, + "09": 24, + "02": 24, + 13: 24, + "07": 24, + quicker: 24, + remain: 24, + reader: 24, + knew: [24, 28], + furthermor: [24, 28], + contextu: [24, 28], + major: [24, 30], + realiz: 24, + pair: 24, + realist: [24, 28], + expect: [24, 28], + length: 24, + 14: [24, 28], + now: [24, 28], + record_from_nersc: 24, + nersc_md: 24, + 31030353: 24, + cnm: [24, 28], + 11: 24, + "08": 24, + "04": 24, + 31027390: 24, + record_from_alcf: 24, + 29426537: 24, + from_olcf: 24, + nersc_data: 24, + txt: 24, + 31030394: 24, + "05": 24, + our: [24, 28], + wherev: [24, 28], + elect: [24, 28], + proceed: 24, + henc: 24, + leav: [24, 28], + unset: 24, + proce: [24, 28], + reveal: [24, 28], + 37: 24, + global: 24, + u2: 24, + elsewher: [24, 28], + 10314975: 24, + cln_b_1_beline_0001: 24, + mb: 24, + "57230a10": 24, + "7ba2": 24, + "11e7": 24, + "8c3b": 24, + "22000b9923ef": 24, + nanophas: 24, + h5: 24, + "01": 24, + 54: 24, + 15: 24, + 31: 24, + bash: 24, + hlt: 24, + "28m": 24, + rw: 24, + nov: 24, + 58: 24, + "400k": 24, + 36: 24, + translation_compil: 24, + "9m": 24, + image_02: 24, + mat: 24, + 41: 24, + "26m": 24, + got: [24, 28], + heavi: [24, 28], + wast: [24, 28], + preciou: [24, 28], + wall: [24, 28], + nativ: 27, + miniconda: 27, + nearli: 27, + anyth: 27, + pip: 27, + mac: 27, + And: 27, + encount: [27, 28], + machine_nam: 27, + anaconda: [27, 28], + job: 27, + conda: 27, + endpoint_name_her: 27, + inspect: 27, + suit: [27, 28], + conclud: 27, + thereof: 27, + hostnam: 27, + behind: 27, + firewal: 27, + traffic: 27, + gov: [27, 28], + 7512: 27, + tailor: 27, + config_dir: 27, + usr: 27, + default_endpoint: 27, + higher: 27, + come: 27, + varieti: [27, 30], + overridden: 27, + programmat: [27, 28], + datef: 27, + kept: 27, + incid: 27, + n: [27, 28], + datafed_server_cfg_fil: 27, + datafed_server_cfg_dir: 27, + public_key_fil: 27, + datafed_server_pub_key_fil: 27, + datafed_server_host: 27, + config_fil: 27, + datafed_client_cfg_fil: 27, + datafed_client_cfg_dir: 27, + datafed_client_pub_key_fil: 27, + private_key_fil: 27, + datafed_client_priv_key_fil: 27, + datafed_default_endpoint: 27, + incorrect: [27, 28], + librari: 28, + class: 28, + meant: 28, + exhaust: 28, + tutori: [28, 29], + comprehens: 28, + youtub: [28, 29], + deal: 28, + datetim: 28, + convers: 28, + final: 28, + df_api: 28, + try: 28, + plist_resp: 28, + abc123: 28, + breetju: 28, + sn: 28, + dv: 28, + bl: 28, + "11a": 28, + stansberrydv: 28, + trn001: 28, + train: 28, + respond: 28, + comfort: 28, + dig: 28, + pl_resp: 28, + len: 28, + interpret: 28, + python_messag: 28, + quick: 28, + nomin: 28, + besid: 28, + main: 28, + past: [28, 29], + denot: 28, + won: 28, + might: 28, + forward: [28, 30], + remind: 28, + peel: 28, + jump: 28, + straight: 28, + henceforth: 28, + breviti: 28, + sai: 28, + proj: 28, + 1610905375: 28, + 1610912585: 28, + 1073741824: 28, + data_s: 28, + rec_count: 28, + data10t: 28, + kind: 28, + nonetheless: 28, + peopl: 28, + life: 28, + profession: 28, + offer: 28, + mention: 28, + earlier: 28, + among: 28, + keyword: 28, + p_trn001_root: 28, + somewhat: 28, + fact: 28, + happen: 28, + u_somnaths_root: 28, + correct: 28, + everyth: 28, + ls_resp: 28, + 34559341: 28, + 34559108: 28, + projshar: 28, + 34558900: 28, + 34559268: 28, + Not: 28, + keep: 28, + mind: 28, + traceback: 28, + ipython: 28, + acb948617f34: 28, + lib: 28, + python3: 28, + py: 28, + self: 28, + _mapi: 28, + 761: 28, + 299: 28, + 300: 28, + _timeout: 28, + els: 28, + 301: 28, + mt: 28, + 302: 28, + 303: 28, + 343: 28, + msg_type: 28, + _nack_except: 28, + 344: 28, + err_msg: 28, + 345: 28, + rais: 28, + 346: 28, + 347: 28, + err_cod: 28, + dbget: 28, + 126: 28, + 1610905632: 28, + 1610905667: 28, + successfulli: 28, + narrow: 28, + unnecessari: 28, + carefulli: 28, + solut: [28, 29], + hopefulli: 28, + minim: 28, + naiv: 28, + accident: 28, + tediou: 28, + instanti: 28, + clutter: 28, + dest_collect: 28, + fake: 28, + real: 28, + 123: 28, + someth: 28, + dump: 28, + turn: 28, + dc_resp: 28, + unspecifi: 28, + 34682319: 28, + ext_auto: 28, + 1611077217: 28, + crucial: 28, + piec: 28, + Such: 28, + obtain: 28, + record_id: 28, + du_resp: 28, + my_first_dataset: 28, + appended_metadata: 28, + 1611077220: 28, + deps_avail: 28, + acknowledg: 28, + dv_resp: 28, + fromtimestamp: 28, + 26: 28, + 57: 28, + append: 28, + q: 28, + hello: 28, + went: 28, + clean: 28, + multi: 28, + dc2_resp: 28, + cleaning_algorithm: 28, + gaussian_blur: 28, + clean_rec_id: 28, + 34682715: 28, + wherein: 28, + dep_resp: 28, + 1611077405: 28, + 1611078386: 28, + newli: 28, + facilit: 28, + shot: 28, + colloqui: 28, + sake: 28, + file_handl: 28, + put_resp: 28, + 34702491: 28, + finish: 28, + 1611102437: 28, + 1611102444: 28, + gpf: 28, + alpin: 28, + stf011: 28, + scratch: 28, + datafed_tutori: 28, + dest: 28, + ot: 28, + behavior: 28, + usecas: 28, + 86: 28, + 1611077286: 28, + dt: 28, + compar: 28, + clash: 28, + prove: 28, + whose: 28, + expected_file_nam: 28, + join: 28, + split: 28, + bug: 28, + singular: 28, + get_resp: 28, + 34682556: 28, + 1611077310: 28, + 1611077320: 28, + renam: 28, + whatev: 28, + duplicate_paramet: 28, + task_resp: 28, + had: 28, + deliv: 28, + thousand: 28, + spread: 28, + world: 28, + contin: 28, + composit: 28, + mark: 28, + properti: 28, + exact: 28, + nomenclatur: 28, + evolv: 28, + certainli: 28, + perhap: 28, + ideal: 28, + conceiv: 28, + launch: 28, + took: 28, + computation: 28, + expens: 28, + expensive_simul: 28, + sleep: 28, + written: 28, + dat: 28, + comic: 28, + oversimplifi: 28, + accur: 28, + ye: 28, + determinist: 28, + path_to_result: 28, + esnet: 28, + cern: 28, + diskpt1: 28, + data1: 28, + "5mb": 28, + tini: 28, + "1kb": 28, + check_xfer_statu: 28, + instantan: 28, + status: 28, + hold: [28, 30], + this_task_id: 28, + mimic: 28, + coll_resp: 28, + sim_coll_id: 28, + imped: 28, + importantli: 28, + supercomput: 28, + xfer_task: 28, + ind: 28, + results_fil: 28, + rec_resp: 28, + simulation_: 28, + parameter_1: 28, + this_rec_id: 28, + cours: 28, + compet: 28, + vari: 28, + workload: 28, + great: 28, + vast: 28, + coll_alia: 28, + cat_dog_train: 28, + imag: 28, + classif: 28, + 34683877: 28, + 1611078472: 28, + ahead: 28, + gather: 28, + cat: 28, + dog: 28, + simplic: 28, + distinguish: 28, + anim: 28, + generate_animal_data: 28, + is_dog: 28, + this_anim: 28, + randint: 28, + 100: 28, + teas: 28, + raw_data_path: 28, + newi: 28, + littl: 28, + realli: 28, + cat_record: 28, + dog_record: 28, + 34684011: 28, + 34684035: 28, + 34684059: 28, + 34684083: 28, + 34684107: 28, + 34683891: 28, + 34683915: 28, + 34683939: 28, + 34683963: 28, + 34683987: 28, + collectionitemlist: 28, + coll_list_resp: 28, + cat_22: 28, + cat_32: 28, + cat_6: 28, + cat_93: 28, + cat_96: 28, + dog_3: 28, + dog_63: 28, + dog_70: 28, + dog_71: 28, + dog_8: 28, + dozen: 28, + hundr: 28, + segreg: 28, + enumer: 28, + meaning: 28, + obvious: 28, + optim: 28, + technic: 28, + soon: 28, + screenshot: 28, + bottom: [28, 30], + uncheck: 28, + checkbox: 28, + yellow: 28, + taken: 28, + floppi: 28, + pop: 28, + give: 28, + find_all_cat: 28, + ql_resp: 28, + 34684970: 28, + 1611078781: 28, + query_resp: 28, + 50: 28, + cat_rec_id: 28, + simplest: 28, + cat_coll_id: 28, + 34685092: 28, + idea: 28, + path_resp: 28, + cup_resp: 28, + obj: 28, + outer: 28, + de: 28, + collectionsitemsupd: 28, + suboptim: 28, + accomplish: 28, + fortun: 28, + entir: [28, 30], + cat_data: 28, + 34685359: 28, + pend: 28, + 1611079028: 28, + recal: 28, + arbitrarili: 28, + listdir: 28, + popularli: 28, + correspond: 29, + verif: 29, + rapid: 30, + pace: 30, + element: 30, + keyboard: 30, + whereupon: 30, + receiv: 30, + shift: 30, + held: 30, + thr: 30, + collaps: 30, + write_meta: 30, + read_data: 30, + write_data: 30, + ui: 30, + mail: 30, + whenev: 30, + amd: 30, + }, + objects: { + "": [[12, 0, 0, "-", "datafed"]], + datafed: [ + [2, 0, 0, "-", "CLI"], + [3, 0, 0, "-", "CommandLib"], + [4, 0, 0, "-", "Config"], + [5, 0, 0, "-", "Connection"], + [6, 0, 0, "-", "MessageLib"], + [7, 0, 0, "-", "SDMS_Anon_pb2"], + [8, 0, 0, "-", "SDMS_Auth_pb2"], + [9, 0, 0, "-", "SDMS_pb2"], + [10, 0, 0, "-", "VERSION"], + [11, 0, 0, "-", "Version_pb2"], + [12, 4, 1, "", "name"], + [12, 4, 1, "", "version"], + ], + "datafed.CLI": [ + [2, 1, 1, "", "_AliasedGroup"], + [2, 1, 1, "", "_AliasedGroupRoot"], + [2, 3, 1, "", "_NoCommand"], + [2, 4, 1, "", "_OM_JSON"], + [2, 4, 1, "", "_OM_RETN"], + [2, 4, 1, "", "_OM_TEXT"], + [2, 4, 1, "", "_STAT_ERROR"], + [2, 4, 1, "", "_STAT_OK"], + [2, 4, 1, "", "__global_context_options"], + [2, 4, 1, "", "__global_output_options"], + [2, 5, 1, "", "_addConfigOptions"], + [2, 5, 1, "", "_arrayToCSV"], + [2, 5, 1, "", "_arrayToDotted"], + [2, 5, 1, "", "_bar_adaptive_human_readable"], + [2, 5, 1, "", "_batch"], + [2, 4, 1, "", "_capi"], + [2, 5, 1, "", "_cli"], + [2, 5, 1, "", "_coll"], + [2, 5, 1, "", "_collCreate"], + [2, 5, 1, "", "_collDelete"], + [2, 5, 1, "", "_collItemsAdd"], + [2, 5, 1, "", "_collUpdate"], + [2, 5, 1, "", "_collView"], + [2, 5, 1, "", "_coll_rem"], + [2, 4, 1, "", "_ctxt_settings"], + [2, 4, 1, "", "_cur_alias_prefix"], + [2, 4, 1, "", "_cur_coll"], + [2, 4, 1, "", "_cur_coll_prefix"], + [2, 4, 1, "", "_cur_coll_title"], + [2, 4, 1, "", "_cur_ctx"], + [2, 5, 1, "", "_data"], + [2, 5, 1, "", "_dataCreate"], + [2, 5, 1, "", "_dataDelete"], + [2, 5, 1, "", "_dataGet"], + [2, 5, 1, "", "_dataPut"], + [2, 5, 1, "", "_dataUpdate"], + [2, 5, 1, "", "_dataView"], + [2, 5, 1, "", "_data_batch_create"], + [2, 5, 1, "", "_data_batch_update"], + [2, 4, 1, "", "_devnull"], + [2, 5, 1, "", "_ep"], + [2, 5, 1, "", "_epDefault"], + [2, 5, 1, "", "_epDefaultGet"], + [2, 5, 1, "", "_epDefaultSet"], + [2, 5, 1, "", "_epGet"], + [2, 5, 1, "", "_epList"], + [2, 5, 1, "", "_epSet"], + [2, 5, 1, "", "_exit_cli"], + [2, 5, 1, "", "_genDoc"], + [2, 5, 1, "", "_genDocCmd"], + [2, 5, 1, "", "_genDocHeader"], + [2, 5, 1, "", "_generic_reply_handler"], + [2, 5, 1, "", "_global_context_options"], + [2, 5, 1, "", "_global_output_options"], + [2, 4, 1, "", "_hdr_lev_char"], + [2, 5, 1, "", "_help_cli"], + [2, 5, 1, "", "_initialize"], + [2, 4, 1, "", "_initialized"], + [2, 4, 1, "", "_interactive"], + [2, 5, 1, "", "_list"], + [2, 4, 1, "", "_list_items"], + [2, 4, 1, "", "_output_mode"], + [2, 4, 1, "", "_output_mode_sticky"], + [2, 4, 1, "", "_prev_coll"], + [2, 4, 1, "", "_prev_ctx"], + [2, 5, 1, "", "_printJSON"], + [2, 5, 1, "", "_printJSON_List"], + [2, 5, 1, "", "_print_ack_reply"], + [2, 5, 1, "", "_print_batch"], + [2, 5, 1, "", "_print_coll"], + [2, 5, 1, "", "_print_data"], + [2, 5, 1, "", "_print_deps"], + [2, 5, 1, "", "_print_endpoints"], + [2, 5, 1, "", "_print_listing"], + [2, 5, 1, "", "_print_msg"], + [2, 5, 1, "", "_print_path"], + [2, 5, 1, "", "_print_proj"], + [2, 5, 1, "", "_print_proj_listing"], + [2, 5, 1, "", "_print_query"], + [2, 5, 1, "", "_print_task"], + [2, 5, 1, "", "_print_task_array"], + [2, 5, 1, "", "_print_task_listing"], + [2, 5, 1, "", "_print_user"], + [2, 5, 1, "", "_print_user_listing"], + [2, 5, 1, "", "_project"], + [2, 5, 1, "", "_projectList"], + [2, 5, 1, "", "_projectView"], + [2, 5, 1, "", "_query"], + [2, 5, 1, "", "_queryCreate"], + [2, 5, 1, "", "_queryDelete"], + [2, 5, 1, "", "_queryExec"], + [2, 5, 1, "", "_queryList"], + [2, 5, 1, "", "_queryRun"], + [2, 5, 1, "", "_queryUpdate"], + [2, 5, 1, "", "_queryView"], + [2, 5, 1, "", "_resolve_coll_id"], + [2, 5, 1, "", "_resolve_id"], + [2, 4, 1, "", "_return_val"], + [2, 5, 1, "", "_setWorkingCollectionTitle"], + [2, 5, 1, "", "_set_script_cb"], + [2, 5, 1, "", "_set_verbosity_cb"], + [2, 5, 1, "", "_setup"], + [2, 5, 1, "", "_shares"], + [2, 5, 1, "", "_task"], + [2, 5, 1, "", "_taskList"], + [2, 5, 1, "", "_taskView"], + [2, 4, 1, "", "_task_statuses"], + [2, 4, 1, "", "_task_types"], + [2, 4, 1, "", "_uid"], + [2, 5, 1, "", "_user"], + [2, 5, 1, "", "_userListAll"], + [2, 5, 1, "", "_userListCollab"], + [2, 5, 1, "", "_userView"], + [2, 5, 1, "", "_userWho"], + [2, 4, 1, "", "_verbosity"], + [2, 5, 1, "", "_verbositySet"], + [2, 4, 1, "", "_verbosity_sticky"], + [2, 5, 1, "", "_wc"], + [2, 5, 1, "", "_wp"], + [2, 5, 1, "", "_wrap_text"], + [2, 5, 1, "", "command"], + [2, 5, 1, "", "init"], + [2, 5, 1, "", "loginByPassword"], + [2, 5, 1, "", "loginByToken"], + [2, 5, 1, "", "run"], + ], + "datafed.CLI._AliasedGroup": [ + [2, 2, 1, "", "get_command"], + [2, 2, 1, "", "resolve_command"], + ], + "datafed.CLI._AliasedGroupRoot": [[2, 2, 1, "", "get_command"]], + "datafed.CommandLib": [[3, 1, 1, "", "API"]], + "datafed.CommandLib.API": [ + [3, 2, 1, "", "_buildSearchRequest"], + [3, 6, 1, "", "_endpoint_legacy"], + [3, 6, 1, "", "_endpoint_uuid"], + [3, 6, 1, "", "_max_md_size"], + [3, 6, 1, "", "_max_payload_size"], + [3, 2, 1, "", "_resolvePathForGlobus"], + [3, 2, 1, "", "_resolvePathForHTTP"], + [3, 2, 1, "", "_resolve_id"], + [3, 2, 1, "", "_setSaneDefaultOptions"], + [3, 2, 1, "", "_uniquifyFilename"], + [3, 2, 1, "", "collectionCreate"], + [3, 2, 1, "", "collectionDelete"], + [3, 2, 1, "", "collectionGetParents"], + [3, 2, 1, "", "collectionItemsList"], + [3, 2, 1, "", "collectionItemsUpdate"], + [3, 2, 1, "", "collectionUpdate"], + [3, 2, 1, "", "collectionView"], + [3, 2, 1, "", "dataBatchCreate"], + [3, 2, 1, "", "dataBatchUpdate"], + [3, 2, 1, "", "dataCreate"], + [3, 2, 1, "", "dataDelete"], + [3, 2, 1, "", "dataGet"], + [3, 2, 1, "", "dataPut"], + [3, 2, 1, "", "dataUpdate"], + [3, 2, 1, "", "dataView"], + [3, 2, 1, "", "endpointDefaultGet"], + [3, 2, 1, "", "endpointDefaultSet"], + [3, 2, 1, "", "endpointGet"], + [3, 2, 1, "", "endpointListRecent"], + [3, 2, 1, "", "endpointSet"], + [3, 2, 1, "", "generateCredentials"], + [3, 2, 1, "", "getAuthUser"], + [3, 2, 1, "", "getContext"], + [3, 2, 1, "", "loginByPassword"], + [3, 2, 1, "", "logout"], + [3, 2, 1, "", "projectGetRole"], + [3, 2, 1, "", "projectList"], + [3, 2, 1, "", "projectView"], + [3, 2, 1, "", "queryCreate"], + [3, 2, 1, "", "queryDelete"], + [3, 2, 1, "", "queryDirect"], + [3, 2, 1, "", "queryExec"], + [3, 2, 1, "", "queryList"], + [3, 2, 1, "", "queryUpdate"], + [3, 2, 1, "", "queryView"], + [3, 2, 1, "", "repoAllocationCreate"], + [3, 2, 1, "", "repoAllocationDelete"], + [3, 2, 1, "", "repoCreate"], + [3, 2, 1, "", "repoDelete"], + [3, 2, 1, "", "repoList"], + [3, 2, 1, "", "repoListAllocations"], + [3, 2, 1, "", "setContext"], + [3, 2, 1, "", "setupCredentials"], + [3, 2, 1, "", "sharedList"], + [3, 2, 1, "", "sharedListItems"], + [3, 2, 1, "", "sizeToStr"], + [3, 2, 1, "", "strToTimestamp"], + [3, 2, 1, "", "taskList"], + [3, 2, 1, "", "taskView"], + [3, 2, 1, "", "timestampToStr"], + [3, 2, 1, "", "userListAll"], + [3, 2, 1, "", "userListCollaborators"], + [3, 2, 1, "", "userView"], + ], + "datafed.Config": [ + [4, 1, 1, "", "API"], + [4, 4, 1, "", "_OPT_BOOL"], + [4, 4, 1, "", "_OPT_EAGER"], + [4, 4, 1, "", "_OPT_HIDE"], + [4, 4, 1, "", "_OPT_INT"], + [4, 4, 1, "", "_OPT_NO_CF"], + [4, 4, 1, "", "_OPT_NO_CL"], + [4, 4, 1, "", "_OPT_NO_ENV"], + [4, 4, 1, "", "_OPT_PATH"], + [4, 4, 1, "", "_opt_info"], + ], + "datafed.Config.API": [ + [4, 2, 1, "", "_loadConfigFile"], + [4, 2, 1, "", "_loadEnvironVars"], + [4, 2, 1, "", "_processOptions"], + [4, 2, 1, "", "get"], + [4, 2, 1, "", "getOpts"], + [4, 2, 1, "", "printSettingInfo"], + [4, 2, 1, "", "save"], + [4, 2, 1, "", "set"], + ], + "datafed.Connection": [[5, 1, 1, "", "Connection"]], + "datafed.Connection.Connection": [ + [5, 2, 1, "", "__del__"], + [5, 2, 1, "", "makeMessage"], + [5, 2, 1, "", "recv"], + [5, 2, 1, "", "registerProtocol"], + [5, 2, 1, "", "reset"], + [5, 2, 1, "", "send"], + ], + "datafed.MessageLib": [ + [6, 1, 1, "", "API"], + [6, 5, 1, "", "get_latest_version"], + ], + "datafed.MessageLib.API": [ + [6, 2, 1, "", "getAuthStatus"], + [6, 2, 1, "", "getDailyMessage"], + [6, 2, 1, "", "getDefaultTimeout"], + [6, 2, 1, "", "getNackExceptionEnabled"], + [6, 2, 1, "", "keysLoaded"], + [6, 2, 1, "", "keysValid"], + [6, 2, 1, "", "logout"], + [6, 2, 1, "", "manualAuthByPassword"], + [6, 2, 1, "", "manualAuthByToken"], + [6, 2, 1, "", "recv"], + [6, 2, 1, "", "send"], + [6, 2, 1, "", "sendRecv"], + [6, 2, 1, "", "setDefaultTimeout"], + [6, 2, 1, "", "setNackExceptionEnabled"], + ], + "datafed.SDMS_Anon_pb2": [ + [7, 4, 1, "", "AckReply"], + [7, 4, 1, "", "AuthStatusReply"], + [7, 4, 1, "", "AuthenticateByPasswordRequest"], + [7, 4, 1, "", "AuthenticateByTokenRequest"], + [7, 4, 1, "", "DESCRIPTOR"], + [7, 4, 1, "", "DailyMessageReply"], + [7, 4, 1, "", "DailyMessageRequest"], + [7, 4, 1, "", "GetAuthStatusRequest"], + [7, 4, 1, "", "ID"], + [7, 4, 1, "", "NackReply"], + [7, 4, 1, "", "Protocol"], + [7, 4, 1, "", "VersionReply"], + [7, 4, 1, "", "VersionRequest"], + [7, 4, 1, "", "_ACKREPLY"], + [7, 4, 1, "", "_AUTHENTICATEBYPASSWORDREQUEST"], + [7, 4, 1, "", "_AUTHENTICATEBYTOKENREQUEST"], + [7, 4, 1, "", "_AUTHSTATUSREPLY"], + [7, 4, 1, "", "_DAILYMESSAGEREPLY"], + [7, 4, 1, "", "_DAILYMESSAGEREQUEST"], + [7, 4, 1, "", "_GETAUTHSTATUSREQUEST"], + [7, 4, 1, "", "_NACKREPLY"], + [7, 4, 1, "", "_PROTOCOL"], + [7, 4, 1, "", "_VERSIONREPLY"], + [7, 4, 1, "", "_VERSIONREQUEST"], + [7, 4, 1, "id30", "_msg_name_to_type"], + [7, 4, 1, "id31", "_msg_type_to_name"], + [7, 4, 1, "", "_sym_db"], + ], + "datafed.SDMS_Auth_pb2": [ + [8, 4, 1, "", "ACLDataReply"], + [8, 4, 1, "", "ACLSharedListItemsRequest"], + [8, 4, 1, "", "ACLSharedListRequest"], + [8, 4, 1, "", "ACLUpdateRequest"], + [8, 4, 1, "", "ACLViewRequest"], + [8, 4, 1, "", "CheckPermsReply"], + [8, 4, 1, "", "CheckPermsRequest"], + [8, 4, 1, "", "CollCreateRequest"], + [8, 4, 1, "", "CollDataReply"], + [8, 4, 1, "", "CollDeleteRequest"], + [8, 4, 1, "", "CollGetOffsetReply"], + [8, 4, 1, "", "CollGetOffsetRequest"], + [8, 4, 1, "", "CollGetParentsRequest"], + [8, 4, 1, "", "CollListPublishedRequest"], + [8, 4, 1, "", "CollMoveRequest"], + [8, 4, 1, "", "CollPathReply"], + [8, 4, 1, "", "CollReadRequest"], + [8, 4, 1, "", "CollUpdateRequest"], + [8, 4, 1, "", "CollViewRequest"], + [8, 4, 1, "", "CollWriteRequest"], + [8, 4, 1, "", "DESCRIPTOR"], + [8, 4, 1, "", "DataDeleteRequest"], + [8, 4, 1, "", "DataGetReply"], + [8, 4, 1, "", "DataGetRequest"], + [8, 4, 1, "", "DataPathReply"], + [8, 4, 1, "", "DataPathRequest"], + [8, 4, 1, "", "DataPutReply"], + [8, 4, 1, "", "DataPutRequest"], + [8, 4, 1, "", "GenerateCredentialsReply"], + [8, 4, 1, "", "GenerateCredentialsRequest"], + [8, 4, 1, "", "GetPermsReply"], + [8, 4, 1, "", "GetPermsRequest"], + [8, 4, 1, "", "GroupCreateRequest"], + [8, 4, 1, "", "GroupDataReply"], + [8, 4, 1, "", "GroupDeleteRequest"], + [8, 4, 1, "", "GroupListRequest"], + [8, 4, 1, "", "GroupUpdateRequest"], + [8, 4, 1, "", "GroupViewRequest"], + [8, 4, 1, "", "ID"], + [8, 4, 1, "", "ListingReply"], + [8, 4, 1, "", "MetadataValidateReply"], + [8, 4, 1, "", "MetadataValidateRequest"], + [8, 4, 1, "", "NoteCommentEditRequest"], + [8, 4, 1, "", "NoteCreateRequest"], + [8, 4, 1, "", "NoteDataReply"], + [8, 4, 1, "", "NoteListBySubjectRequest"], + [8, 4, 1, "", "NoteUpdateRequest"], + [8, 4, 1, "", "NoteViewRequest"], + [8, 4, 1, "", "ProjectCreateRequest"], + [8, 4, 1, "", "ProjectDataReply"], + [8, 4, 1, "", "ProjectDeleteRequest"], + [8, 4, 1, "", "ProjectGetRoleReply"], + [8, 4, 1, "", "ProjectGetRoleRequest"], + [8, 4, 1, "", "ProjectListRequest"], + [8, 4, 1, "", "ProjectSearchRequest"], + [8, 4, 1, "", "ProjectUpdateRequest"], + [8, 4, 1, "", "ProjectViewRequest"], + [8, 4, 1, "", "Protocol"], + [8, 4, 1, "", "QueryCreateRequest"], + [8, 4, 1, "", "QueryDataReply"], + [8, 4, 1, "", "QueryDeleteRequest"], + [8, 4, 1, "", "QueryExecRequest"], + [8, 4, 1, "", "QueryListRequest"], + [8, 4, 1, "", "QueryUpdateRequest"], + [8, 4, 1, "", "QueryViewRequest"], + [8, 4, 1, "", "RecordAllocChangeReply"], + [8, 4, 1, "", "RecordAllocChangeRequest"], + [8, 4, 1, "", "RecordCreateBatchRequest"], + [8, 4, 1, "", "RecordCreateRequest"], + [8, 4, 1, "", "RecordDataReply"], + [8, 4, 1, "", "RecordDeleteRequest"], + [8, 4, 1, "", "RecordExportReply"], + [8, 4, 1, "", "RecordExportRequest"], + [8, 4, 1, "", "RecordGetDependencyGraphRequest"], + [8, 4, 1, "", "RecordListByAllocRequest"], + [8, 4, 1, "", "RecordLockRequest"], + [8, 4, 1, "", "RecordOwnerChangeReply"], + [8, 4, 1, "", "RecordOwnerChangeRequest"], + [8, 4, 1, "", "RecordUpdateBatchRequest"], + [8, 4, 1, "", "RecordUpdateRequest"], + [8, 4, 1, "", "RecordViewRequest"], + [8, 4, 1, "", "RepoAllocationCreateRequest"], + [8, 4, 1, "", "RepoAllocationDeleteRequest"], + [8, 4, 1, "", "RepoAllocationSetDefaultRequest"], + [8, 4, 1, "", "RepoAllocationSetRequest"], + [8, 4, 1, "", "RepoAllocationStatsReply"], + [8, 4, 1, "", "RepoAllocationStatsRequest"], + [8, 4, 1, "", "RepoAllocationsReply"], + [8, 4, 1, "", "RepoAuthzRequest"], + [8, 4, 1, "", "RepoCalcSizeReply"], + [8, 4, 1, "", "RepoCalcSizeRequest"], + [8, 4, 1, "", "RepoCreateRequest"], + [8, 4, 1, "", "RepoDataDeleteRequest"], + [8, 4, 1, "", "RepoDataGetSizeRequest"], + [8, 4, 1, "", "RepoDataReply"], + [8, 4, 1, "", "RepoDataSizeReply"], + [8, 4, 1, "", "RepoDeleteRequest"], + [8, 4, 1, "", "RepoListAllocationsRequest"], + [8, 4, 1, "", "RepoListObjectAllocationsRequest"], + [8, 4, 1, "", "RepoListRequest"], + [8, 4, 1, "", "RepoListSubjectAllocationsRequest"], + [8, 4, 1, "", "RepoPathCreateRequest"], + [8, 4, 1, "", "RepoPathDeleteRequest"], + [8, 4, 1, "", "RepoUpdateRequest"], + [8, 4, 1, "", "RepoViewAllocationRequest"], + [8, 4, 1, "", "RepoViewRequest"], + [8, 4, 1, "", "RevokeCredentialsRequest"], + [8, 4, 1, "", "SchemaCreateRequest"], + [8, 4, 1, "", "SchemaDataReply"], + [8, 4, 1, "", "SchemaDeleteRequest"], + [8, 4, 1, "", "SchemaReviseRequest"], + [8, 4, 1, "", "SchemaSearchRequest"], + [8, 4, 1, "", "SchemaUpdateRequest"], + [8, 4, 1, "", "SchemaViewRequest"], + [8, 4, 1, "", "SearchRequest"], + [8, 4, 1, "", "TagDataReply"], + [8, 4, 1, "", "TagListByCountRequest"], + [8, 4, 1, "", "TagSearchRequest"], + [8, 4, 1, "", "TaskDataReply"], + [8, 4, 1, "", "TaskListRequest"], + [8, 4, 1, "", "TaskViewRequest"], + [8, 4, 1, "", "TopicDataReply"], + [8, 4, 1, "", "TopicListTopicsRequest"], + [8, 4, 1, "", "TopicSearchRequest"], + [8, 4, 1, "", "TopicViewRequest"], + [8, 4, 1, "", "UserAccessTokenReply"], + [8, 4, 1, "", "UserCreateRequest"], + [8, 4, 1, "", "UserDataReply"], + [8, 4, 1, "", "UserFindByNameUIDRequest"], + [8, 4, 1, "", "UserFindByUUIDsRequest"], + [8, 4, 1, "", "UserGetAccessTokenRequest"], + [8, 4, 1, "", "UserGetRecentEPReply"], + [8, 4, 1, "", "UserGetRecentEPRequest"], + [8, 4, 1, "", "UserListAllRequest"], + [8, 4, 1, "", "UserListCollabRequest"], + [8, 4, 1, "", "UserSetAccessTokenRequest"], + [8, 4, 1, "", "UserSetRecentEPRequest"], + [8, 4, 1, "", "UserUpdateRequest"], + [8, 4, 1, "", "UserViewRequest"], + [8, 4, 1, "", "_ACLDATAREPLY"], + [8, 4, 1, "", "_ACLSHAREDLISTITEMSREQUEST"], + [8, 4, 1, "", "_ACLSHAREDLISTREQUEST"], + [8, 4, 1, "", "_ACLUPDATEREQUEST"], + [8, 4, 1, "", "_ACLVIEWREQUEST"], + [8, 4, 1, "", "_CHECKPERMSREPLY"], + [8, 4, 1, "", "_CHECKPERMSREQUEST"], + [8, 4, 1, "", "_COLLCREATEREQUEST"], + [8, 4, 1, "", "_COLLDATAREPLY"], + [8, 4, 1, "", "_COLLDELETEREQUEST"], + [8, 4, 1, "", "_COLLGETOFFSETREPLY"], + [8, 4, 1, "", "_COLLGETOFFSETREQUEST"], + [8, 4, 1, "", "_COLLGETPARENTSREQUEST"], + [8, 4, 1, "", "_COLLLISTPUBLISHEDREQUEST"], + [8, 4, 1, "", "_COLLMOVEREQUEST"], + [8, 4, 1, "", "_COLLPATHREPLY"], + [8, 4, 1, "", "_COLLREADREQUEST"], + [8, 4, 1, "", "_COLLUPDATEREQUEST"], + [8, 4, 1, "", "_COLLVIEWREQUEST"], + [8, 4, 1, "", "_COLLWRITEREQUEST"], + [8, 4, 1, "", "_DATADELETEREQUEST"], + [8, 4, 1, "", "_DATAGETREPLY"], + [8, 4, 1, "", "_DATAGETREQUEST"], + [8, 4, 1, "", "_DATAPATHREPLY"], + [8, 4, 1, "", "_DATAPATHREQUEST"], + [8, 4, 1, "", "_DATAPUTREPLY"], + [8, 4, 1, "", "_DATAPUTREQUEST"], + [8, 4, 1, "", "_GENERATECREDENTIALSREPLY"], + [8, 4, 1, "", "_GENERATECREDENTIALSREQUEST"], + [8, 4, 1, "", "_GETPERMSREPLY"], + [8, 4, 1, "", "_GETPERMSREQUEST"], + [8, 4, 1, "", "_GROUPCREATEREQUEST"], + [8, 4, 1, "", "_GROUPDATAREPLY"], + [8, 4, 1, "", "_GROUPDELETEREQUEST"], + [8, 4, 1, "", "_GROUPLISTREQUEST"], + [8, 4, 1, "", "_GROUPUPDATEREQUEST"], + [8, 4, 1, "", "_GROUPVIEWREQUEST"], + [8, 4, 1, "", "_LISTINGREPLY"], + [8, 4, 1, "", "_METADATAVALIDATEREPLY"], + [8, 4, 1, "", "_METADATAVALIDATEREQUEST"], + [8, 4, 1, "", "_NOTECOMMENTEDITREQUEST"], + [8, 4, 1, "", "_NOTECREATEREQUEST"], + [8, 4, 1, "", "_NOTEDATAREPLY"], + [8, 4, 1, "", "_NOTELISTBYSUBJECTREQUEST"], + [8, 4, 1, "", "_NOTEUPDATEREQUEST"], + [8, 4, 1, "", "_NOTEVIEWREQUEST"], + [8, 4, 1, "", "_PROJECTCREATEREQUEST"], + [8, 4, 1, "", "_PROJECTDATAREPLY"], + [8, 4, 1, "", "_PROJECTDELETEREQUEST"], + [8, 4, 1, "", "_PROJECTGETROLEREPLY"], + [8, 4, 1, "", "_PROJECTGETROLEREQUEST"], + [8, 4, 1, "", "_PROJECTLISTREQUEST"], + [8, 4, 1, "", "_PROJECTSEARCHREQUEST"], + [8, 4, 1, "", "_PROJECTUPDATEREQUEST"], + [8, 4, 1, "", "_PROJECTVIEWREQUEST"], + [8, 4, 1, "", "_PROTOCOL"], + [8, 4, 1, "", "_QUERYCREATEREQUEST"], + [8, 4, 1, "", "_QUERYDATAREPLY"], + [8, 4, 1, "", "_QUERYDELETEREQUEST"], + [8, 4, 1, "", "_QUERYEXECREQUEST"], + [8, 4, 1, "", "_QUERYLISTREQUEST"], + [8, 4, 1, "", "_QUERYUPDATEREQUEST"], + [8, 4, 1, "", "_QUERYVIEWREQUEST"], + [8, 4, 1, "", "_RECORDALLOCCHANGEREPLY"], + [8, 4, 1, "", "_RECORDALLOCCHANGEREQUEST"], + [8, 4, 1, "", "_RECORDCREATEBATCHREQUEST"], + [8, 4, 1, "", "_RECORDCREATEREQUEST"], + [8, 4, 1, "", "_RECORDDATAREPLY"], + [8, 4, 1, "", "_RECORDDELETEREQUEST"], + [8, 4, 1, "", "_RECORDEXPORTREPLY"], + [8, 4, 1, "", "_RECORDEXPORTREQUEST"], + [8, 4, 1, "", "_RECORDGETDEPENDENCYGRAPHREQUEST"], + [8, 4, 1, "", "_RECORDLISTBYALLOCREQUEST"], + [8, 4, 1, "", "_RECORDLOCKREQUEST"], + [8, 4, 1, "", "_RECORDOWNERCHANGEREPLY"], + [8, 4, 1, "", "_RECORDOWNERCHANGEREQUEST"], + [8, 4, 1, "", "_RECORDUPDATEBATCHREQUEST"], + [8, 4, 1, "", "_RECORDUPDATEREQUEST"], + [8, 4, 1, "", "_RECORDVIEWREQUEST"], + [8, 4, 1, "", "_REPOALLOCATIONCREATEREQUEST"], + [8, 4, 1, "", "_REPOALLOCATIONDELETEREQUEST"], + [8, 4, 1, "", "_REPOALLOCATIONSETDEFAULTREQUEST"], + [8, 4, 1, "", "_REPOALLOCATIONSETREQUEST"], + [8, 4, 1, "", "_REPOALLOCATIONSREPLY"], + [8, 4, 1, "", "_REPOALLOCATIONSTATSREPLY"], + [8, 4, 1, "", "_REPOALLOCATIONSTATSREQUEST"], + [8, 4, 1, "", "_REPOAUTHZREQUEST"], + [8, 4, 1, "", "_REPOCALCSIZEREPLY"], + [8, 4, 1, "", "_REPOCALCSIZEREQUEST"], + [8, 4, 1, "", "_REPOCREATEREQUEST"], + [8, 4, 1, "", "_REPODATADELETEREQUEST"], + [8, 4, 1, "", "_REPODATAGETSIZEREQUEST"], + [8, 4, 1, "", "_REPODATAREPLY"], + [8, 4, 1, "", "_REPODATASIZEREPLY"], + [8, 4, 1, "", "_REPODELETEREQUEST"], + [8, 4, 1, "", "_REPOLISTALLOCATIONSREQUEST"], + [8, 4, 1, "", "_REPOLISTOBJECTALLOCATIONSREQUEST"], + [8, 4, 1, "", "_REPOLISTREQUEST"], + [8, 4, 1, "", "_REPOLISTSUBJECTALLOCATIONSREQUEST"], + [8, 4, 1, "", "_REPOPATHCREATEREQUEST"], + [8, 4, 1, "", "_REPOPATHDELETEREQUEST"], + [8, 4, 1, "", "_REPOUPDATEREQUEST"], + [8, 4, 1, "", "_REPOVIEWALLOCATIONREQUEST"], + [8, 4, 1, "", "_REPOVIEWREQUEST"], + [8, 4, 1, "", "_REVOKECREDENTIALSREQUEST"], + [8, 4, 1, "", "_SCHEMACREATEREQUEST"], + [8, 4, 1, "", "_SCHEMADATAREPLY"], + [8, 4, 1, "", "_SCHEMADELETEREQUEST"], + [8, 4, 1, "", "_SCHEMAREVISEREQUEST"], + [8, 4, 1, "", "_SCHEMASEARCHREQUEST"], + [8, 4, 1, "", "_SCHEMAUPDATEREQUEST"], + [8, 4, 1, "", "_SCHEMAVIEWREQUEST"], + [8, 4, 1, "", "_SEARCHREQUEST"], + [8, 4, 1, "", "_TAGDATAREPLY"], + [8, 4, 1, "", "_TAGLISTBYCOUNTREQUEST"], + [8, 4, 1, "", "_TAGSEARCHREQUEST"], + [8, 4, 1, "", "_TASKDATAREPLY"], + [8, 4, 1, "", "_TASKLISTREQUEST"], + [8, 4, 1, "", "_TASKVIEWREQUEST"], + [8, 4, 1, "", "_TOPICDATAREPLY"], + [8, 4, 1, "", "_TOPICLISTTOPICSREQUEST"], + [8, 4, 1, "", "_TOPICSEARCHREQUEST"], + [8, 4, 1, "", "_TOPICVIEWREQUEST"], + [8, 4, 1, "", "_USERACCESSTOKENREPLY"], + [8, 4, 1, "", "_USERCREATEREQUEST"], + [8, 4, 1, "", "_USERDATAREPLY"], + [8, 4, 1, "", "_USERFINDBYNAMEUIDREQUEST"], + [8, 4, 1, "", "_USERFINDBYUUIDSREQUEST"], + [8, 4, 1, "", "_USERGETACCESSTOKENREQUEST"], + [8, 4, 1, "", "_USERGETRECENTEPREPLY"], + [8, 4, 1, "", "_USERGETRECENTEPREQUEST"], + [8, 4, 1, "", "_USERLISTALLREQUEST"], + [8, 4, 1, "", "_USERLISTCOLLABREQUEST"], + [8, 4, 1, "", "_USERSETACCESSTOKENREQUEST"], + [8, 4, 1, "", "_USERSETRECENTEPREQUEST"], + [8, 4, 1, "", "_USERUPDATEREQUEST"], + [8, 4, 1, "", "_USERVIEWREQUEST"], + [8, 4, 1, "id30", "_msg_name_to_type"], + [8, 4, 1, "id31", "_msg_type_to_name"], + [8, 4, 1, "", "_sym_db"], + ], + "datafed.SDMS_pb2": [ + [9, 4, 1, "", "ACLRule"], + [9, 4, 1, "", "AllocData"], + [9, 4, 1, "", "AllocStatsData"], + [9, 4, 1, "", "CollData"], + [9, 4, 1, "", "DEP_IN"], + [9, 4, 1, "", "DEP_IS_COMPONENT_OF"], + [9, 4, 1, "", "DEP_IS_DERIVED_FROM"], + [9, 4, 1, "", "DEP_IS_NEW_VERSION_OF"], + [9, 4, 1, "", "DEP_OUT"], + [9, 4, 1, "", "DEP_TYPE_COUNT"], + [9, 4, 1, "", "DESCRIPTOR"], + [9, 4, 1, "", "DependencyData"], + [9, 4, 1, "", "DependencyDir"], + [9, 4, 1, "", "DependencySpecData"], + [9, 4, 1, "", "DependencyType"], + [9, 4, 1, "", "ENCRYPT_AVAIL"], + [9, 4, 1, "", "ENCRYPT_FORCE"], + [9, 4, 1, "", "ENCRYPT_NONE"], + [9, 4, 1, "", "Encryption"], + [9, 4, 1, "", "ErrorCode"], + [9, 4, 1, "", "GroupData"], + [9, 4, 1, "", "ID_AUTHN_ERROR"], + [9, 4, 1, "", "ID_AUTHN_REQUIRED"], + [9, 4, 1, "", "ID_BAD_REQUEST"], + [9, 4, 1, "", "ID_CLIENT_ERROR"], + [9, 4, 1, "", "ID_DEST_FILE_ERROR"], + [9, 4, 1, "", "ID_DEST_PATH_ERROR"], + [9, 4, 1, "", "ID_INTERNAL_ERROR"], + [9, 4, 1, "", "ID_SERVICE_ERROR"], + [9, 4, 1, "", "ListingData"], + [9, 4, 1, "", "NOTE_ACTIVE"], + [9, 4, 1, "", "NOTE_CLOSED"], + [9, 4, 1, "", "NOTE_ERROR"], + [9, 4, 1, "", "NOTE_INFO"], + [9, 4, 1, "", "NOTE_OPEN"], + [9, 4, 1, "", "NOTE_QUESTION"], + [9, 4, 1, "", "NOTE_WARN"], + [9, 4, 1, "", "NoteComment"], + [9, 4, 1, "", "NoteData"], + [9, 4, 1, "", "NoteState"], + [9, 4, 1, "", "NoteType"], + [9, 4, 1, "", "PROJ_ADMIN"], + [9, 4, 1, "", "PROJ_MANAGER"], + [9, 4, 1, "", "PROJ_MEMBER"], + [9, 4, 1, "", "PROJ_NO_ROLE"], + [9, 4, 1, "", "PathData"], + [9, 4, 1, "", "ProjectData"], + [9, 4, 1, "", "ProjectRole"], + [9, 4, 1, "", "RecordData"], + [9, 4, 1, "", "RecordDataLocation"], + [9, 4, 1, "", "RecordDataSize"], + [9, 4, 1, "", "RepoData"], + [9, 4, 1, "", "RepoRecordDataLocations"], + [9, 4, 1, "", "SM_COLLECTION"], + [9, 4, 1, "", "SM_DATA"], + [9, 4, 1, "", "SORT_ID"], + [9, 4, 1, "", "SORT_OWNER"], + [9, 4, 1, "", "SORT_RELEVANCE"], + [9, 4, 1, "", "SORT_TIME_CREATE"], + [9, 4, 1, "", "SORT_TIME_UPDATE"], + [9, 4, 1, "", "SORT_TITLE"], + [9, 4, 1, "", "SS_DEGRADED"], + [9, 4, 1, "", "SS_FAILED"], + [9, 4, 1, "", "SS_NORMAL"], + [9, 4, 1, "", "SS_OFFLINE"], + [9, 4, 1, "", "SchemaData"], + [9, 4, 1, "", "SearchMode"], + [9, 4, 1, "", "ServiceStatus"], + [9, 4, 1, "", "SortOption"], + [9, 4, 1, "", "TC_ALLOC_CREATE"], + [9, 4, 1, "", "TC_ALLOC_DELETE"], + [9, 4, 1, "", "TC_RAW_DATA_DELETE"], + [9, 4, 1, "", "TC_RAW_DATA_TRANSFER"], + [9, 4, 1, "", "TC_RAW_DATA_UPDATE_SIZE"], + [9, 4, 1, "", "TC_STOP"], + [9, 4, 1, "", "TS_BLOCKED"], + [9, 4, 1, "", "TS_FAILED"], + [9, 4, 1, "", "TS_READY"], + [9, 4, 1, "", "TS_RUNNING"], + [9, 4, 1, "", "TS_SUCCEEDED"], + [9, 4, 1, "", "TT_ALLOC_CREATE"], + [9, 4, 1, "", "TT_ALLOC_DEL"], + [9, 4, 1, "", "TT_DATA_DEL"], + [9, 4, 1, "", "TT_DATA_GET"], + [9, 4, 1, "", "TT_DATA_PUT"], + [9, 4, 1, "", "TT_PROJ_DEL"], + [9, 4, 1, "", "TT_REC_CHG_ALLOC"], + [9, 4, 1, "", "TT_REC_CHG_OWNER"], + [9, 4, 1, "", "TT_REC_DEL"], + [9, 4, 1, "", "TT_USER_DEL"], + [9, 4, 1, "", "TagData"], + [9, 4, 1, "", "TaskCommand"], + [9, 4, 1, "", "TaskData"], + [9, 4, 1, "", "TaskStatus"], + [9, 4, 1, "", "TaskType"], + [9, 4, 1, "", "TopicData"], + [9, 4, 1, "", "UserData"], + [9, 4, 1, "", "_ACLRULE"], + [9, 4, 1, "", "_ALLOCDATA"], + [9, 4, 1, "", "_ALLOCSTATSDATA"], + [9, 4, 1, "", "_COLLDATA"], + [9, 4, 1, "", "_DEPENDENCYDATA"], + [9, 4, 1, "", "_DEPENDENCYDIR"], + [9, 4, 1, "", "_DEPENDENCYSPECDATA"], + [9, 4, 1, "", "_DEPENDENCYTYPE"], + [9, 4, 1, "", "_ENCRYPTION"], + [9, 4, 1, "", "_ERRORCODE"], + [9, 4, 1, "", "_GROUPDATA"], + [9, 4, 1, "", "_LISTINGDATA"], + [9, 4, 1, "", "_NOTECOMMENT"], + [9, 4, 1, "", "_NOTEDATA"], + [9, 4, 1, "", "_NOTESTATE"], + [9, 4, 1, "", "_NOTETYPE"], + [9, 4, 1, "", "_PATHDATA"], + [9, 4, 1, "", "_PROJECTDATA"], + [9, 4, 1, "", "_PROJECTROLE"], + [9, 4, 1, "", "_RECORDDATA"], + [9, 4, 1, "", "_RECORDDATALOCATION"], + [9, 4, 1, "", "_RECORDDATASIZE"], + [9, 4, 1, "", "_REPODATA"], + [9, 4, 1, "", "_REPORECORDDATALOCATIONS"], + [9, 4, 1, "", "_SCHEMADATA"], + [9, 4, 1, "", "_SEARCHMODE"], + [9, 4, 1, "", "_SERVICESTATUS"], + [9, 4, 1, "", "_SORTOPTION"], + [9, 4, 1, "", "_TAGDATA"], + [9, 4, 1, "", "_TASKCOMMAND"], + [9, 4, 1, "", "_TASKDATA"], + [9, 4, 1, "", "_TASKSTATUS"], + [9, 4, 1, "", "_TASKTYPE"], + [9, 4, 1, "", "_TOPICDATA"], + [9, 4, 1, "", "_USERDATA"], + [9, 4, 1, "", "_sym_db"], + ], + "datafed.VERSION": [[10, 4, 1, "", "__version__"]], + "datafed.Version_pb2": [ + [11, 4, 1, "", "DATAFED_COMMON_PROTOCOL_API_MAJOR"], + [11, 4, 1, "", "DATAFED_COMMON_PROTOCOL_API_MINOR"], + [11, 4, 1, "", "DATAFED_COMMON_PROTOCOL_API_PATCH"], + [11, 4, 1, "", "DATAFED_RELEASE_DAY"], + [11, 4, 1, "", "DATAFED_RELEASE_HOUR"], + [11, 4, 1, "", "DATAFED_RELEASE_MINUTE"], + [11, 4, 1, "", "DATAFED_RELEASE_MONTH"], + [11, 4, 1, "", "DATAFED_RELEASE_YEAR"], + [11, 4, 1, "", "DESCRIPTOR"], + [11, 4, 1, "", "Version"], + [11, 4, 1, "", "_VERSION"], + [11, 4, 1, "", "_sym_db"], + ], + }, + objtypes: { + 0: "py:module", + 1: "py:class", + 2: "py:method", + 3: "py:exception", + 4: "py:data", + 5: "py:function", + 6: "py:attribute", + }, + objnames: { + 0: ["py", "module", "Python module"], + 1: ["py", "class", "Python class"], + 2: ["py", "method", "Python method"], + 3: ["py", "exception", "Python exception"], + 4: ["py", "data", "Python data"], + 5: ["py", "function", "Python function"], + 6: ["py", "attribute", "Python attribute"], + }, + titleterms: { + dataf: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 18, 19, 20, 26, 28], + command: [0, 18, 24, 26], + coll: [0, 26], + add: [0, 26, 28], + creat: [0, 24, 26, 28], + delet: [0, 26], + remov: [0, 26, 28], + updat: [0, 26], + view: [0, 24, 26, 28], + data: [0, 1, 18, 19, 20, 21, 24, 26, 28, 30], + batch: [0, 26, 28], + get: [0, 19, 26, 28], + put: [0, 26], + ep: [0, 26], + default: [0, 26, 27, 28], + set: [0, 26, 27, 28, 30], + list: [0, 26, 28], + exit: [0, 26], + help: [0, 24, 26], + l: [0, 26], + project: [0, 15, 21, 26, 28, 30], + queri: [0, 26, 28], + exec: [0, 26], + run: [0, 26], + setup: [0, 26], + share: [0, 26, 30], + task: [0, 26, 28], + user: [0, 17, 21, 24, 26], + all: [0, 26], + collab: [0, 26], + who: [0, 26], + verbos: [0, 26], + wc: [0, 26], + wp: [0, 26], + administr: [1, 18], + system: [1, 21], + deploy: 1, + download: [1, 24, 28], + instal: [1, 19, 27], + depend: 1, + gener: 1, + configur: [1, 27], + databas: 1, + core: 1, + servic: 1, + web: [1, 18, 30], + repositori: [1, 21], + authz: 1, + librari: 1, + network: 1, + cli: 2, + modul: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11], + content: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 28], + class: [2, 3, 4, 5, 6], + function: [2, 6, 28], + attribut: [2, 3, 4], + commandlib: 3, + paramet: 3, + rais: 3, + return: 3, + config: [4, 27], + connect: 5, + messagelib: 6, + sdms_anon_pb2: 7, + sdms_auth_pb2: 8, + sdms_pb2: 9, + version: 10, + version_pb2: 11, + submodul: 12, + packag: [12, 18, 27, 28], + api: 13, + refer: [13, 21, 26, 27], + architectur: [14, 21], + design: 14, + manag: [15, 20, 21, 28], + personnel: 15, + releas: 16, + note: 16, + 1: [16, 19, 27], + 2: [16, 19, 27], + 0: [16, 27], + 4: [16, 19], + mai: 16, + 28: 16, + 2021: 16, + new: [16, 17], + featur: [16, 17], + impact: 16, + exist: 16, + enhanc: 16, + bug: 16, + fix: 16, + known: 16, + issu: 16, + road: 17, + map: 17, + plan: 17, + product: 17, + relat: 17, + chang: 17, + potenti: 17, + A: 18, + scientif: [18, 20, 24, 28], + feder: 18, + document: [18, 24], + about: 18, + portal: [18, 30], + client: [18, 27], + line: 18, + interfac: [18, 19, 21, 28], + python: [18, 27], + develop: 18, + indic: 18, + tabl: 18, + start: [19, 28], + globu: 19, + account: [19, 21], + id: [19, 28], + 3: [19, 27], + regist: 19, + alloc: [19, 21], + 5: 19, + identifi: [19, 21], + endpoint: [19, 27], + high: [19, 28], + perform: 19, + comput: 19, + cluster: 19, + person: [19, 30], + workstat: 19, + 6: 19, + activ: 19, + program: 19, + introduct: [20, 24], + background: 20, + lifecycl: 20, + why: 20, + overview: 21, + cross: 21, + facil: 21, + concept: 21, + quick: [21, 27], + alias: [21, 28], + record: [21, 24, 28], + metadata: [21, 24, 28], + proven: [21, 28], + raw: [21, 24, 28], + field: 21, + summari: 21, + collect: [21, 28], + root: 21, + public: [21, 27], + access: 21, + control: 21, + schema: 21, + tag: 21, + annot: 21, + search: [21, 30], + catalog: 21, + paper: 22, + present: 22, + us: 23, + case: 23, + guid: [24, 28, 30], + syntax: 24, + shortcut: 24, + upload: [24, 28], + comment: 24, + prerequisit: 27, + ensur: 27, + bin: 27, + directori: 27, + i: 27, + path: 27, + basic: 27, + advanc: 27, + file: 27, + prioriti: 27, + automat: 27, + authent: 27, + server: 27, + kei: 27, + host: 27, + port: 27, + privat: 27, + level: 28, + import: 28, + instanc: 28, + respons: 28, + subcript: 28, + messag: 28, + object: 28, + iter: 28, + through: 28, + item: 28, + explor: 28, + context: 28, + per: 28, + alia: 28, + v: 28, + manual: 28, + work: 28, + prepar: 28, + extract: 28, + edit: 28, + inform: [28, 30], + replac: 28, + relationship: 28, + oper: 28, + other: 28, + transfer: [28, 30], + asynchron: 28, + popul: 28, + save: 28, + execut: 28, + continu: 28, + organ: 28, + parent: 28, + from: 28, + close: 28, + remark: 28, + jupyt: 29, + notebook: 29, + drag: 30, + drop: 30, + result: 30, + panel: 30, + action: 30, + button: 30, + header: 30, + footer: 30, + }, + envversion: { + "sphinx.domains.c": 3, + "sphinx.domains.changeset": 1, + "sphinx.domains.citation": 1, + "sphinx.domains.cpp": 9, + "sphinx.domains.index": 1, + "sphinx.domains.javascript": 3, + "sphinx.domains.math": 2, + "sphinx.domains.python": 4, + "sphinx.domains.rst": 2, + "sphinx.domains.std": 2, + sphinx: 58, + }, + alltitles: { + "Datafed Commands": [ + [0, "datafed-commands"], + [26, "datafed-commands"], + ], + "Coll Commands": [ + [0, "coll-commands"], + [26, "coll-commands"], + ], + "Coll Add Command": [ + [0, "coll-add-command"], + [26, "coll-add-command"], + ], + "Coll Create Command": [ + [0, "coll-create-command"], + [26, "coll-create-command"], + ], + "Coll Delete Command": [ + [0, "coll-delete-command"], + [26, "coll-delete-command"], + ], + "Coll Remove Command": [ + [0, "coll-remove-command"], + [26, "coll-remove-command"], + ], + "Coll Update Command": [ + [0, "coll-update-command"], + [26, "coll-update-command"], + ], + "Coll View Command": [ + [0, "coll-view-command"], + [26, "coll-view-command"], + ], + "Data Commands": [ + [0, "data-commands"], + [26, "data-commands"], + ], + "Data Batch Commands": [ + [0, "data-batch-commands"], + [26, "data-batch-commands"], + ], + "Data Batch Create Command": [ + [0, "data-batch-create-command"], + [26, "data-batch-create-command"], + ], + "Data Batch Update Command": [ + [0, "data-batch-update-command"], + [26, "data-batch-update-command"], + ], + "Data Create Command": [ + [0, "data-create-command"], + [26, "data-create-command"], + ], + "Data Delete Command": [ + [0, "data-delete-command"], + [26, "data-delete-command"], + ], + "Data Get Command": [ + [0, "data-get-command"], + [26, "data-get-command"], + ], + "Data Put Command": [ + [0, "data-put-command"], + [26, "data-put-command"], + ], + "Data Update Command": [ + [0, "data-update-command"], + [26, "data-update-command"], + ], + "Data View Command": [ + [0, "data-view-command"], + [26, "data-view-command"], + ], + "Ep Commands": [ + [0, "ep-commands"], + [26, "ep-commands"], + ], + "Ep Default Commands": [ + [0, "ep-default-commands"], + [26, "ep-default-commands"], + ], + "Ep Default Get Command": [ + [0, "ep-default-get-command"], + [26, "ep-default-get-command"], + ], + "Ep Default Set Command": [ + [0, "ep-default-set-command"], + [26, "ep-default-set-command"], + ], + "Ep Get Command": [ + [0, "ep-get-command"], + [26, "ep-get-command"], + ], + "Ep List Command": [ + [0, "ep-list-command"], + [26, "ep-list-command"], + ], + "Ep Set Command": [ + [0, "ep-set-command"], + [26, "ep-set-command"], + ], + "Exit Command": [ + [0, "exit-command"], + [26, "exit-command"], + ], + "Help Command": [ + [0, "help-command"], + [26, "help-command"], + ], + "Ls Command": [ + [0, "ls-command"], + [26, "ls-command"], + ], + "Project Commands": [ + [0, "project-commands"], + [26, "project-commands"], + ], + "Project List Command": [ + [0, "project-list-command"], + [26, "project-list-command"], + ], + "Project View Command": [ + [0, "project-view-command"], + [26, "project-view-command"], + ], + "Query Commands": [ + [0, "query-commands"], + [26, "query-commands"], + ], + "Query Create Command": [ + [0, "query-create-command"], + [26, "query-create-command"], + ], + "Query Delete Command": [ + [0, "query-delete-command"], + [26, "query-delete-command"], + ], + "Query Exec Command": [ + [0, "query-exec-command"], + [26, "query-exec-command"], + ], + "Query List Command": [ + [0, "query-list-command"], + [26, "query-list-command"], + ], + "Query Run Command": [ + [0, "query-run-command"], + [26, "query-run-command"], + ], + "Query Update Command": [ + [0, "query-update-command"], + [26, "query-update-command"], + ], + "Query View Command": [ + [0, "query-view-command"], + [26, "query-view-command"], + ], + "Setup Command": [ + [0, "setup-command"], + [26, "setup-command"], + ], + "Shares Command": [ + [0, "shares-command"], + [26, "shares-command"], + ], + "Task Commands": [ + [0, "task-commands"], + [26, "task-commands"], + ], + "Task List Command": [ + [0, "task-list-command"], + [26, "task-list-command"], + ], + "Task View Command": [ + [0, "task-view-command"], + [26, "task-view-command"], + ], + "User Commands": [ + [0, "user-commands"], + [26, "user-commands"], + ], + "User All Command": [ + [0, "user-all-command"], + [26, "user-all-command"], + ], + "User Collab Command": [ + [0, "user-collab-command"], + [26, "user-collab-command"], + ], + "User View Command": [ + [0, "user-view-command"], + [26, "user-view-command"], + ], + "User Who Command": [ + [0, "user-who-command"], + [26, "user-who-command"], + ], + "Verbosity Command": [ + [0, "verbosity-command"], + [26, "verbosity-command"], + ], + "Wc Command": [ + [0, "wc-command"], + [26, "wc-command"], + ], + "Wp Command": [ + [0, "wp-command"], + [26, "wp-command"], + ], + Administration: [ + [1, "administration"], + [18, null], + ], + "System Deployment": [[1, "system-deployment"]], + "Downloading DataFed & Installing Dependencies": [ + [1, "downloading-datafed-installing-dependencies"], + ], + "General Installation & Configuration": [[1, "general-installation-configuration"]], + Database: [[1, "database"]], + "Core Service": [[1, "core-service"]], + "Web Service": [[1, "web-service"]], + "Data Repository": [[1, "data-repository"]], + "Authz Library": [[1, "authz-library"]], + Networking: [[1, "networking"]], + "datafed.CLI": [[2, "module-datafed.CLI"]], + "Module Contents": [ + [2, "module-contents"], + [3, "module-contents"], + [4, "module-contents"], + [5, "module-contents"], + [6, "module-contents"], + [7, "module-contents"], + [8, "module-contents"], + [9, "module-contents"], + [10, "module-contents"], + [11, "module-contents"], + ], + Classes: [ + [2, "classes"], + [3, "classes"], + [4, "classes"], + [5, "classes"], + [6, "classes"], + ], + Functions: [ + [2, "functions"], + [6, "functions"], + ], + Attributes: [ + [2, "attributes"], + [3, "attributes"], + [4, "attributes"], + ], + "datafed.CommandLib": [[3, "module-datafed.CommandLib"]], + Parameters: [ + [3, "parameters"], + [3, "id2"], + [3, "id7"], + [3, "id10"], + [3, "id13"], + [3, "id16"], + [3, "id19"], + [3, "id22"], + [3, "id25"], + [3, "id28"], + [3, "id31"], + [3, "id34"], + [3, "id37"], + [3, "id40"], + [3, "id43"], + [3, "id46"], + [3, "id49"], + [3, "id52"], + [3, "id55"], + [3, "id58"], + [3, "id61"], + [3, "id64"], + [3, "id67"], + [3, "id70"], + [3, "id73"], + [3, "id76"], + [3, "id79"], + [3, "id82"], + [3, "id85"], + [3, "id88"], + [3, "id91"], + [3, "id94"], + [3, "id97"], + [3, "id100"], + [3, "id103"], + [3, "id106"], + [3, "id112"], + [3, "id114"], + [3, "id117"], + [3, "id121"], + [3, "id123"], + [3, "id125"], + [3, "id127"], + [3, "id129"], + [3, "id131"], + [3, "id133"], + ], + Raises: [ + [3, "raises"], + [3, "id4"], + [3, "id6"], + [3, "id9"], + [3, "id12"], + [3, "id15"], + [3, "id18"], + [3, "id21"], + [3, "id24"], + [3, "id27"], + [3, "id30"], + [3, "id33"], + [3, "id36"], + [3, "id39"], + [3, "id42"], + [3, "id45"], + [3, "id48"], + [3, "id51"], + [3, "id54"], + [3, "id57"], + [3, "id60"], + [3, "id63"], + [3, "id66"], + [3, "id69"], + [3, "id72"], + [3, "id75"], + [3, "id78"], + [3, "id81"], + [3, "id84"], + [3, "id87"], + [3, "id90"], + [3, "id93"], + [3, "id96"], + [3, "id99"], + [3, "id102"], + [3, "id105"], + [3, "id108"], + [3, "id110"], + [3, "id116"], + [3, "id119"], + ], + Returns: [ + [3, "returns"], + [3, "id1"], + [3, "id3"], + [3, "id5"], + [3, "id8"], + [3, "id11"], + [3, "id14"], + [3, "id17"], + [3, "id20"], + [3, "id23"], + [3, "id26"], + [3, "id29"], + [3, "id32"], + [3, "id35"], + [3, "id38"], + [3, "id41"], + [3, "id44"], + [3, "id47"], + [3, "id50"], + [3, "id53"], + [3, "id56"], + [3, "id59"], + [3, "id62"], + [3, "id65"], + [3, "id68"], + [3, "id71"], + [3, "id74"], + [3, "id77"], + [3, "id80"], + [3, "id83"], + [3, "id86"], + [3, "id89"], + [3, "id92"], + [3, "id95"], + [3, "id98"], + [3, "id101"], + [3, "id104"], + [3, "id107"], + [3, "id109"], + [3, "id111"], + [3, "id113"], + [3, "id115"], + [3, "id118"], + [3, "id120"], + [3, "id122"], + [3, "id124"], + [3, "id126"], + [3, "id128"], + [3, "id130"], + [3, "id132"], + [3, "id134"], + [3, "id135"], + ], + "datafed.Config": [[4, "module-datafed.Config"]], + "datafed.Connection": [[5, "module-datafed.Connection"]], + "datafed.MessageLib": [[6, "module-datafed.MessageLib"]], + "datafed.SDMS_Anon_pb2": [[7, "module-datafed.SDMS_Anon_pb2"]], + "datafed.SDMS_Auth_pb2": [[8, "module-datafed.SDMS_Auth_pb2"]], + "datafed.SDMS_pb2": [[9, "module-datafed.SDMS_pb2"]], + "datafed.VERSION": [[10, "module-datafed.VERSION"]], + "datafed.Version_pb2": [[11, "module-datafed.Version_pb2"]], + datafed: [[12, "module-datafed"]], + Submodules: [[12, "submodules"]], + "Package Contents": [[12, "package-contents"]], + "API Reference": [[13, "api-reference"]], + "Architecture & Design": [[14, "architecture-design"]], + "Project Management": [[15, "project-management"]], + Personnel: [[15, "personnel"]], + "Release Notes": [[16, "release-notes"]], + "1.2.0-4, May 28, 2021": [[16, "may-28-2021"]], + "New Features": [[16, "new-features"]], + "Impacts to Existing Features": [[16, "impacts-to-existing-features"]], + "Enhancements and Bug Fixes": [[16, "enhancements-and-bug-fixes"]], + "Known Issues": [[16, "known-issues"]], + "Feature Road Map": [[17, "feature-road-map"]], + "Planned Features": [[17, "planned-features"]], + "New User Features": [[17, "new-user-features"]], + "Production-Related Changes": [[17, "production-related-changes"]], + "Potential Features / Changes": [[17, "potential-features-changes"]], + "DataFed - A Scientific Data Federation": [[18, "datafed-a-scientific-data-federation"]], + "DataFed Documentation": [[18, "datafed-documentation"]], + "About DataFed": [[18, null]], + "Web Portal": [[18, null]], + "Client Package": [[18, null]], + "Command Line Interface": [[18, null]], + "Python Interface": [[18, null]], + Development: [[18, null]], + "Indices and tables": [[18, "indices-and-tables"]], + "Getting Started": [ + [19, "getting-started"], + [28, "getting-started"], + ], + "1. Get a Globus account": [[19, "get-a-globus-account"]], + "2. Get a Globus ID": [[19, "get-a-globus-id"]], + "3. Register at DataFed": [[19, "register-at-datafed"]], + "4. Get data allocations": [[19, "get-data-allocations"]], + "5. Install / identify Globus Endpoint": [[19, "install-identify-globus-endpoint"]], + "High Performance Compute clusters": [[19, "high-performance-compute-clusters"]], + "Personal Computers and Workstations": [[19, "personal-computers-and-workstations"]], + "6. Activate Globus Endpoint": [[19, "activate-globus-endpoint"]], + "Programming interfaces to DataFed": [[19, "programming-interfaces-to-datafed"]], + Introduction: [ + [20, "introduction"], + [24, "introduction"], + ], + Background: [[20, "background"]], + "Scientific Data Management": [[20, "scientific-data-management"]], + "Data Lifecycle": [[20, "data-lifecycle"]], + "Why DataFed?": [[20, "why-datafed"]], + "System Overview": [[21, "system-overview"]], + "Cross-Facility Data Management": [[21, "cross-facility-data-management"]], + "System Architecture": [[21, "system-architecture"]], + Interfaces: [[21, "interfaces"]], + "User Accounts": [[21, "user-accounts"]], + "System Concepts": [[21, "system-concepts"]], + "Quick Reference": [[21, "quick-reference"]], + "Identifiers and Aliases": [[21, "identifiers-and-aliases"]], + "Data Records": [ + [21, "data-records"], + [28, "data-records"], + ], + Metadata: [[21, "metadata"]], + Provenance: [[21, "provenance"]], + "Raw Data": [[21, "raw-data"]], + "Field Summary": [ + [21, "field-summary"], + [21, "id1"], + ], + Collections: [ + [21, "collections"], + [28, "collections"], + ], + "Root Collection": [[21, "root-collection"]], + "Public Collections": [[21, "public-collections"]], + Projects: [[21, "projects"]], + "Access Controls": [[21, "access-controls"]], + "Repository Allocations": [[21, "repository-allocations"]], + "Metadata Schemas": [[21, "metadata-schemas"]], + Tags: [[21, "tags"]], + Annotations: [[21, "annotations"]], + "Data and Collection Search": [[21, "data-and-collection-search"]], + Catalog: [[21, "catalog"]], + "Papers and Presentations": [[22, "papers-and-presentations"]], + "Use Cases": [[23, "use-cases"]], + "User Guide": [[24, "user-guide"]], + "Command Syntax": [[24, "command-syntax"]], + "Command Shortcuts": [[24, "command-shortcuts"]], + "Help and Documentation": [[24, "help-and-documentation"]], + "Scientific Metadata": [[24, "scientific-metadata"]], + "Creating Records": [[24, "creating-records"]], + "Uploading Raw Data": [[24, "uploading-raw-data"]], + "Viewing Data Records": [[24, "viewing-data-records"]], + "Downloading Raw Data": [[24, "downloading-raw-data"]], + Comments: [[24, "comments"]], + "Command Reference": [[26, "command-reference"]], + "Installation and Configuration": [[27, "installation-and-configuration"]], + Installation: [[27, "installation"]], + "0. Prerequisites": [[27, "prerequisites"]], + "1. Install python package": [[27, "install-python-package"]], + "2. Ensure bin directory is in Path": [[27, "ensure-bin-directory-is-in-path"]], + "3. Basic Configuration": [[27, "basic-configuration"]], + "Advanced Configuration": [[27, "advanced-configuration"]], + "Configuration Files": [[27, "configuration-files"]], + "Configuration Priority": [[27, "configuration-priority"]], + "Configuring Automatic Authentication": [[27, "configuring-automatic-authentication"]], + "Configuration Settings": [[27, "configuration-settings"]], + "Settings Quick Reference": [[27, "settings-quick-reference"]], + "Server Configuration File": [[27, "server-configuration-file"]], + "Server Configuration Directory": [[27, "server-configuration-directory"]], + "Server Public Key File": [[27, "server-public-key-file"]], + "Server Host": [[27, "server-host"]], + "Server Port": [[27, "server-port"]], + "Client Configuration File": [[27, "client-configuration-file"]], + "Client Config Directory": [[27, "client-config-directory"]], + "Client Public Key File": [[27, "client-public-key-file"]], + "Client Private Key File": [[27, "client-private-key-file"]], + "Default Endpoint": [[27, "default-endpoint"]], + "Guide to High Level Interface": [[28, "guide-to-high-level-interface"]], + "Import package": [[28, "import-package"]], + "Create instance": [[28, "create-instance"]], + "DataFed Responses & Projects": [[28, "datafed-responses-projects"]], + "DataFed functions and responses": [[28, "datafed-functions-and-responses"]], + "Subcripting message objects": [[28, "subcripting-message-objects"]], + "Iterating through message items": [[28, "iterating-through-message-items"]], + "Exploring projects": [[28, "exploring-projects"]], + "Contexts, aliases & IDs": [[28, "contexts-aliases-ids"]], + "Default context": [[28, "default-context"]], + "Context per function": [[28, "context-per-function"]], + "Contents of contexts": [[28, "contents-of-contexts"]], + "Alias vs ID": [[28, "alias-vs-id"]], + "Manual context management": [[28, "manual-context-management"]], + "Set default context": [[28, "set-default-context"]], + "Set working collection": [[28, "set-working-collection"]], + "Prepare (scientific) metadata": [[28, "prepare-scientific-metadata"]], + "Create Data Record": [[28, "create-data-record"]], + "Extract Record ID": [[28, "extract-record-id"]], + "Edit Record information": [[28, "edit-record-information"]], + "View Record information": [[28, "view-record-information"]], + "Extract metadata": [[28, "extract-metadata"]], + "Replace metadata": [[28, "replace-metadata"]], + "Relationships and provenance": [[28, "relationships-and-provenance"]], + "Batch operations": [[28, "batch-operations"]], + "Other functions": [ + [28, "other-functions"], + [28, "id3"], + ], + "Data Transfer": [[28, "data-transfer"]], + "Upload raw data": [[28, "upload-raw-data"]], + "Download raw data": [[28, "download-raw-data"]], + Tasks: [[28, "tasks"]], + "Asynchronous transfers": [[28, "asynchronous-transfers"]], + "Task list": [[28, "task-list"]], + "Create collection": [[28, "create-collection"]], + "Populate with Records": [[28, "populate-with-records"]], + "List items in Collection": [[28, "list-items-in-collection"]], + Queries: [[28, "queries"]], + "Create query": [[28, "create-query"]], + "List saved queries": [[28, "list-saved-queries"]], + "View query": [[28, "view-query"]], + "Execute query": [[28, "execute-query"]], + "Collections continued": [[28, "collections-continued"]], + "Organize with Collections": [[28, "organize-with-collections"]], + "Collection Parents": [[28, "collection-parents"]], + "Add and remove from Collections": [[28, "add-and-remove-from-collections"]], + "Download Collection": [[28, "download-collection"]], + "Closing remarks": [[28, "closing-remarks"]], + "Jupyter Notebooks": [[29, "jupyter-notebooks"]], + "Web Portal Guide": [[30, "web-portal-guide"]], + "Drag and Drop": [[30, "drag-and-drop"]], + "Personal Data": [[30, "personal-data"]], + "Project Data": [[30, "project-data"]], + "Shared Data": [[30, "shared-data"]], + "Search Results": [[30, "search-results"]], + "Information Panel": [[30, "information-panel"]], + "Action Buttons": [[30, "action-buttons"]], + Search: [[30, "search"]], + Transfers: [[30, "transfers"]], + Settings: [[30, "settings"]], + "Header and Footer": [[30, "header-and-footer"]], + }, + indexentries: { + "_aliasedgroup (class in datafed.cli)": [[2, "datafed.CLI._AliasedGroup"]], + "_aliasedgrouproot (class in datafed.cli)": [[2, "datafed.CLI._AliasedGroupRoot"]], + _nocommand: [[2, "datafed.CLI._NoCommand"]], + "_om_json (in module datafed.cli)": [[2, "datafed.CLI._OM_JSON"]], + "_om_retn (in module datafed.cli)": [[2, "datafed.CLI._OM_RETN"]], + "_om_text (in module datafed.cli)": [[2, "datafed.CLI._OM_TEXT"]], + "_stat_error (in module datafed.cli)": [[2, "datafed.CLI._STAT_ERROR"]], + "_stat_ok (in module datafed.cli)": [[2, "datafed.CLI._STAT_OK"]], + "__global_context_options (in module datafed.cli)": [ + [2, "datafed.CLI.__global_context_options"], + ], + "__global_output_options (in module datafed.cli)": [ + [2, "datafed.CLI.__global_output_options"], + ], + "_addconfigoptions() (in module datafed.cli)": [[2, "datafed.CLI._addConfigOptions"]], + "_arraytocsv() (in module datafed.cli)": [[2, "datafed.CLI._arrayToCSV"]], + "_arraytodotted() (in module datafed.cli)": [[2, "datafed.CLI._arrayToDotted"]], + "_bar_adaptive_human_readable() (in module datafed.cli)": [ + [2, "datafed.CLI._bar_adaptive_human_readable"], + ], + "_batch() (in module datafed.cli)": [[2, "datafed.CLI._batch"]], + "_capi (in module datafed.cli)": [[2, "datafed.CLI._capi"]], + "_cli() (in module datafed.cli)": [[2, "datafed.CLI._cli"]], + "_coll() (in module datafed.cli)": [[2, "datafed.CLI._coll"]], + "_collcreate() (in module datafed.cli)": [[2, "datafed.CLI._collCreate"]], + "_colldelete() (in module datafed.cli)": [[2, "datafed.CLI._collDelete"]], + "_collitemsadd() (in module datafed.cli)": [[2, "datafed.CLI._collItemsAdd"]], + "_collupdate() (in module datafed.cli)": [[2, "datafed.CLI._collUpdate"]], + "_collview() (in module datafed.cli)": [[2, "datafed.CLI._collView"]], + "_coll_rem() (in module datafed.cli)": [[2, "datafed.CLI._coll_rem"]], + "_ctxt_settings (in module datafed.cli)": [[2, "datafed.CLI._ctxt_settings"]], + "_cur_alias_prefix (in module datafed.cli)": [[2, "datafed.CLI._cur_alias_prefix"]], + "_cur_coll (in module datafed.cli)": [[2, "datafed.CLI._cur_coll"]], + "_cur_coll_prefix (in module datafed.cli)": [[2, "datafed.CLI._cur_coll_prefix"]], + "_cur_coll_title (in module datafed.cli)": [[2, "datafed.CLI._cur_coll_title"]], + "_cur_ctx (in module datafed.cli)": [[2, "datafed.CLI._cur_ctx"]], + "_data() (in module datafed.cli)": [[2, "datafed.CLI._data"]], + "_datacreate() (in module datafed.cli)": [[2, "datafed.CLI._dataCreate"]], + "_datadelete() (in module datafed.cli)": [[2, "datafed.CLI._dataDelete"]], + "_dataget() (in module datafed.cli)": [[2, "datafed.CLI._dataGet"]], + "_dataput() (in module datafed.cli)": [[2, "datafed.CLI._dataPut"]], + "_dataupdate() (in module datafed.cli)": [[2, "datafed.CLI._dataUpdate"]], + "_dataview() (in module datafed.cli)": [[2, "datafed.CLI._dataView"]], + "_data_batch_create() (in module datafed.cli)": [[2, "datafed.CLI._data_batch_create"]], + "_data_batch_update() (in module datafed.cli)": [[2, "datafed.CLI._data_batch_update"]], + "_devnull (in module datafed.cli)": [[2, "datafed.CLI._devnull"]], + "_ep() (in module datafed.cli)": [[2, "datafed.CLI._ep"]], + "_epdefault() (in module datafed.cli)": [[2, "datafed.CLI._epDefault"]], + "_epdefaultget() (in module datafed.cli)": [[2, "datafed.CLI._epDefaultGet"]], + "_epdefaultset() (in module datafed.cli)": [[2, "datafed.CLI._epDefaultSet"]], + "_epget() (in module datafed.cli)": [[2, "datafed.CLI._epGet"]], + "_eplist() (in module datafed.cli)": [[2, "datafed.CLI._epList"]], + "_epset() (in module datafed.cli)": [[2, "datafed.CLI._epSet"]], + "_exit_cli() (in module datafed.cli)": [[2, "datafed.CLI._exit_cli"]], + "_gendoc() (in module datafed.cli)": [[2, "datafed.CLI._genDoc"]], + "_gendoccmd() (in module datafed.cli)": [[2, "datafed.CLI._genDocCmd"]], + "_gendocheader() (in module datafed.cli)": [[2, "datafed.CLI._genDocHeader"]], + "_generic_reply_handler() (in module datafed.cli)": [ + [2, "datafed.CLI._generic_reply_handler"], + ], + "_global_context_options() (in module datafed.cli)": [ + [2, "datafed.CLI._global_context_options"], + ], + "_global_output_options() (in module datafed.cli)": [ + [2, "datafed.CLI._global_output_options"], + ], + "_hdr_lev_char (in module datafed.cli)": [[2, "datafed.CLI._hdr_lev_char"]], + "_help_cli() (in module datafed.cli)": [[2, "datafed.CLI._help_cli"]], + "_initialize() (in module datafed.cli)": [[2, "datafed.CLI._initialize"]], + "_initialized (in module datafed.cli)": [[2, "datafed.CLI._initialized"]], + "_interactive (in module datafed.cli)": [[2, "datafed.CLI._interactive"]], + "_list() (in module datafed.cli)": [[2, "datafed.CLI._list"]], + "_list_items (in module datafed.cli)": [[2, "datafed.CLI._list_items"]], + "_output_mode (in module datafed.cli)": [[2, "datafed.CLI._output_mode"]], + "_output_mode_sticky (in module datafed.cli)": [[2, "datafed.CLI._output_mode_sticky"]], + "_prev_coll (in module datafed.cli)": [[2, "datafed.CLI._prev_coll"]], + "_prev_ctx (in module datafed.cli)": [[2, "datafed.CLI._prev_ctx"]], + "_printjson() (in module datafed.cli)": [[2, "datafed.CLI._printJSON"]], + "_printjson_list() (in module datafed.cli)": [[2, "datafed.CLI._printJSON_List"]], + "_print_ack_reply() (in module datafed.cli)": [[2, "datafed.CLI._print_ack_reply"]], + "_print_batch() (in module datafed.cli)": [[2, "datafed.CLI._print_batch"]], + "_print_coll() (in module datafed.cli)": [[2, "datafed.CLI._print_coll"]], + "_print_data() (in module datafed.cli)": [[2, "datafed.CLI._print_data"]], + "_print_deps() (in module datafed.cli)": [[2, "datafed.CLI._print_deps"]], + "_print_endpoints() (in module datafed.cli)": [[2, "datafed.CLI._print_endpoints"]], + "_print_listing() (in module datafed.cli)": [[2, "datafed.CLI._print_listing"]], + "_print_msg() (in module datafed.cli)": [[2, "datafed.CLI._print_msg"]], + "_print_path() (in module datafed.cli)": [[2, "datafed.CLI._print_path"]], + "_print_proj() (in module datafed.cli)": [[2, "datafed.CLI._print_proj"]], + "_print_proj_listing() (in module datafed.cli)": [[2, "datafed.CLI._print_proj_listing"]], + "_print_query() (in module datafed.cli)": [[2, "datafed.CLI._print_query"]], + "_print_task() (in module datafed.cli)": [[2, "datafed.CLI._print_task"]], + "_print_task_array() (in module datafed.cli)": [[2, "datafed.CLI._print_task_array"]], + "_print_task_listing() (in module datafed.cli)": [[2, "datafed.CLI._print_task_listing"]], + "_print_user() (in module datafed.cli)": [[2, "datafed.CLI._print_user"]], + "_print_user_listing() (in module datafed.cli)": [[2, "datafed.CLI._print_user_listing"]], + "_project() (in module datafed.cli)": [[2, "datafed.CLI._project"]], + "_projectlist() (in module datafed.cli)": [[2, "datafed.CLI._projectList"]], + "_projectview() (in module datafed.cli)": [[2, "datafed.CLI._projectView"]], + "_query() (in module datafed.cli)": [[2, "datafed.CLI._query"]], + "_querycreate() (in module datafed.cli)": [[2, "datafed.CLI._queryCreate"]], + "_querydelete() (in module datafed.cli)": [[2, "datafed.CLI._queryDelete"]], + "_queryexec() (in module datafed.cli)": [[2, "datafed.CLI._queryExec"]], + "_querylist() (in module datafed.cli)": [[2, "datafed.CLI._queryList"]], + "_queryrun() (in module datafed.cli)": [[2, "datafed.CLI._queryRun"]], + "_queryupdate() (in module datafed.cli)": [[2, "datafed.CLI._queryUpdate"]], + "_queryview() (in module datafed.cli)": [[2, "datafed.CLI._queryView"]], + "_resolve_coll_id() (in module datafed.cli)": [[2, "datafed.CLI._resolve_coll_id"]], + "_resolve_id() (in module datafed.cli)": [[2, "datafed.CLI._resolve_id"]], + "_return_val (in module datafed.cli)": [[2, "datafed.CLI._return_val"]], + "_setworkingcollectiontitle() (in module datafed.cli)": [ + [2, "datafed.CLI._setWorkingCollectionTitle"], + ], + "_set_script_cb() (in module datafed.cli)": [[2, "datafed.CLI._set_script_cb"]], + "_set_verbosity_cb() (in module datafed.cli)": [[2, "datafed.CLI._set_verbosity_cb"]], + "_setup() (in module datafed.cli)": [[2, "datafed.CLI._setup"]], + "_shares() (in module datafed.cli)": [[2, "datafed.CLI._shares"]], + "_task() (in module datafed.cli)": [[2, "datafed.CLI._task"]], + "_tasklist() (in module datafed.cli)": [[2, "datafed.CLI._taskList"]], + "_taskview() (in module datafed.cli)": [[2, "datafed.CLI._taskView"]], + "_task_statuses (in module datafed.cli)": [[2, "datafed.CLI._task_statuses"]], + "_task_types (in module datafed.cli)": [[2, "datafed.CLI._task_types"]], + "_uid (in module datafed.cli)": [[2, "datafed.CLI._uid"]], + "_user() (in module datafed.cli)": [[2, "datafed.CLI._user"]], + "_userlistall() (in module datafed.cli)": [[2, "datafed.CLI._userListAll"]], + "_userlistcollab() (in module datafed.cli)": [[2, "datafed.CLI._userListCollab"]], + "_userview() (in module datafed.cli)": [[2, "datafed.CLI._userView"]], + "_userwho() (in module datafed.cli)": [[2, "datafed.CLI._userWho"]], + "_verbosity (in module datafed.cli)": [[2, "datafed.CLI._verbosity"]], + "_verbosityset() (in module datafed.cli)": [[2, "datafed.CLI._verbositySet"]], + "_verbosity_sticky (in module datafed.cli)": [[2, "datafed.CLI._verbosity_sticky"]], + "_wc() (in module datafed.cli)": [[2, "datafed.CLI._wc"]], + "_wp() (in module datafed.cli)": [[2, "datafed.CLI._wp"]], + "_wrap_text() (in module datafed.cli)": [[2, "datafed.CLI._wrap_text"]], + "command() (in module datafed.cli)": [[2, "datafed.CLI.command"]], + "datafed.cli": [[2, "module-datafed.CLI"]], + "get_command() (datafed.cli._aliasedgroup method)": [ + [2, "datafed.CLI._AliasedGroup.get_command"], + ], + "get_command() (datafed.cli._aliasedgrouproot method)": [ + [2, "datafed.CLI._AliasedGroupRoot.get_command"], + ], + "init() (in module datafed.cli)": [[2, "datafed.CLI.init"]], + "loginbypassword() (in module datafed.cli)": [[2, "datafed.CLI.loginByPassword"]], + "loginbytoken() (in module datafed.cli)": [[2, "datafed.CLI.loginByToken"]], + module: [ + [2, "module-datafed.CLI"], + [3, "module-datafed.CommandLib"], + [4, "module-datafed.Config"], + [5, "module-datafed.Connection"], + [6, "module-datafed.MessageLib"], + [7, "module-datafed.SDMS_Anon_pb2"], + [8, "module-datafed.SDMS_Auth_pb2"], + [9, "module-datafed.SDMS_pb2"], + [10, "module-datafed.VERSION"], + [11, "module-datafed.Version_pb2"], + [12, "module-datafed"], + ], + "resolve_command() (datafed.cli._aliasedgroup method)": [ + [2, "datafed.CLI._AliasedGroup.resolve_command"], + ], + "run() (in module datafed.cli)": [[2, "datafed.CLI.run"]], + "api (class in datafed.commandlib)": [[3, "datafed.CommandLib.API"]], + "_buildsearchrequest() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API._buildSearchRequest"], + ], + "_endpoint_legacy (datafed.commandlib.api attribute)": [ + [3, "datafed.CommandLib.API._endpoint_legacy"], + ], + "_endpoint_uuid (datafed.commandlib.api attribute)": [ + [3, "datafed.CommandLib.API._endpoint_uuid"], + ], + "_max_md_size (datafed.commandlib.api attribute)": [ + [3, "datafed.CommandLib.API._max_md_size"], + ], + "_max_payload_size (datafed.commandlib.api attribute)": [ + [3, "datafed.CommandLib.API._max_payload_size"], + ], + "_resolvepathforglobus() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API._resolvePathForGlobus"], + ], + "_resolvepathforhttp() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API._resolvePathForHTTP"], + ], + "_resolve_id() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API._resolve_id"], + ], + "_setsanedefaultoptions() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API._setSaneDefaultOptions"], + ], + "_uniquifyfilename() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API._uniquifyFilename"], + ], + "collectioncreate() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.collectionCreate"], + ], + "collectiondelete() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.collectionDelete"], + ], + "collectiongetparents() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.collectionGetParents"], + ], + "collectionitemslist() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.collectionItemsList"], + ], + "collectionitemsupdate() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.collectionItemsUpdate"], + ], + "collectionupdate() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.collectionUpdate"], + ], + "collectionview() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.collectionView"], + ], + "databatchcreate() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.dataBatchCreate"], + ], + "databatchupdate() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.dataBatchUpdate"], + ], + "datacreate() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.dataCreate"]], + "datadelete() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.dataDelete"]], + "dataget() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.dataGet"]], + "dataput() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.dataPut"]], + "dataupdate() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.dataUpdate"]], + "dataview() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.dataView"]], + "datafed.commandlib": [[3, "module-datafed.CommandLib"]], + "endpointdefaultget() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.endpointDefaultGet"], + ], + "endpointdefaultset() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.endpointDefaultSet"], + ], + "endpointget() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.endpointGet"], + ], + "endpointlistrecent() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.endpointListRecent"], + ], + "endpointset() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.endpointSet"], + ], + "generatecredentials() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.generateCredentials"], + ], + "getauthuser() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.getAuthUser"], + ], + "getcontext() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.getContext"]], + "loginbypassword() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.loginByPassword"], + ], + "logout() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.logout"]], + "projectgetrole() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.projectGetRole"], + ], + "projectlist() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.projectList"], + ], + "projectview() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.projectView"], + ], + "querycreate() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.queryCreate"], + ], + "querydelete() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.queryDelete"], + ], + "querydirect() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.queryDirect"], + ], + "queryexec() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.queryExec"]], + "querylist() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.queryList"]], + "queryupdate() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.queryUpdate"], + ], + "queryview() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.queryView"]], + "repoallocationcreate() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.repoAllocationCreate"], + ], + "repoallocationdelete() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.repoAllocationDelete"], + ], + "repocreate() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.repoCreate"]], + "repodelete() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.repoDelete"]], + "repolist() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.repoList"]], + "repolistallocations() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.repoListAllocations"], + ], + "setcontext() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.setContext"]], + "setupcredentials() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.setupCredentials"], + ], + "sharedlist() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.sharedList"]], + "sharedlistitems() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.sharedListItems"], + ], + "sizetostr() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.sizeToStr"]], + "strtotimestamp() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.strToTimestamp"], + ], + "tasklist() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.taskList"]], + "taskview() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.taskView"]], + "timestamptostr() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.timestampToStr"], + ], + "userlistall() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.userListAll"], + ], + "userlistcollaborators() (datafed.commandlib.api method)": [ + [3, "datafed.CommandLib.API.userListCollaborators"], + ], + "userview() (datafed.commandlib.api method)": [[3, "datafed.CommandLib.API.userView"]], + "api (class in datafed.config)": [[4, "datafed.Config.API"]], + "_opt_bool (in module datafed.config)": [[4, "datafed.Config._OPT_BOOL"]], + "_opt_eager (in module datafed.config)": [[4, "datafed.Config._OPT_EAGER"]], + "_opt_hide (in module datafed.config)": [[4, "datafed.Config._OPT_HIDE"]], + "_opt_int (in module datafed.config)": [[4, "datafed.Config._OPT_INT"]], + "_opt_no_cf (in module datafed.config)": [[4, "datafed.Config._OPT_NO_CF"]], + "_opt_no_cl (in module datafed.config)": [[4, "datafed.Config._OPT_NO_CL"]], + "_opt_no_env (in module datafed.config)": [[4, "datafed.Config._OPT_NO_ENV"]], + "_opt_path (in module datafed.config)": [[4, "datafed.Config._OPT_PATH"]], + "_loadconfigfile() (datafed.config.api method)": [ + [4, "datafed.Config.API._loadConfigFile"], + ], + "_loadenvironvars() (datafed.config.api method)": [ + [4, "datafed.Config.API._loadEnvironVars"], + ], + "_opt_info (in module datafed.config)": [[4, "datafed.Config._opt_info"]], + "_processoptions() (datafed.config.api method)": [ + [4, "datafed.Config.API._processOptions"], + ], + "datafed.config": [[4, "module-datafed.Config"]], + "get() (datafed.config.api method)": [[4, "datafed.Config.API.get"]], + "getopts() (datafed.config.api method)": [[4, "datafed.Config.API.getOpts"]], + "printsettinginfo() (datafed.config.api method)": [ + [4, "datafed.Config.API.printSettingInfo"], + ], + "save() (datafed.config.api method)": [[4, "datafed.Config.API.save"]], + "set() (datafed.config.api method)": [[4, "datafed.Config.API.set"]], + "connection (class in datafed.connection)": [[5, "datafed.Connection.Connection"]], + "__del__() (datafed.connection.connection method)": [ + [5, "datafed.Connection.Connection.__del__"], + ], + "datafed.connection": [[5, "module-datafed.Connection"]], + "makemessage() (datafed.connection.connection method)": [ + [5, "datafed.Connection.Connection.makeMessage"], + ], + "recv() (datafed.connection.connection method)": [ + [5, "datafed.Connection.Connection.recv"], + ], + "registerprotocol() (datafed.connection.connection method)": [ + [5, "datafed.Connection.Connection.registerProtocol"], + ], + "reset() (datafed.connection.connection method)": [ + [5, "datafed.Connection.Connection.reset"], + ], + "send() (datafed.connection.connection method)": [ + [5, "datafed.Connection.Connection.send"], + ], + "api (class in datafed.messagelib)": [[6, "datafed.MessageLib.API"]], + "datafed.messagelib": [[6, "module-datafed.MessageLib"]], + "getauthstatus() (datafed.messagelib.api method)": [ + [6, "datafed.MessageLib.API.getAuthStatus"], + ], + "getdailymessage() (datafed.messagelib.api method)": [ + [6, "datafed.MessageLib.API.getDailyMessage"], + ], + "getdefaulttimeout() (datafed.messagelib.api method)": [ + [6, "datafed.MessageLib.API.getDefaultTimeout"], + ], + "getnackexceptionenabled() (datafed.messagelib.api method)": [ + [6, "datafed.MessageLib.API.getNackExceptionEnabled"], + ], + "get_latest_version() (in module datafed.messagelib)": [ + [6, "datafed.MessageLib.get_latest_version"], + ], + "keysloaded() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.keysLoaded"]], + "keysvalid() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.keysValid"]], + "logout() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.logout"]], + "manualauthbypassword() (datafed.messagelib.api method)": [ + [6, "datafed.MessageLib.API.manualAuthByPassword"], + ], + "manualauthbytoken() (datafed.messagelib.api method)": [ + [6, "datafed.MessageLib.API.manualAuthByToken"], + ], + "recv() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.recv"]], + "send() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.send"]], + "sendrecv() (datafed.messagelib.api method)": [[6, "datafed.MessageLib.API.sendRecv"]], + "setdefaulttimeout() (datafed.messagelib.api method)": [ + [6, "datafed.MessageLib.API.setDefaultTimeout"], + ], + "setnackexceptionenabled() (datafed.messagelib.api method)": [ + [6, "datafed.MessageLib.API.setNackExceptionEnabled"], + ], + "ackreply (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.AckReply"]], + "authstatusreply (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2.AuthStatusReply"], + ], + "authenticatebypasswordrequest (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2.AuthenticateByPasswordRequest"], + ], + "authenticatebytokenrequest (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2.AuthenticateByTokenRequest"], + ], + "descriptor (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.DESCRIPTOR"]], + "dailymessagereply (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2.DailyMessageReply"], + ], + "dailymessagerequest (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2.DailyMessageRequest"], + ], + "getauthstatusrequest (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2.GetAuthStatusRequest"], + ], + "id (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.ID"]], + "nackreply (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.NackReply"]], + "protocol (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2.Protocol"]], + "versionreply (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2.VersionReply"], + ], + "versionrequest (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2.VersionRequest"], + ], + "_ackreply (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._ACKREPLY"]], + "_authenticatebypasswordrequest (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2._AUTHENTICATEBYPASSWORDREQUEST"], + ], + "_authenticatebytokenrequest (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2._AUTHENTICATEBYTOKENREQUEST"], + ], + "_authstatusreply (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2._AUTHSTATUSREPLY"], + ], + "_dailymessagereply (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2._DAILYMESSAGEREPLY"], + ], + "_dailymessagerequest (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2._DAILYMESSAGEREQUEST"], + ], + "_getauthstatusrequest (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2._GETAUTHSTATUSREQUEST"], + ], + "_nackreply (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._NACKREPLY"]], + "_protocol (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._PROTOCOL"]], + "_versionreply (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2._VERSIONREPLY"], + ], + "_versionrequest (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2._VERSIONREQUEST"], + ], + "_msg_name_to_type (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2._msg_name_to_type"], + [7, "id0"], + [7, "id10"], + [7, "id12"], + [7, "id14"], + [7, "id16"], + [7, "id18"], + [7, "id2"], + [7, "id20"], + [7, "id22"], + [7, "id24"], + [7, "id26"], + [7, "id28"], + [7, "id30"], + [7, "id4"], + [7, "id6"], + [7, "id8"], + ], + "_msg_type_to_name (in module datafed.sdms_anon_pb2)": [ + [7, "datafed.SDMS_Anon_pb2._msg_type_to_name"], + [7, "id1"], + [7, "id11"], + [7, "id13"], + [7, "id15"], + [7, "id17"], + [7, "id19"], + [7, "id21"], + [7, "id23"], + [7, "id25"], + [7, "id27"], + [7, "id29"], + [7, "id3"], + [7, "id31"], + [7, "id5"], + [7, "id7"], + [7, "id9"], + ], + "_sym_db (in module datafed.sdms_anon_pb2)": [[7, "datafed.SDMS_Anon_pb2._sym_db"]], + "datafed.sdms_anon_pb2": [[7, "module-datafed.SDMS_Anon_pb2"]], + "acldatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.ACLDataReply"], + ], + "aclsharedlistitemsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.ACLSharedListItemsRequest"], + ], + "aclsharedlistrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.ACLSharedListRequest"], + ], + "aclupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.ACLUpdateRequest"], + ], + "aclviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.ACLViewRequest"], + ], + "checkpermsreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.CheckPermsReply"], + ], + "checkpermsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.CheckPermsRequest"], + ], + "collcreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.CollCreateRequest"], + ], + "colldatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.CollDataReply"], + ], + "colldeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.CollDeleteRequest"], + ], + "collgetoffsetreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.CollGetOffsetReply"], + ], + "collgetoffsetrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.CollGetOffsetRequest"], + ], + "collgetparentsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.CollGetParentsRequest"], + ], + "colllistpublishedrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.CollListPublishedRequest"], + ], + "collmoverequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.CollMoveRequest"], + ], + "collpathreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.CollPathReply"], + ], + "collreadrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.CollReadRequest"], + ], + "collupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.CollUpdateRequest"], + ], + "collviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.CollViewRequest"], + ], + "collwriterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.CollWriteRequest"], + ], + "descriptor (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.DESCRIPTOR"]], + "datadeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.DataDeleteRequest"], + ], + "datagetreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.DataGetReply"], + ], + "datagetrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.DataGetRequest"], + ], + "datapathreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.DataPathReply"], + ], + "datapathrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.DataPathRequest"], + ], + "dataputreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.DataPutReply"], + ], + "dataputrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.DataPutRequest"], + ], + "generatecredentialsreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.GenerateCredentialsReply"], + ], + "generatecredentialsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.GenerateCredentialsRequest"], + ], + "getpermsreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.GetPermsReply"], + ], + "getpermsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.GetPermsRequest"], + ], + "groupcreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.GroupCreateRequest"], + ], + "groupdatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.GroupDataReply"], + ], + "groupdeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.GroupDeleteRequest"], + ], + "grouplistrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.GroupListRequest"], + ], + "groupupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.GroupUpdateRequest"], + ], + "groupviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.GroupViewRequest"], + ], + "id (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.ID"]], + "listingreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.ListingReply"], + ], + "metadatavalidatereply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.MetadataValidateReply"], + ], + "metadatavalidaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.MetadataValidateRequest"], + ], + "notecommenteditrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.NoteCommentEditRequest"], + ], + "notecreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.NoteCreateRequest"], + ], + "notedatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.NoteDataReply"], + ], + "notelistbysubjectrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.NoteListBySubjectRequest"], + ], + "noteupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.NoteUpdateRequest"], + ], + "noteviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.NoteViewRequest"], + ], + "projectcreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.ProjectCreateRequest"], + ], + "projectdatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.ProjectDataReply"], + ], + "projectdeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.ProjectDeleteRequest"], + ], + "projectgetrolereply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.ProjectGetRoleReply"], + ], + "projectgetrolerequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.ProjectGetRoleRequest"], + ], + "projectlistrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.ProjectListRequest"], + ], + "projectsearchrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.ProjectSearchRequest"], + ], + "projectupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.ProjectUpdateRequest"], + ], + "projectviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.ProjectViewRequest"], + ], + "protocol (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2.Protocol"]], + "querycreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.QueryCreateRequest"], + ], + "querydatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.QueryDataReply"], + ], + "querydeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.QueryDeleteRequest"], + ], + "queryexecrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.QueryExecRequest"], + ], + "querylistrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.QueryListRequest"], + ], + "queryupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.QueryUpdateRequest"], + ], + "queryviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.QueryViewRequest"], + ], + "recordallocchangereply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RecordAllocChangeReply"], + ], + "recordallocchangerequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RecordAllocChangeRequest"], + ], + "recordcreatebatchrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RecordCreateBatchRequest"], + ], + "recordcreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RecordCreateRequest"], + ], + "recorddatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RecordDataReply"], + ], + "recorddeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RecordDeleteRequest"], + ], + "recordexportreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RecordExportReply"], + ], + "recordexportrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RecordExportRequest"], + ], + "recordgetdependencygraphrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RecordGetDependencyGraphRequest"], + ], + "recordlistbyallocrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RecordListByAllocRequest"], + ], + "recordlockrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RecordLockRequest"], + ], + "recordownerchangereply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RecordOwnerChangeReply"], + ], + "recordownerchangerequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RecordOwnerChangeRequest"], + ], + "recordupdatebatchrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RecordUpdateBatchRequest"], + ], + "recordupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RecordUpdateRequest"], + ], + "recordviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RecordViewRequest"], + ], + "repoallocationcreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoAllocationCreateRequest"], + ], + "repoallocationdeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoAllocationDeleteRequest"], + ], + "repoallocationsetdefaultrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoAllocationSetDefaultRequest"], + ], + "repoallocationsetrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoAllocationSetRequest"], + ], + "repoallocationstatsreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoAllocationStatsReply"], + ], + "repoallocationstatsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoAllocationStatsRequest"], + ], + "repoallocationsreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoAllocationsReply"], + ], + "repoauthzrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoAuthzRequest"], + ], + "repocalcsizereply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoCalcSizeReply"], + ], + "repocalcsizerequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoCalcSizeRequest"], + ], + "repocreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoCreateRequest"], + ], + "repodatadeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoDataDeleteRequest"], + ], + "repodatagetsizerequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoDataGetSizeRequest"], + ], + "repodatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoDataReply"], + ], + "repodatasizereply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoDataSizeReply"], + ], + "repodeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoDeleteRequest"], + ], + "repolistallocationsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoListAllocationsRequest"], + ], + "repolistobjectallocationsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoListObjectAllocationsRequest"], + ], + "repolistrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoListRequest"], + ], + "repolistsubjectallocationsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoListSubjectAllocationsRequest"], + ], + "repopathcreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoPathCreateRequest"], + ], + "repopathdeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoPathDeleteRequest"], + ], + "repoupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoUpdateRequest"], + ], + "repoviewallocationrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoViewAllocationRequest"], + ], + "repoviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RepoViewRequest"], + ], + "revokecredentialsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.RevokeCredentialsRequest"], + ], + "schemacreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.SchemaCreateRequest"], + ], + "schemadatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.SchemaDataReply"], + ], + "schemadeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.SchemaDeleteRequest"], + ], + "schemareviserequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.SchemaReviseRequest"], + ], + "schemasearchrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.SchemaSearchRequest"], + ], + "schemaupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.SchemaUpdateRequest"], + ], + "schemaviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.SchemaViewRequest"], + ], + "searchrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.SearchRequest"], + ], + "tagdatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.TagDataReply"], + ], + "taglistbycountrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.TagListByCountRequest"], + ], + "tagsearchrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.TagSearchRequest"], + ], + "taskdatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.TaskDataReply"], + ], + "tasklistrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.TaskListRequest"], + ], + "taskviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.TaskViewRequest"], + ], + "topicdatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.TopicDataReply"], + ], + "topiclisttopicsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.TopicListTopicsRequest"], + ], + "topicsearchrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.TopicSearchRequest"], + ], + "topicviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.TopicViewRequest"], + ], + "useraccesstokenreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.UserAccessTokenReply"], + ], + "usercreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.UserCreateRequest"], + ], + "userdatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.UserDataReply"], + ], + "userfindbynameuidrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.UserFindByNameUIDRequest"], + ], + "userfindbyuuidsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.UserFindByUUIDsRequest"], + ], + "usergetaccesstokenrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.UserGetAccessTokenRequest"], + ], + "usergetrecentepreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.UserGetRecentEPReply"], + ], + "usergetrecenteprequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.UserGetRecentEPRequest"], + ], + "userlistallrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.UserListAllRequest"], + ], + "userlistcollabrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.UserListCollabRequest"], + ], + "usersetaccesstokenrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.UserSetAccessTokenRequest"], + ], + "usersetrecenteprequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.UserSetRecentEPRequest"], + ], + "userupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.UserUpdateRequest"], + ], + "userviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2.UserViewRequest"], + ], + "_acldatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._ACLDATAREPLY"], + ], + "_aclsharedlistitemsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._ACLSHAREDLISTITEMSREQUEST"], + ], + "_aclsharedlistrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._ACLSHAREDLISTREQUEST"], + ], + "_aclupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._ACLUPDATEREQUEST"], + ], + "_aclviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._ACLVIEWREQUEST"], + ], + "_checkpermsreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._CHECKPERMSREPLY"], + ], + "_checkpermsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._CHECKPERMSREQUEST"], + ], + "_collcreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._COLLCREATEREQUEST"], + ], + "_colldatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._COLLDATAREPLY"], + ], + "_colldeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._COLLDELETEREQUEST"], + ], + "_collgetoffsetreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._COLLGETOFFSETREPLY"], + ], + "_collgetoffsetrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._COLLGETOFFSETREQUEST"], + ], + "_collgetparentsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._COLLGETPARENTSREQUEST"], + ], + "_colllistpublishedrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._COLLLISTPUBLISHEDREQUEST"], + ], + "_collmoverequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._COLLMOVEREQUEST"], + ], + "_collpathreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._COLLPATHREPLY"], + ], + "_collreadrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._COLLREADREQUEST"], + ], + "_collupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._COLLUPDATEREQUEST"], + ], + "_collviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._COLLVIEWREQUEST"], + ], + "_collwriterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._COLLWRITEREQUEST"], + ], + "_datadeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._DATADELETEREQUEST"], + ], + "_datagetreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._DATAGETREPLY"], + ], + "_datagetrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._DATAGETREQUEST"], + ], + "_datapathreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._DATAPATHREPLY"], + ], + "_datapathrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._DATAPATHREQUEST"], + ], + "_dataputreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._DATAPUTREPLY"], + ], + "_dataputrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._DATAPUTREQUEST"], + ], + "_generatecredentialsreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._GENERATECREDENTIALSREPLY"], + ], + "_generatecredentialsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._GENERATECREDENTIALSREQUEST"], + ], + "_getpermsreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._GETPERMSREPLY"], + ], + "_getpermsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._GETPERMSREQUEST"], + ], + "_groupcreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._GROUPCREATEREQUEST"], + ], + "_groupdatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._GROUPDATAREPLY"], + ], + "_groupdeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._GROUPDELETEREQUEST"], + ], + "_grouplistrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._GROUPLISTREQUEST"], + ], + "_groupupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._GROUPUPDATEREQUEST"], + ], + "_groupviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._GROUPVIEWREQUEST"], + ], + "_listingreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._LISTINGREPLY"], + ], + "_metadatavalidatereply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._METADATAVALIDATEREPLY"], + ], + "_metadatavalidaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._METADATAVALIDATEREQUEST"], + ], + "_notecommenteditrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._NOTECOMMENTEDITREQUEST"], + ], + "_notecreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._NOTECREATEREQUEST"], + ], + "_notedatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._NOTEDATAREPLY"], + ], + "_notelistbysubjectrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._NOTELISTBYSUBJECTREQUEST"], + ], + "_noteupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._NOTEUPDATEREQUEST"], + ], + "_noteviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._NOTEVIEWREQUEST"], + ], + "_projectcreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._PROJECTCREATEREQUEST"], + ], + "_projectdatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._PROJECTDATAREPLY"], + ], + "_projectdeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._PROJECTDELETEREQUEST"], + ], + "_projectgetrolereply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._PROJECTGETROLEREPLY"], + ], + "_projectgetrolerequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._PROJECTGETROLEREQUEST"], + ], + "_projectlistrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._PROJECTLISTREQUEST"], + ], + "_projectsearchrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._PROJECTSEARCHREQUEST"], + ], + "_projectupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._PROJECTUPDATEREQUEST"], + ], + "_projectviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._PROJECTVIEWREQUEST"], + ], + "_protocol (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._PROTOCOL"]], + "_querycreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._QUERYCREATEREQUEST"], + ], + "_querydatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._QUERYDATAREPLY"], + ], + "_querydeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._QUERYDELETEREQUEST"], + ], + "_queryexecrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._QUERYEXECREQUEST"], + ], + "_querylistrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._QUERYLISTREQUEST"], + ], + "_queryupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._QUERYUPDATEREQUEST"], + ], + "_queryviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._QUERYVIEWREQUEST"], + ], + "_recordallocchangereply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._RECORDALLOCCHANGEREPLY"], + ], + "_recordallocchangerequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._RECORDALLOCCHANGEREQUEST"], + ], + "_recordcreatebatchrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._RECORDCREATEBATCHREQUEST"], + ], + "_recordcreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._RECORDCREATEREQUEST"], + ], + "_recorddatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._RECORDDATAREPLY"], + ], + "_recorddeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._RECORDDELETEREQUEST"], + ], + "_recordexportreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._RECORDEXPORTREPLY"], + ], + "_recordexportrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._RECORDEXPORTREQUEST"], + ], + "_recordgetdependencygraphrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._RECORDGETDEPENDENCYGRAPHREQUEST"], + ], + "_recordlistbyallocrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._RECORDLISTBYALLOCREQUEST"], + ], + "_recordlockrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._RECORDLOCKREQUEST"], + ], + "_recordownerchangereply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._RECORDOWNERCHANGEREPLY"], + ], + "_recordownerchangerequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._RECORDOWNERCHANGEREQUEST"], + ], + "_recordupdatebatchrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._RECORDUPDATEBATCHREQUEST"], + ], + "_recordupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._RECORDUPDATEREQUEST"], + ], + "_recordviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._RECORDVIEWREQUEST"], + ], + "_repoallocationcreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOALLOCATIONCREATEREQUEST"], + ], + "_repoallocationdeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOALLOCATIONDELETEREQUEST"], + ], + "_repoallocationsetdefaultrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOALLOCATIONSETDEFAULTREQUEST"], + ], + "_repoallocationsetrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOALLOCATIONSETREQUEST"], + ], + "_repoallocationsreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOALLOCATIONSREPLY"], + ], + "_repoallocationstatsreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOALLOCATIONSTATSREPLY"], + ], + "_repoallocationstatsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOALLOCATIONSTATSREQUEST"], + ], + "_repoauthzrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOAUTHZREQUEST"], + ], + "_repocalcsizereply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOCALCSIZEREPLY"], + ], + "_repocalcsizerequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOCALCSIZEREQUEST"], + ], + "_repocreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOCREATEREQUEST"], + ], + "_repodatadeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPODATADELETEREQUEST"], + ], + "_repodatagetsizerequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPODATAGETSIZEREQUEST"], + ], + "_repodatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPODATAREPLY"], + ], + "_repodatasizereply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPODATASIZEREPLY"], + ], + "_repodeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPODELETEREQUEST"], + ], + "_repolistallocationsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOLISTALLOCATIONSREQUEST"], + ], + "_repolistobjectallocationsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOLISTOBJECTALLOCATIONSREQUEST"], + ], + "_repolistrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOLISTREQUEST"], + ], + "_repolistsubjectallocationsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOLISTSUBJECTALLOCATIONSREQUEST"], + ], + "_repopathcreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOPATHCREATEREQUEST"], + ], + "_repopathdeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOPATHDELETEREQUEST"], + ], + "_repoupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOUPDATEREQUEST"], + ], + "_repoviewallocationrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOVIEWALLOCATIONREQUEST"], + ], + "_repoviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REPOVIEWREQUEST"], + ], + "_revokecredentialsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._REVOKECREDENTIALSREQUEST"], + ], + "_schemacreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._SCHEMACREATEREQUEST"], + ], + "_schemadatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._SCHEMADATAREPLY"], + ], + "_schemadeleterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._SCHEMADELETEREQUEST"], + ], + "_schemareviserequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._SCHEMAREVISEREQUEST"], + ], + "_schemasearchrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._SCHEMASEARCHREQUEST"], + ], + "_schemaupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._SCHEMAUPDATEREQUEST"], + ], + "_schemaviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._SCHEMAVIEWREQUEST"], + ], + "_searchrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._SEARCHREQUEST"], + ], + "_tagdatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._TAGDATAREPLY"], + ], + "_taglistbycountrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._TAGLISTBYCOUNTREQUEST"], + ], + "_tagsearchrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._TAGSEARCHREQUEST"], + ], + "_taskdatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._TASKDATAREPLY"], + ], + "_tasklistrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._TASKLISTREQUEST"], + ], + "_taskviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._TASKVIEWREQUEST"], + ], + "_topicdatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._TOPICDATAREPLY"], + ], + "_topiclisttopicsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._TOPICLISTTOPICSREQUEST"], + ], + "_topicsearchrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._TOPICSEARCHREQUEST"], + ], + "_topicviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._TOPICVIEWREQUEST"], + ], + "_useraccesstokenreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._USERACCESSTOKENREPLY"], + ], + "_usercreaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._USERCREATEREQUEST"], + ], + "_userdatareply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._USERDATAREPLY"], + ], + "_userfindbynameuidrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._USERFINDBYNAMEUIDREQUEST"], + ], + "_userfindbyuuidsrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._USERFINDBYUUIDSREQUEST"], + ], + "_usergetaccesstokenrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._USERGETACCESSTOKENREQUEST"], + ], + "_usergetrecentepreply (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._USERGETRECENTEPREPLY"], + ], + "_usergetrecenteprequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._USERGETRECENTEPREQUEST"], + ], + "_userlistallrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._USERLISTALLREQUEST"], + ], + "_userlistcollabrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._USERLISTCOLLABREQUEST"], + ], + "_usersetaccesstokenrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._USERSETACCESSTOKENREQUEST"], + ], + "_usersetrecenteprequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._USERSETRECENTEPREQUEST"], + ], + "_userupdaterequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._USERUPDATEREQUEST"], + ], + "_userviewrequest (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._USERVIEWREQUEST"], + ], + "_msg_name_to_type (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._msg_name_to_type"], + [8, "id0"], + [8, "id10"], + [8, "id12"], + [8, "id14"], + [8, "id16"], + [8, "id18"], + [8, "id2"], + [8, "id20"], + [8, "id22"], + [8, "id24"], + [8, "id26"], + [8, "id28"], + [8, "id30"], + [8, "id4"], + [8, "id6"], + [8, "id8"], + ], + "_msg_type_to_name (in module datafed.sdms_auth_pb2)": [ + [8, "datafed.SDMS_Auth_pb2._msg_type_to_name"], + [8, "id1"], + [8, "id11"], + [8, "id13"], + [8, "id15"], + [8, "id17"], + [8, "id19"], + [8, "id21"], + [8, "id23"], + [8, "id25"], + [8, "id27"], + [8, "id29"], + [8, "id3"], + [8, "id31"], + [8, "id5"], + [8, "id7"], + [8, "id9"], + ], + "_sym_db (in module datafed.sdms_auth_pb2)": [[8, "datafed.SDMS_Auth_pb2._sym_db"]], + "datafed.sdms_auth_pb2": [[8, "module-datafed.SDMS_Auth_pb2"]], + "aclrule (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ACLRule"]], + "allocdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.AllocData"]], + "allocstatsdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.AllocStatsData"]], + "colldata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.CollData"]], + "dep_in (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DEP_IN"]], + "dep_is_component_of (in module datafed.sdms_pb2)": [ + [9, "datafed.SDMS_pb2.DEP_IS_COMPONENT_OF"], + ], + "dep_is_derived_from (in module datafed.sdms_pb2)": [ + [9, "datafed.SDMS_pb2.DEP_IS_DERIVED_FROM"], + ], + "dep_is_new_version_of (in module datafed.sdms_pb2)": [ + [9, "datafed.SDMS_pb2.DEP_IS_NEW_VERSION_OF"], + ], + "dep_out (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DEP_OUT"]], + "dep_type_count (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DEP_TYPE_COUNT"]], + "descriptor (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DESCRIPTOR"]], + "dependencydata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DependencyData"]], + "dependencydir (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DependencyDir"]], + "dependencyspecdata (in module datafed.sdms_pb2)": [ + [9, "datafed.SDMS_pb2.DependencySpecData"], + ], + "dependencytype (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.DependencyType"]], + "encrypt_avail (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ENCRYPT_AVAIL"]], + "encrypt_force (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ENCRYPT_FORCE"]], + "encrypt_none (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ENCRYPT_NONE"]], + "encryption (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.Encryption"]], + "errorcode (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ErrorCode"]], + "groupdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.GroupData"]], + "id_authn_error (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ID_AUTHN_ERROR"]], + "id_authn_required (in module datafed.sdms_pb2)": [ + [9, "datafed.SDMS_pb2.ID_AUTHN_REQUIRED"], + ], + "id_bad_request (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ID_BAD_REQUEST"]], + "id_client_error (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ID_CLIENT_ERROR"]], + "id_dest_file_error (in module datafed.sdms_pb2)": [ + [9, "datafed.SDMS_pb2.ID_DEST_FILE_ERROR"], + ], + "id_dest_path_error (in module datafed.sdms_pb2)": [ + [9, "datafed.SDMS_pb2.ID_DEST_PATH_ERROR"], + ], + "id_internal_error (in module datafed.sdms_pb2)": [ + [9, "datafed.SDMS_pb2.ID_INTERNAL_ERROR"], + ], + "id_service_error (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ID_SERVICE_ERROR"]], + "listingdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ListingData"]], + "note_active (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NOTE_ACTIVE"]], + "note_closed (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NOTE_CLOSED"]], + "note_error (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NOTE_ERROR"]], + "note_info (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NOTE_INFO"]], + "note_open (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NOTE_OPEN"]], + "note_question (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NOTE_QUESTION"]], + "note_warn (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NOTE_WARN"]], + "notecomment (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NoteComment"]], + "notedata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NoteData"]], + "notestate (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NoteState"]], + "notetype (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.NoteType"]], + "proj_admin (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.PROJ_ADMIN"]], + "proj_manager (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.PROJ_MANAGER"]], + "proj_member (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.PROJ_MEMBER"]], + "proj_no_role (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.PROJ_NO_ROLE"]], + "pathdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.PathData"]], + "projectdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ProjectData"]], + "projectrole (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ProjectRole"]], + "recorddata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.RecordData"]], + "recorddatalocation (in module datafed.sdms_pb2)": [ + [9, "datafed.SDMS_pb2.RecordDataLocation"], + ], + "recorddatasize (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.RecordDataSize"]], + "repodata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.RepoData"]], + "reporecorddatalocations (in module datafed.sdms_pb2)": [ + [9, "datafed.SDMS_pb2.RepoRecordDataLocations"], + ], + "sm_collection (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SM_COLLECTION"]], + "sm_data (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SM_DATA"]], + "sort_id (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SORT_ID"]], + "sort_owner (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SORT_OWNER"]], + "sort_relevance (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SORT_RELEVANCE"]], + "sort_time_create (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SORT_TIME_CREATE"]], + "sort_time_update (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SORT_TIME_UPDATE"]], + "sort_title (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SORT_TITLE"]], + "ss_degraded (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SS_DEGRADED"]], + "ss_failed (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SS_FAILED"]], + "ss_normal (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SS_NORMAL"]], + "ss_offline (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SS_OFFLINE"]], + "schemadata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SchemaData"]], + "searchmode (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SearchMode"]], + "servicestatus (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.ServiceStatus"]], + "sortoption (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.SortOption"]], + "tc_alloc_create (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TC_ALLOC_CREATE"]], + "tc_alloc_delete (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TC_ALLOC_DELETE"]], + "tc_raw_data_delete (in module datafed.sdms_pb2)": [ + [9, "datafed.SDMS_pb2.TC_RAW_DATA_DELETE"], + ], + "tc_raw_data_transfer (in module datafed.sdms_pb2)": [ + [9, "datafed.SDMS_pb2.TC_RAW_DATA_TRANSFER"], + ], + "tc_raw_data_update_size (in module datafed.sdms_pb2)": [ + [9, "datafed.SDMS_pb2.TC_RAW_DATA_UPDATE_SIZE"], + ], + "tc_stop (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TC_STOP"]], + "ts_blocked (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TS_BLOCKED"]], + "ts_failed (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TS_FAILED"]], + "ts_ready (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TS_READY"]], + "ts_running (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TS_RUNNING"]], + "ts_succeeded (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TS_SUCCEEDED"]], + "tt_alloc_create (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_ALLOC_CREATE"]], + "tt_alloc_del (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_ALLOC_DEL"]], + "tt_data_del (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_DATA_DEL"]], + "tt_data_get (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_DATA_GET"]], + "tt_data_put (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_DATA_PUT"]], + "tt_proj_del (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_PROJ_DEL"]], + "tt_rec_chg_alloc (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_REC_CHG_ALLOC"]], + "tt_rec_chg_owner (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_REC_CHG_OWNER"]], + "tt_rec_del (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_REC_DEL"]], + "tt_user_del (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TT_USER_DEL"]], + "tagdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TagData"]], + "taskcommand (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TaskCommand"]], + "taskdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TaskData"]], + "taskstatus (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TaskStatus"]], + "tasktype (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TaskType"]], + "topicdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.TopicData"]], + "userdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2.UserData"]], + "_aclrule (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._ACLRULE"]], + "_allocdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._ALLOCDATA"]], + "_allocstatsdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._ALLOCSTATSDATA"]], + "_colldata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._COLLDATA"]], + "_dependencydata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._DEPENDENCYDATA"]], + "_dependencydir (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._DEPENDENCYDIR"]], + "_dependencyspecdata (in module datafed.sdms_pb2)": [ + [9, "datafed.SDMS_pb2._DEPENDENCYSPECDATA"], + ], + "_dependencytype (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._DEPENDENCYTYPE"]], + "_encryption (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._ENCRYPTION"]], + "_errorcode (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._ERRORCODE"]], + "_groupdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._GROUPDATA"]], + "_listingdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._LISTINGDATA"]], + "_notecomment (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._NOTECOMMENT"]], + "_notedata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._NOTEDATA"]], + "_notestate (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._NOTESTATE"]], + "_notetype (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._NOTETYPE"]], + "_pathdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._PATHDATA"]], + "_projectdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._PROJECTDATA"]], + "_projectrole (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._PROJECTROLE"]], + "_recorddata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._RECORDDATA"]], + "_recorddatalocation (in module datafed.sdms_pb2)": [ + [9, "datafed.SDMS_pb2._RECORDDATALOCATION"], + ], + "_recorddatasize (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._RECORDDATASIZE"]], + "_repodata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._REPODATA"]], + "_reporecorddatalocations (in module datafed.sdms_pb2)": [ + [9, "datafed.SDMS_pb2._REPORECORDDATALOCATIONS"], + ], + "_schemadata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._SCHEMADATA"]], + "_searchmode (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._SEARCHMODE"]], + "_servicestatus (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._SERVICESTATUS"]], + "_sortoption (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._SORTOPTION"]], + "_tagdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._TAGDATA"]], + "_taskcommand (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._TASKCOMMAND"]], + "_taskdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._TASKDATA"]], + "_taskstatus (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._TASKSTATUS"]], + "_tasktype (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._TASKTYPE"]], + "_topicdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._TOPICDATA"]], + "_userdata (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._USERDATA"]], + "_sym_db (in module datafed.sdms_pb2)": [[9, "datafed.SDMS_pb2._sym_db"]], + "datafed.sdms_pb2": [[9, "module-datafed.SDMS_pb2"]], + "__version__ (in module datafed.version)": [[10, "datafed.VERSION.__version__"]], + "datafed.version": [[10, "module-datafed.VERSION"]], + "datafed_common_protocol_api_major (in module datafed.version_pb2)": [ + [11, "datafed.Version_pb2.DATAFED_COMMON_PROTOCOL_API_MAJOR"], + ], + "datafed_common_protocol_api_minor (in module datafed.version_pb2)": [ + [11, "datafed.Version_pb2.DATAFED_COMMON_PROTOCOL_API_MINOR"], + ], + "datafed_common_protocol_api_patch (in module datafed.version_pb2)": [ + [11, "datafed.Version_pb2.DATAFED_COMMON_PROTOCOL_API_PATCH"], + ], + "datafed_release_day (in module datafed.version_pb2)": [ + [11, "datafed.Version_pb2.DATAFED_RELEASE_DAY"], + ], + "datafed_release_hour (in module datafed.version_pb2)": [ + [11, "datafed.Version_pb2.DATAFED_RELEASE_HOUR"], + ], + "datafed_release_minute (in module datafed.version_pb2)": [ + [11, "datafed.Version_pb2.DATAFED_RELEASE_MINUTE"], + ], + "datafed_release_month (in module datafed.version_pb2)": [ + [11, "datafed.Version_pb2.DATAFED_RELEASE_MONTH"], + ], + "datafed_release_year (in module datafed.version_pb2)": [ + [11, "datafed.Version_pb2.DATAFED_RELEASE_YEAR"], + ], + "descriptor (in module datafed.version_pb2)": [[11, "datafed.Version_pb2.DESCRIPTOR"]], + "version (in module datafed.version_pb2)": [[11, "datafed.Version_pb2.Version"]], + "_version (in module datafed.version_pb2)": [[11, "datafed.Version_pb2._VERSION"]], + "_sym_db (in module datafed.version_pb2)": [[11, "datafed.Version_pb2._sym_db"]], + "datafed.version_pb2": [[11, "module-datafed.Version_pb2"]], + datafed: [[12, "module-datafed"]], + "name (in module datafed)": [[12, "datafed.name"]], + "version (in module datafed)": [[12, "datafed.version"]], + }, +}); diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 000000000..1ccbe2af1 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,32 @@ +const globals = require("globals"); +const jsdocPlugin = require("eslint-plugin-jsdoc"); + +module.exports = [ + { + ignores: ["docs/_static/**/*", "web/static/jquery/jquery.js", "web/node_modules"], + languageOptions: { + globals: { + ...globals.jquery, + ...globals.node, + }, + }, + files: ["web/**/*.js", "core/**/*.js"], // Adjust file patterns as needed + plugins: { + jsdoc: jsdocPlugin, + }, + rules: { + "jsdoc/check-alignment": "error", + "jsdoc/check-indentation": "error", + "jsdoc/check-param-names": "error", + "jsdoc/check-tag-names": "error", + "jsdoc/check-types": "error", + "jsdoc/require-param": "error", + "jsdoc/require-param-name": "error", + "jsdoc/require-param-type": "error", + "jsdoc/require-param-description": "error", + "jsdoc/require-returns": "error", + "jsdoc/require-returns-description": "error", + "jsdoc/require-returns-type": "error", + }, + }, +]; diff --git a/external/protobuf b/external/protobuf index a9b006bdd..fff909ea5 160000 --- a/external/protobuf +++ b/external/protobuf @@ -1 +1 @@ -Subproject commit a9b006bddd52e289029f16aa77b77e8e0033d9ee +Subproject commit fff909ea5104ca2104898516511ee03ee4505078 diff --git a/jupyter_notebooks/.flake8 b/jupyter_notebooks/.flake8 new file mode 100644 index 000000000..f84a70d81 --- /dev/null +++ b/jupyter_notebooks/.flake8 @@ -0,0 +1,12 @@ +[flake8] +max-line-length = 100 + +# Ignoring the following is specific to jupyternotebooks +# +# F821 - Ignore undefined variable errors, these are false positives in jupyter +# notebooks if they are defined in a previous cell. +# F841 - assigned to but unused, appears because the examples have code +# that the user will need to fill in. +# F401 - imported but unused, occurs because the user will need to fill in +# parts that require the import. +extend-ignore = F821, F401, F841 diff --git a/jupyter_notebooks/0_verify.ipynb b/jupyter_notebooks/0_verify.ipynb index 4b5b215b5..17c849367 100644 --- a/jupyter_notebooks/0_verify.ipynb +++ b/jupyter_notebooks/0_verify.ipynb @@ -1,199 +1,251 @@ { - "cells": [ - {"cell_type": "markdown", "metadata": {}, "source": ["# DataFed Checklist"]}, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import getpass\n", - "import subprocess\n", - "from platform import platform\n", - "import sys", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": ["## 0. Machine information:"], - }, - {"cell_type": "markdown", "metadata": {}, "source": ["Python version:"]}, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["sys.version_info"], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["platform()"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": ["## 1. Verify DataFed installation:"], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "try:\n", - " # This package is not part of anaconda and may need to be installed.\n", - " from datafed.CommandLib import API\n", - "except ImportError:\n", - " print('datafed not found. Installing from pip.')\n", - ' subprocess.call([sys.executable, "-m", "pip", "install", \'datafed\'])\n', - " from datafed.CommandLib import API\n", - "\n", - "from datafed import version as df_ver\n", - "\n", - "if not df_ver.startswith('1.1'):\n", - " print('Attempting to update DataFed.')\n", - ' subprocess.call([sys.executable, "-m", "pip", "install", \'--upgrade\', \'datafed\'])\n', - " print('Please restart the python kernel or upgrade manually to V 1.1.0:1 if you are repeatedly seeing this message via'\n", - " '\\n\\tpip install --upgrade datafed')\n", - "else: \n", - " df_api = API()\n", - " print('Success! You have DataFed: ' + df_ver)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": ["## 2. Verify user authentication: "], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "if df_api.getAuthUser():\n", - " print('Success! You have been authenticated into DataFed as: ' + df_api.getAuthUser())\n", - "else:\n", - " print('You have not authenticated into DataFed Client')\n", - " print('Please follow instructions in the \"Basic Configuration\" section in the link below to authenticate yourself:')\n", - " print('https://ornl.github.io/DataFed/user/client/install.html#basic-configuration')", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": ["## 3. Ensure Globus Endpoint is set:"], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "if not df_api.endpointDefaultGet():\n", - " print('Please follow instructions in the link below to find your Globus Endpoint:')\n", - " print('https://ornl.github.io/DataFed/system/getting_started.html#install-identify-globus-endpoint')\n", - " endpoint = input('\\nPlease enter either the Endpoint UUID or Legacy Name for your Globus Endpoint: ')\n", - " df_api.endpointDefaultSet(endpoint)\n", - " \n", - "print('Your default Globus Endpoint in DataFed is:\\n' + df_api.endpointDefaultGet())", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 4. Test Globus Endpoint:\n", - "And in the case of Windows - write access to the folder:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dget_resp = df_api.dataGet('d/35437908',\n", - " os.path.abspath('.'), \n", - " wait=True)\n", - "dget_resp", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "if dget_resp[0].task[0].status == 3:\n", - " print('Success! Downloaded a test file to your location. Removing the file now')\n", - " os.remove('35437908.md5sum')\n", - "else:\n", - ' if dget_resp[0].task[0].msg == "globus connect offline":\n', - " print('You need to activate your Globus Endpoint and/or ensure Globus Connect Personal is running.\\n'\n", - " 'Please visit https://globus.org to activate your Endpoint')\n", - ' elif dget_resp[0].task[0].msg == "permission denied":\n', - " print('Globus does not have write access to this directory. \\n'\n", - " 'If you are using Globus Connect Personal, ensure that this notebook runs within'\n", - " 'one of the directories where Globus has write access. You may consider moving this'\n", - " 'notebook to a valid directory or add this directory to the Globus Connect Personal settings')\n", - " else:\n", - " NotImplementedError('Get in touch with us or consider looking online to find a solution to this problem:\\n' + dget_resp[0].task[0].msg)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### (Optional) for Windows - test for Admin priveleges\n", - "Admin priveleges may be necessary to remove files or directories using Python:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import ctypes, os\n", - "try:\n", - " is_admin = os.getuid() == 0\n", - "except AttributeError:\n", - " is_admin = ctypes.windll.shell32.IsUserAnAdmin() != 0\n", - " \n", - "is_admin", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [], - }, - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3", - }, - "language_info": { - "codemirror_mode": {"name": "ipython", "version": 3}, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.3", - }, - }, - "nbformat": 4, - "nbformat_minor": 2, + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# DataFed Checklist" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import subprocess\n", + "from platform import platform\n", + "import sys\n", + "import ctypes\n", + "\n", + "try:\n", + " # This package is not part of anaconda and may need to be\n", + " # installed.\n", + " from datafed.CommandLib import API\n", + "except ImportError:\n", + " print(\"datafed not found. Installing from pip.\")\n", + " subprocess.call([sys.executable, \"-m\", \"pip\", \"install\", \"datafed\"])\n", + " from datafed.CommandLib import API\n", + "\n", + "from datafed import version as df_ver" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 0. Machine information:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python version:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sys.version_info" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "platform()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. Verify DataFed installation:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "if not df_ver.startswith(\"1.1\"):\n", + " print(\"Attempting to update DataFed.\")\n", + " subprocess.call([sys.executable, \"-m\", \"pip\", \"install\", \"--upgrade\", \"datafed\"])\n", + " print(\n", + " \"Please restart the python kernel or upgrade manually to V \"\n", + " \" 1.1.0:1 if you are repeatedly seeing this message via\"\n", + " \"\\n\\tpip install --upgrade datafed\"\n", + " )\n", + "else:\n", + " df_api = API()\n", + " print(\"Success! You have DataFed: \" + df_ver)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. Verify user authentication: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "if df_api.getAuthUser():\n", + " print(\n", + " \"Success! You have been authenticated into DataFed as: \"\n", + " df_api.getAuthUser()\n", + " )\n", + "else:\n", + " print(\"You have not authenticated into DataFed Client\")\n", + " print(\n", + " 'Please follow instructions in the \"Basic Configuration\" '\n", + " 'section in the link below to authenticate yourself:'\n", + " )\n", + " print(\"https://ornl.github.io/DataFed/user/client/\"\n", + " \"install.html#basic-configuration\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. Ensure Globus Endpoint is set:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "if not df_api.endpointDefaultGet():\n", + " print(\"Please follow instructions in the link below to find \" \"your Globus Endpoint:\")\n", + " print(\n", + " \"https://ornl.github.io/DataFed/system/getting_started.\"\n", + " \"html#install-identify-globus-endpoint\"\n", + " )\n", + " endpoint = input(\n", + " \"\\nPlease enter either the Endpoint UUID or Legacy Name \" \"for your Globus Endpoint: \"\n", + " )\n", + " df_api.endpointDefaultSet(endpoint)\n", + "\n", + "print(\"Your default Globus Endpoint in DataFed is:\\n\" f\"{df_api.endpointDefaultGet()}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4. Test Globus Endpoint:\n", + "And in the case of Windows - write access to the folder:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dget_resp = df_api.dataGet(\"d/35437908\", os.path.abspath(\".\"), wait=True)\n", + "dget_resp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "if dget_resp[0].task[0].status == 3:\n", + " print(\"Success! Downloaded a test file to your location.\" \"Removing the file now\")\n", + " os.remove(\"35437908.md5sum\")\n", + "else:\n", + " if dget_resp[0].task[0].msg == \"globus connect offline\":\n", + " print(\n", + " \"You need to activate your Globus Endpoint and/or ensure \"\n", + " \"Globus Connect Personal is running.\\n\"\n", + " \"Please visit https://globus.org to activate your Endpoint\"\n", + " )\n", + " elif dget_resp[0].task[0].msg == \"permission denied\":\n", + " print(\n", + " \"Globus does not have write access to this directory.\\n\"\n", + " \"If you are using Globus Connect Personal, ensure that\"\n", + " \"this notebook runs within one of the directories where \"\n", + " \"Globus has write access. You may consider moving this\"\n", + " \"notebook to a valid directory or add this directory to \"\n", + " \"the Globus Connect Personal settings\"\n", + " )\n", + " else:\n", + " NotImplementedError(\n", + " \"Get in touch with us or consider looking online to \"\n", + " \"find a solution to this problem:\\n\"\n", + " f\"{dget_resp[0].task[0].msg}\"\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### (Optional) for Windows - test for Admin priveleges\n", + "Admin priveleges may be necessary to remove files or directories ", + "using Python:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "try:\n", + " is_admin = os.getuid() == 0\n", + "except AttributeError:\n", + " is_admin = ctypes.windll.shell32.IsUserAnAdmin() != 0\n", + "\n", + "is_admin" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/jupyter_notebooks/1_Basics.ipynb b/jupyter_notebooks/1_Basics.ipynb index 114aa73e3..17cd726e4 100644 --- a/jupyter_notebooks/1_Basics.ipynb +++ b/jupyter_notebooks/1_Basics.ipynb @@ -1,310 +1,344 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Getting Started with DataFed\n", - "In this notebook we will be going over basic concepts such as ``contexts``, ``projects``, understanding how DataFed responds to function calls, etc. \n", - "\n", - "To get started, we need to import only the ``API`` class from ``CommandLab`` in the datafed package. ", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["from datafed.CommandLib import API"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": ["Next, we need to instantiate the ``API`` class as:"], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api = API()"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# First DataFed function\n", - "Let's try out the DataFed API by simply asking DataFed for a list of all projects that we are part of using the ``projectList()`` function:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["pl_resp = df_api.projectList()\n", "print(pl_resp)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Jupyter Tip: \n', - '> With the cursor just past the starting parenthesis of ``projectList(``, simultaneously press the ``Shift`` and ``Tab`` keys once, twice, or four times to view more of the documentation about the function. \n', - "\n", - "## DataFed Messages\n", - "\n", - "DataFed responds using ``Google Protocol Buffer`` or ``protobuf`` messages\n", - "\n", - "Let's take a closer look at this response:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["print(type(pl_resp), len(pl_resp))"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As you can see, the reply is a tuple containing two objects, namely the protobuf message reply itself, `[0]` and the type of reply received, `ListingReply` at `[1]`. We can confirm this by checking the response type:" - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["type(pl_resp[0])"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Contexts\n", - 'DataFed allows us to work within multiple different "data spaces" – such as our own ``Personal Data``, and those of our ``Project``s. Let\'s find out what ``context`` DataFed automatically put us into using ``getContext()``:', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["print(df_api.getContext())"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "By default, DataFed sets our working space or ``context`` to our own ``Personal Data`` (`u/username`). \n", - "\n", - "### Specifying contexts:\n", - "If we want to take a look at the ``root`` collection of the Training Project, we need to specify that using the `context` keyword argument:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["print(df_api.collectionView('root', context='p/trn001'))"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here's what we get when we give the same `collectionView` request without the project context:" - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["print(df_api.collectionView('root'))"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Subscripting and Iterating messages\n", - "Let us take a look at the contents of the Project (its ``root`` Collection) using ``collectionItemsList()``", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ls_resp = df_api.collectionItemsList('root', context='p/trn001')\n", - "print(ls_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Much like the ``projectList()``, we get a ``ListingReply`` in this case as well\n", - "\n", - "### Subscripting\n", - "The listing reply `item` behaves similarly to a python list in terms of subscriptability. For example, in order to access the title of the last item in the collection listing, we can use indexing:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["ls_resp[0].item[-1].title"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Iterating\n", - "These messages also mirror python lists in their iterability. We can iterate through the items in this listing and use the subscripting capability to only extract the ``id`` and ``alias`` fields of each of the collections", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for record in ls_resp[0].item:\n", - " print(record.id, '\\t', record.alias)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Aliases and IDs\n", - "\n", - "Let's try taking a closer look at the ``PROJSHARE`` collection using its ``alias``:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api.collectionView('projshare')"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The above request failed because we asked DataFed to look for a Collection with alias: ``projshare`` without specifying the ``context``. Naturally, DataFed assumed that we meant our own ``Personal Data`` rather than the training ``Project``. \n", - "\n", - "If we want to address an item by its ``alias``, we need to be careful about its ``context`` since:\n", - "\n", - "**An ``alias`` is unique only within a given ``context``** such as ``Personal Data`` or a ``Project``\n", - "\n", - '### Exercise: \n', - ' Correct the above function call to view ``projshare`` collection: ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Alternatively, we can view the correct collection by referring to it using its ``id``:" - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api.collectionView('c/34559108')"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The above command worked even though we did not specify a ``context`` because:\n", - "\n", - "**``ID``s are unique across DataFed and do not need a ``context``**


\n", - "\n", - "## Setting Context:\n", - "Having to specify the context for every function call can be tiring if we are sure we are working within a single context. \n", - "\n", - "We can set the context via the ``setContext()`` function:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api.setContext('p/trn001')"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Note \n', - '> ``setContext()`` is valid within the scope of a single python session. You would need to call the function each time you instantiate the DataFed ``CommandLib.API`` class. E.g. - at the top of every notebook ', - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's attempt to view the ``projshare`` Collection via its ``alias`` **without** specifying the ``context`` keyword argument:" - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api.collectionView('projshare')"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise: \n', - ' Using the DataFed API\'s `collectionView()`, extract the create time (`ct`) of your own personal collection within the training project or ``projshare``.

Bonus: Consider using the built-in `df_api.timestampToStr()` function or `datetime.datetime.fromtimestamp` from the `datetime` package to convert the unix formatted time to a human readable string
', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["create_time = "], - }, - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python [default]", - "language": "python", - "name": "python3", - }, - "language_info": { - "codemirror_mode": {"name": "ipython", "version": 3}, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.5", - }, - }, - "nbformat": 4, - "nbformat_minor": 4, + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Getting Started with DataFed\n", + "In this notebook we will be going over basic concepts such as ``contexts``, ``projects``, understanding how DataFed responds to function calls, etc. \n", + "\n", + "To get started, we need to import only the ``API`` class from ``CommandLab`` in the datafed package. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from datafed.CommandLib import API" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to instantiate the ``API`` class as:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api = API()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# First DataFed function\n", + "Let's try out the DataFed API by simply asking DataFed for a list of all projects that we are part of using the ``projectList()`` function:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pl_resp = df_api.projectList()\n", + "print(pl_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Jupyter Tip: \n", + "> With the cursor just past the starting parenthesis of ``projectList(``, simultaneously press the ``Shift`` and ``Tab`` keys once, twice, or four times to view more of the documentation about the function. \n", + "\n", + "## DataFed Messages\n", + "\n", + "DataFed responds using ``Google Protocol Buffer`` or ``protobuf`` messages\n", + "\n", + "Let's take a closer look at this response:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(type(pl_resp), len(pl_resp))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see, the reply is a tuple containing two objects, namely the protobuf message reply itself, `[0]` and the type of reply received, `ListingReply` at `[1]`. We can confirm this by checking the response type:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(pl_resp[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Contexts\n", + "DataFed allows us to work within multiple different \"data spaces\" – such as our own ``Personal Data``, and those of our ``Project``s. Let's find out what ``context`` DataFed automatically put us into using ``getContext()``:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(df_api.getContext())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "By default, DataFed sets our working space or ``context`` to our own ``Personal Data`` (`u/username`). \n", + "\n", + "### Specifying contexts:\n", + "If we want to take a look at the ``root`` collection of the Training Project, we need to specify that using the `context` keyword argument:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(df_api.collectionView(\"root\", context=\"p/trn001\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here's what we get when we give the same `collectionView` request without the project context:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(df_api.collectionView(\"root\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Subscripting and Iterating messages\n", + "Let us take a look at the contents of the Project (its ``root`` Collection) using ``collectionItemsList()``" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ls_resp = df_api.collectionItemsList(\"root\", context=\"p/trn001\")\n", + "print(ls_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Much like the ``projectList()``, we get a ``ListingReply`` in this case as well\n", + "\n", + "### Subscripting\n", + "The listing reply `item` behaves similarly to a python list in terms of subscriptability. For example, in order to access the title of the last item in the collection listing, we can use indexing:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ls_resp[0].item[-1].title" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Iterating\n", + "These messages also mirror python lists in their iterability. We can iterate through the items in this listing and use the subscripting capability to only extract the ``id`` and ``alias`` fields of each of the collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for record in ls_resp[0].item:\n", + " print(record.id, \"\\t\", record.alias)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Aliases and IDs\n", + "\n", + "Let's try taking a closer look at the ``PROJSHARE`` collection using its ``alias``:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api.collectionView(\"projshare\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The above request failed because we asked DataFed to look for a Collection with alias: ``projshare`` without specifying the ``context``. Naturally, DataFed assumed that we meant our own ``Personal Data`` rather than the training ``Project``. \n", + "\n", + "If we want to address an item by its ``alias``, we need to be careful about its ``context`` since:\n", + "\n", + "**An ``alias`` is unique only within a given ``context``** such as ``Personal Data`` or a ``Project``\n", + "\n", + "### Exercise: \n", + " Correct the above function call to view ``projshare`` collection: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Alternatively, we can view the correct collection by referring to it using its ``id``:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api.collectionView(\"c/34559108\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The above command worked even though we did not specify a ``context`` because:\n", + "\n", + "**``ID``s are unique across DataFed and do not need a ``context``**


\n", + "\n", + "## Setting Context:\n", + "Having to specify the context for every function call can be tiring if we are sure we are working within a single context. \n", + "\n", + "We can set the context via the ``setContext()`` function:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api.setContext(\"p/trn001\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Note \n", + "> ``setContext()`` is valid within the scope of a single python session. You would need to call the function each time you instantiate the DataFed ``CommandLib.API`` class. E.g. - at the top of every notebook " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's attempt to view the ``projshare`` Collection via its ``alias`` **without** specifying the ``context`` keyword argument:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api.collectionView(\"projshare\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise: \n", + " Using the DataFed API's `collectionView()`, extract the create time (`ct`) of your own personal collection within the training project or ``projshare``.

Bonus: Consider using the built-in `df_api.timestampToStr()` function or `datetime.datetime.fromtimestamp` from the `datetime` package to convert the unix formatted time to a human readable string
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "create_time = " + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/jupyter_notebooks/1_Basics_with_Solutions.ipynb b/jupyter_notebooks/1_Basics_with_Solutions.ipynb index da1293f95..439b3e58e 100644 --- a/jupyter_notebooks/1_Basics_with_Solutions.ipynb +++ b/jupyter_notebooks/1_Basics_with_Solutions.ipynb @@ -1,323 +1,357 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Getting Started with DataFed\n", - "In this notebook we will be going over basic concepts such as ``contexts``, ``projects``, understanding how DataFed responds to function calls, etc. \n", - "\n", - "To get started, we need to import only the ``API`` class from ``CommandLab`` in the datafed package. ", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["from datafed.CommandLib import API"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": ["Next, we need to instantiate the ``API`` class as:"], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api = API()"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# First DataFed function\n", - "Let's try out the DataFed API by simply asking DataFed for a list of all projects that we are part of using the ``projectList()`` function:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["pl_resp = df_api.projectList()\n", "print(pl_resp)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Jupyter Tip: \n', - '> With the cursor just past the starting parenthesis of ``projectList(``, simultaneously press the ``Shift`` and ``Tab`` keys once, twice, or four times to view more of the documentation about the function. \n', - "\n", - "## DataFed Messages\n", - "\n", - "DataFed responds using ``Google Protocol Buffer`` or ``protobuf`` messages\n", - "\n", - "Let's take a closer look at this response:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["print(type(pl_resp), len(pl_resp))"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As you can see, the reply is a tuple containing two objects, namely the protobuf message reply itself, `[0]` and the type of reply received, `ListingReply` at `[1]`. We can confirm this by checking the response type:" - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["type(pl_resp[0])"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Contexts\n", - 'DataFed allows us to work within multiple different "data spaces" – such as our own ``Personal Data``, and those of our ``Project``s. Let\'s find out what ``context`` DataFed automatically put us into using ``getContext()``:', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["print(df_api.getContext())"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "By default, DataFed sets our working space or ``context`` to our own ``Personal Data`` (`u/username`). \n", - "\n", - "### Specifying contexts:\n", - "If we want to take a look at the ``root`` collection of the Training Project, we need to specify that using the `context` keyword argument:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["print(df_api.collectionView('root', context='p/trn001'))"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here's what we get when we give the same `collectionView` request without the project context:" - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["print(df_api.collectionView('root'))"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Subscripting and Iterating messages\n", - "Let us take a look at the contents of the Project (its ``root`` Collection) using ``collectionItemsList()``", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ls_resp = df_api.collectionItemsList('root', context='p/trn001')\n", - "print(ls_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Much like the ``projectList()``, we get a ``ListingReply`` in this case as well\n", - "\n", - "### Subscripting\n", - "The listing reply `item` behaves similarly to a python list in terms of subscriptability. For example, in order to access the title of the last item in the collection listing, we can use indexing:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["ls_resp[0].item[-1].title"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Iterating\n", - "These messages also mirror python lists in their iterability. We can iterate through the items in this listing and use the subscripting capability to only extract the ``id`` and ``alias`` fields of each of the collections", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for record in ls_resp[0].item:\n", - " print(record.id, '\\t', record.alias)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Aliases and IDs\n", - "\n", - "Let's try taking a closer look at the ``PROJSHARE`` collection using its ``alias``:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api.collectionView('projshare')"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The above request failed because we asked DataFed to look for a Collection with alias: ``projshare`` without specifying the ``context``. Naturally, DataFed assumed that we meant our own ``Personal Data`` rather than the training ``Project``. \n", - "\n", - "If we want to address an item by its ``alias``, we need to be careful about its ``context`` since:\n", - "\n", - "**An ``alias`` is unique only within a given ``context``** such as ``Personal Data`` or a ``Project``\n", - "\n", - '### Exercise: \n', - ' Correct the above function call to view ``projshare`` collection: ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api.collectionView('projshare', context='p/trn001)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Alternatively, we can view the correct collection by referring to it using its ``id``:" - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api.collectionView('c/34559108')"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The above command worked even though we did not specify a ``context`` because:\n", - "\n", - "**``ID``s are unique across DataFed and do not need a ``context``**


\n", - "\n", - "## Setting Context:\n", - "Having to specify the context for every function call can be tiring if we are sure we are working within a single context. \n", - "\n", - "We can set the context via the ``setContext()`` function:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api.setContext('p/trn001')"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Note \n', - '> ``setContext()`` is valid within the scope of a single python session. You would need to call the function each time you instantiate the DataFed ``CommandLib.API`` class. E.g. - at the top of every notebook ', - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's attempt to view the ``projshare`` Collection via its ``alias`` **without** specifying the ``context`` keyword argument:" - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api.collectionView('projshare')"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise: \n', - ' Using the DataFed API\'s `collectionView()`, extract the create time (`ct`) of your own personal collection within the training project or ``projshare``.

Bonus: Consider using the built-in `df_api.timestampToStr()` function or `datetime.datetime.fromtimestamp` from the `datetime` package to convert the unix formatted time to a human readable string
', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "personal_collection_id = ?\n", - "create_time = df_api.collectionView(personal_collection_id)[0].coll[0].ct\n", - "\n", - "# Bonus:\n", - "df_api.timestampToStr(create_time)\n", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [], - }, - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3", - }, - "language_info": { - "codemirror_mode": {"name": "ipython", "version": 3}, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.9", - }, - }, - "nbformat": 4, - "nbformat_minor": 4, + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Getting Started with DataFed\n", + "In this notebook we will be going over basic concepts such as ``contexts``, ``projects``, understanding how DataFed responds to function calls, etc. \n", + "\n", + "To get started, we need to import only the ``API`` class from ``CommandLab`` in the datafed package. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from datafed.CommandLib import API" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to instantiate the ``API`` class as:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api = API()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# First DataFed function\n", + "Let's try out the DataFed API by simply asking DataFed for a list of all projects that we are part of using the ``projectList()`` function:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pl_resp = df_api.projectList()\n", + "print(pl_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Jupyter Tip: \n", + "> With the cursor just past the starting parenthesis of ``projectList(``, simultaneously press the ``Shift`` and ``Tab`` keys once, twice, or four times to view more of the documentation about the function. \n", + "\n", + "## DataFed Messages\n", + "\n", + "DataFed responds using ``Google Protocol Buffer`` or ``protobuf`` messages\n", + "\n", + "Let's take a closer look at this response:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(type(pl_resp), len(pl_resp))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see, the reply is a tuple containing two objects, namely the protobuf message reply itself, `[0]` and the type of reply received, `ListingReply` at `[1]`. We can confirm this by checking the response type:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(pl_resp[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Contexts\n", + "DataFed allows us to work within multiple different \"data spaces\" – such as our own ``Personal Data``, and those of our ``Project``s. Let's find out what ``context`` DataFed automatically put us into using ``getContext()``:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(df_api.getContext())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "By default, DataFed sets our working space or ``context`` to our own ``Personal Data`` (`u/username`). \n", + "\n", + "### Specifying contexts:\n", + "If we want to take a look at the ``root`` collection of the Training Project, we need to specify that using the `context` keyword argument:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(df_api.collectionView(\"root\", context=\"p/trn001\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here's what we get when we give the same `collectionView` request without the project context:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(df_api.collectionView(\"root\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Subscripting and Iterating messages\n", + "Let us take a look at the contents of the Project (its ``root`` Collection) using ``collectionItemsList()``" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ls_resp = df_api.collectionItemsList(\"root\", context=\"p/trn001\")\n", + "print(ls_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Much like the ``projectList()``, we get a ``ListingReply`` in this case as well\n", + "\n", + "### Subscripting\n", + "The listing reply `item` behaves similarly to a python list in terms of subscriptability. For example, in order to access the title of the last item in the collection listing, we can use indexing:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ls_resp[0].item[-1].title" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Iterating\n", + "These messages also mirror python lists in their iterability. We can iterate through the items in this listing and use the subscripting capability to only extract the ``id`` and ``alias`` fields of each of the collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for record in ls_resp[0].item:\n", + " print(record.id, \"\\t\", record.alias)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Aliases and IDs\n", + "\n", + "Let's try taking a closer look at the ``PROJSHARE`` collection using its ``alias``:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api.collectionView(\"projshare\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The above request failed because we asked DataFed to look for a Collection with alias: ``projshare`` without specifying the ``context``. Naturally, DataFed assumed that we meant our own ``Personal Data`` rather than the training ``Project``. \n", + "\n", + "If we want to address an item by its ``alias``, we need to be careful about its ``context`` since:\n", + "\n", + "**An ``alias`` is unique only within a given ``context``** such as ``Personal Data`` or a ``Project``\n", + "\n", + "### Exercise: \n", + " Correct the above function call to view ``projshare`` collection: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api.collectionView('projshare', context='p/trn001)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Alternatively, we can view the correct collection by referring to it using its ``id``:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api.collectionView(\"c/34559108\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The above command worked even though we did not specify a ``context`` because:\n", + "\n", + "**``ID``s are unique across DataFed and do not need a ``context``**


\n", + "\n", + "## Setting Context:\n", + "Having to specify the context for every function call can be tiring if we are sure we are working within a single context. \n", + "\n", + "We can set the context via the ``setContext()`` function:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api.setContext(\"p/trn001\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Note \n", + "> ``setContext()`` is valid within the scope of a single python session. You would need to call the function each time you instantiate the DataFed ``CommandLib.API`` class. E.g. - at the top of every notebook " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's attempt to view the ``projshare`` Collection via its ``alias`` **without** specifying the ``context`` keyword argument:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api.collectionView(\"projshare\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise: \n", + " Using the DataFed API's `collectionView()`, extract the create time (`ct`) of your own personal collection within the training project or ``projshare``.

Bonus: Consider using the built-in `df_api.timestampToStr()` function or `datetime.datetime.fromtimestamp` from the `datetime` package to convert the unix formatted time to a human readable string
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "personal_collection_id = ?\n", + "create_time = df_api.collectionView(personal_collection_id)[0].coll[0].ct\n", + "\n", + "# Bonus:\n", + "df_api.timestampToStr(create_time)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.9" + } + }, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/jupyter_notebooks/2_Data_Records.ipynb b/jupyter_notebooks/2_Data_Records.ipynb index c2ab45fc1..0b4feb668 100644 --- a/jupyter_notebooks/2_Data_Records.ipynb +++ b/jupyter_notebooks/2_Data_Records.ipynb @@ -1,342 +1,409 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# 2. Data Records\n", - "In this notebook, we will be going over how to create, add metadata and other contextual information, edit, establish relationships between ``Data Records`` - the fundamental unit in DataFed\n", - "\n", - "## Setting up:\n", - "Just as in the previous notebook, we start be instantiating the ``datafed.CommandLib.API`` class to communicate with DataFed:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["from datafed.CommandLib import API"], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api = API()"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Specifying context:\n", - "Since we want to work within the ``context`` of the Training Project:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api.setContext('p/trn001')"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To begin with, you will be working within your own private collection whose ``alias`` is the same as your DataFed username.\n", - "\n", - '### Exercise: \n', - ' Enter your username into the ``parent_collection`` variable ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["parent_collection = ?"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating Data Records:\n", - "Data Records can hold a whole lot of contextual information about the raw data in them. One key component is the scientific metadata. Ideally, we would get this metadata from the headers of the raw data file or some other log file that was generated along with the raw data. \n", - "\n", - '### Note \n', - '> DataFed expects scientific metadata to be specified **like** a python dictionary. \n', - "\n", - "For now, let's set up some dummy metadata:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "parameters = {\n", - " 'a': 4,\n", - " 'b': [1, 2, -4, 7.123],\n", - " 'c': 'Something important',\n", - " 'd': {'x': 14, # Can use nested dictionaries\n", - " 'y': -19\n", - " } \n", - " }", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Note \n', - '> DataFed **currently** encodes metadata in JSON strings. The next version will accept python dictonaries as is.\n', - "\n", - "For now, we will need to convert the metadata to a JSON string using the ``dumps()`` function in the ``json`` package", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["import json\n", "json.dumps(parameters)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We use the `dataCreate()` function to make our new record, and the `json.dumps()` function to format the python dictionary to JSON:" - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dc_resp = df_api.dataCreate('my important data',\n", - " metadata=json.dumps(parameters),\n", - " parent_id=parent_collection, # The parent collection, whose alias is your username\n", - " )\n", - "dc_resp", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '#### **Note:** \n', - '> In the future, the ``dataCreate()`` function would by default return only the ``ID`` of the record instead of such a verbose response if it successfully created the Data Record. We expect to be able to continue to get this verbose response through an optional argument. ', - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise: \n', - ' Extract the ``ID`` of the data record from the message returned from ``dataCreate()`` for future use: ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["record_id = ?\n", "print(record_id)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Data Records and the information in them are not static and can always be modified at any time\n", - "## Updating Data Records\n", - "Let's add some additional metadata and change the title of our record:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "du_resp = df_api.dataUpdate(record_id,\n", - " title='Some new title for the data',\n", - " metadata=json.dumps({'appended_metadata': True})\n", - " )\n", - "print(du_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '#### **Note:** \n', - '> In the future, the dataUpdate() command would return only an acknowledgement of the successful execution of the data update. ', - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Viewing Data Records\n", - "We can get full information about a data record including the complete metadata via the ``dataView()`` function. Let us use this function to verify that the changes have been incorporated:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["dv_resp = df_api.dataView(record_id)\n", "print(dv_resp)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '#### **Note:** \n', - '> Record metadata is always stored as a JSON string. \n', - "\n", - '### Exercise: \n', - ' Try isolating the updated metadata and converting it to a python dictionary. \n', - "\n", - "Hint - ``json.loads()`` is the opposite of ``json.dumps()``", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the first update, we **merged** new metadata with the existing metadata within the record. However ``dataUpdate()`` is also capable of replacing the metadata as well. \n", - "\n", - '### Exercise: \n', - ' Now try to **replace** the metadata.

Hint: look at the `metadata_set` keyword argument in the docstrings.
\n', - "\n", - '### Tip: \n', - '> With the cursor just past the starting parenthesis of ``dataUpdate(``, simultaneously press the ``Shift`` and ``Tab`` keys once, twice, or four times to view more of the documentation about the function. ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "new_metadata = ?\n", - "du_resp = df_api.dataUpdate(record_id,\n", - " ...\n", - " )\n", - "dv_resp = df_api.dataView(record_id)\n", - "print(json.loads(dv_resp[0].data[0].metadata))", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Provenance\n", - "Along with in-depth, detailed scientific metadata describing each data record, DataFed also provides a very handy tool for tracking data provenance, i.e. recording the relationships between Data Records which can be used to track the history, lineage, and origins of a data object. ", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise: \n', - ' Create a new record meant to hold some processed version of the first data record.
**Caution**: Make sure to create it in the correct Collection.
', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "new_params = {}\n", - "\n", - "dc2_resp = df_api.dataCreate( ...\n", - " )\n", - "\n", - "clean_rec_id = dc2_resp[0].data[0].id\n", - "print(clean_rec_id)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Specifying Relationships\n", - "Now that we have two records, we can specify the second record's relationship to the first by adding a **dependency** via the ``deps_add`` keyword argument of the ``dataUpdate()`` function.\n", - "\n", - '### Note: \n', - '> As the documentation for ``dataUpdate()`` will reveal, dependencies must be specified as a ``list`` of relationships. Each relationship is expressed as a ``list`` where the first item is a dependency type (a string) and the second is the data record (also a string). \n', - "\n", - "DataFed currently supports three relationship types:\n", - "* `der` - Is derived from\n", - "* `comp` - Is comprised of\n", - "* `ver` - Is new version of", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dep_resp = df_api.dataUpdate(clean_rec_id, \n", - ' deps_add=[["der", record_id]])\n', - "print(dep_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise: \n', - ' Take a look at the records on the DataFed Web Portal in order to see a graphical representation of the data provenance. ', - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise: \n', - '1. Create a new data record to hold a figure in your journal article.
2. Extract the record ID.
3. Now establish a provenance link between this figure record and the processed data record we just created. You may try out a different dependency type if you like.
4. Take a look at the DataFed web portal to see the update to the Provenance of the records
', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [], - }, - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python [default]", - "language": "python", - "name": "python3", - }, - "language_info": { - "codemirror_mode": {"name": "ipython", "version": 3}, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.5", - }, - }, - "nbformat": 4, - "nbformat_minor": 4, + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 2. Data Records\n", + "In this notebook, we will be going over how to create, add metadata and ", + "other contextual information, edit, establish relationships between ", + "``Data Records`` - the fundamental unit in DataFed\n", + "\n", + "## Setting up:\n", + "Just as in the previous notebook, we start be instantiating the ", + "``datafed.CommandLib.API`` class to communicate with DataFed:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "from datafed.CommandLib import API" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api = API()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Specifying context:\n", + "Since we want to work within the ``context`` of the Training Project:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api.setContext(\"p/trn001\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To begin with, you will be working within your own private collection ", + "whose ``alias`` is the same as your DataFed username.\n", + "\n", + "### Exercise: \n", + " Enter your username into the ", + "``parent_collection`` variable " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "parent_collection = \"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating Data Records:\n", + "Data Records can hold a whole lot of contextual information about the ", + "raw data in them. One key component is the scientific metadata. Ideally, ", + "we would get this metadata from the headers of the raw data file or some ", + "other log file that was generated along with the raw data. \n", + "\n", + "### Note \n", + "> DataFed expects scientific metadata to be ", + "specified **like** a python dictionary. \n", + "\n", + "For now, let's set up some dummy metadata:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "parameters = {\n", + " \"a\": 4,\n", + " \"b\": [1, 2, -4, 7.123],\n", + " \"c\": \"Something important\",\n", + " \"d\": {\"x\": 14, \"y\": -19}, # Can use nested dictionaries\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Note \n", + "> DataFed **currently** encodes metadata in ", + "JSON strings. The next version will accept python dictonaries as ", + "is.\n", + "\n", + "For now, we will need to convert the metadata to a JSON string using the ", + "``dumps()`` function in the ``json`` package" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "json.dumps(parameters)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We use the `dataCreate()` function to make our new record, and the ", + "`json.dumps()` function to format the python dictionary to JSON:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# parent_collection - The parent collection, whose alias is your\n", + "# username\n", + "dc_resp = df_api.dataCreate(\n", + " \"my important data\",\n", + " metadata=json.dumps(parameters),\n", + " parent_id=parent_collection,\n", + ")\n", + "dc_resp" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### **Note:** \n", + "> In the future, the ``dataCreate()`` ", + "function would by default return only the ``ID`` of the record instead ", + "of such a verbose response if it successfully created the Data Record. ", + "We expect to be able to continue to get this verbose response through ", + "an optional argument. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise: \n", + " Extract the ``ID`` of the data record from ", + "the message returned from ``dataCreate()`` for future use: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "record_id = \"\"\n", + "print(record_id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Data Records and the information in them are not static and can always ", + "be modified at any time\n", + "## Updating Data Records\n", + "Let's add some additional metadata and change the title of our record:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "du_resp = df_api.dataUpdate(\n", + " record_id,\n", + " title=\"Some new title for the data\",\n", + " metadata=json.dumps({\"appended_metadata\": True}),\n", + ")\n", + "print(du_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### **Note:** \n", + "> In the future, the dataUpdate() command ", + "would return only an acknowledgement of the successful execution of the ", + "data update. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Viewing Data Records\n", + "We can get full information about a data record including the complete ", + "metadata via the ``dataView()`` function. Let us use this function to ", + "verify that the changes have been incorporated:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dv_resp = df_api.dataView(record_id)\n", + "print(dv_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### **Note:** \n", + "> Record metadata is always stored as a JSON ", + "string. \n", + "\n", + "### Exercise: \n", + " Try isolating the updated metadata and ", + "converting it to a python dictionary. \n", + "\n", + "Hint - ``json.loads()`` is the opposite of ``json.dumps()``" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the first update, we **merged** new metadata with the existing ", + "metadata within the record. However ``dataUpdate()`` is also capable of ", + "replacing the metadata as well. \n", + "\n", + "### Exercise: \n", + " Now try to **replace** the metadata. ", + "

Hint: look at the `metadata_set` keyword argument in the ", + "docstrings.
\n", + "\n", + "### Tip: \n", + "> With the cursor just past the starting ", + "parenthesis of ``dataUpdate(``, simultaneously press the ``Shift`` and ", + "``Tab`` keys once, twice, or four times to view more of the documentation", + " about the function. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "du_resp = df_api.dataUpdate(record_id, ...)\n", + "dv_resp = df_api.dataView(record_id)\n", + "print(json.loads(dv_resp[0].data[0].metadata))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Provenance\n", + "Along with in-depth, detailed scientific metadata describing each data ", + "record, DataFed also provides a very handy tool for tracking data ", + "provenance, i.e. recording the relationships between Data Records which ", + "can be used to track the history, lineage, and origins of a data object. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise: \n", + " Create a new record meant to hold some ", + "processed version of the first data record.
**Caution**: Make sure ", + "to create it in the correct Collection.
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "new_params = {}\n", + "\n", + "dc2_resp = df_api.dataCreate(...)\n", + "\n", + "clean_rec_id = dc2_resp[0].data[0].id\n", + "print(clean_rec_id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Specifying Relationships\n", + "Now that we have two records, we can specify the second record's ", + "relationship to the first by adding a **dependency** via the ``deps_add``", + " keyword argument of the ``dataUpdate()`` function.\n", + "\n", + "### Note: \n", + "> As the documentation for ``dataUpdate()`` ", + "will reveal, dependencies must be specified as a ``list`` of ", + "relationships. Each relationship is expressed as a ``list`` where the ", + "first item is a dependency type (a string) and the second is the data ", + "record (also a string). \n", + "\n", + "DataFed currently supports three relationship types:\n", + "* `der` - Is derived from\n", + "* `comp` - Is comprised of\n", + "* `ver` - Is new version of" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dep_resp = df_api.dataUpdate(clean_rec_id, deps_add=[[\"der\", record_id]])\n", + "print(dep_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise: \n", + " Take a look at the records on the DataFed Web", + " Portal in order to see a graphical representation of the data ", + "provenance. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise: \n", + "1. Create a new data record to hold a figure ", + "in your journal article.
2. Extract the record ID.
3. Now ", + "establish a provenance link between this figure record and the processed", + " data record we just created. You may try out a different dependency ", + "type if you like.
4. Take a look at the DataFed web portal to see ", + "the update to the Provenance of the records
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/jupyter_notebooks/2_Data_Records_with_Solutions.ipynb b/jupyter_notebooks/2_Data_Records_with_Solutions.ipynb index 501df70bf..470b813e5 100644 --- a/jupyter_notebooks/2_Data_Records_with_Solutions.ipynb +++ b/jupyter_notebooks/2_Data_Records_with_Solutions.ipynb @@ -1,354 +1,376 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# 2. Data Records\n", - "In this notebook, we will be going over how to create, add metadata and other contextual information, edit, establish relationships between ``Data Records`` - the fundamental unit in DataFed\n", - "\n", - "## Setting up:\n", - "Just as in the previous notebook, we start be instantiating the ``datafed.CommandLib.API`` class to communicate with DataFed:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["from datafed.CommandLib import API"], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api = API()"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Specifying context:\n", - "Since we want to work within the ``context`` of the Training Project:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api.setContext('p/trn001')"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To begin with, you will be working within your own private collection whose ``alias`` is the same as your DataFed username.\n", - "\n", - '### Exercise: \n', - ' Enter your username into the ``parent_collection`` variable ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["parent_collection = ?"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating Data Records:\n", - "Data Records can hold a whole lot of contextual information about the raw data in them. One key component is the scientific metadata. Ideally, we would get this metadata from the headers of the raw data file or some other log file that was generated along with the raw data. \n", - "\n", - '### Note \n', - '> DataFed expects scientific metadata to be specified **like** a python dictionary. \n', - "\n", - "For now, let's set up some dummy metadata:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "parameters = {\n", - " 'a': 4,\n", - " 'b': [1, 2, -4, 7.123],\n", - " 'c': 'Something important',\n", - " 'd': {'x': 14, # Can use nested dictionaries\n", - " 'y': -19\n", - " } \n", - " }", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Note \n', - '> DataFed **currently** encodes metadata in JSON strings. The next version will accept python dictonaries as is.\n', - "\n", - "For now, we will need to convert the metadata to a JSON string using the ``dumps()`` function in the ``json`` package", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["import json\n", "json.dumps(parameters)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We use the `dataCreate()` function to make our new record, and the `json.dumps()` function to format the python dictionary to JSON:" - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dc_resp = df_api.dataCreate('my important data',\n", - " metadata=json.dumps(parameters),\n", - " parent_id=parent_collection, # The parent collection, whose alias is your username\n", - " )\n", - "dc_resp", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '#### **Note:** \n', - '> In the future, the ``dataCreate()`` function would by default return only the ``ID`` of the record instead of such a verbose response if it successfully created the Data Record. We expect to be able to continue to get this verbose response through an optional argument. ', - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise: \n', - ' Extract the ``ID`` of the data record from the message returned from ``dataCreate()`` for future use: ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["record_id = dc_resp[0].data[0].id\n", "print(record_id)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Data Records and the information in them are not static and can always be modified at any time\n", - "## Updating Data Records\n", - "Let's add some additional metadata and change the title of our record:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "du_resp = df_api.dataUpdate(record_id,\n", - " title='Some new title for the data',\n", - " metadata=json.dumps({'appended_metadata': True})\n", - " )\n", - "print(du_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '#### **Note:** \n', - '> In the future, the dataUpdate() command would return only an acknowledgement of the successful execution of the data update. ', - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Viewing Data Records\n", - "We can get full information about a data record including the complete metadata via the ``dataView()`` function. Let us use this function to verify that the changes have been incorporated:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["dv_resp = df_api.dataView(record_id)\n", "print(dv_resp)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '#### **Note:** \n', - '> Record metadata is always stored as a JSON string. \n', - "\n", - '### Exercise: \n', - ' Try isolating the updated metadata and converting it to a python dictionary. \n', - "\n", - "Hint - ``json.loads()`` is the opposite of ``json.dumps()``", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "metadata = json.loads(dv_resp[0].data[0].metadata)\n", - "print(metadata)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the first update, we **merged** new metadata with the existing metadata within the record. However ``dataUpdate()`` is also capable of replacing the metadata as well. \n", - "\n", - '### Exercise: \n', - ' Now try to **replace** the metadata.

Hint: look at the `metadata_set` keyword argument in the docstrings.
\n', - "\n", - '### Tip: \n', - '> With the cursor just past the starting parenthesis of ``dataUpdate(``, simultaneously press the ``Shift`` and ``Tab`` keys once, twice, or four times to view more of the documentation about the function. ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - 'new_metadata = {"key": "value", "E": \'mc^2\'}\n', - "du_resp = df_api.dataUpdate(record_id,\n", - " metadata = json.dumps(new_metadata),\n", - " metadata_set=True)\n", - "dv_resp = df_api.dataView(record_id)\n", - "print(json.loads(dv_resp[0].data[0].metadata))", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Provenance\n", - "Along with in-depth, detailed scientific metadata describing each data record, DataFed also provides a very handy tool for tracking data provenance, i.e. recording the relationships between Data Records which can be used to track the history, lineage, and origins of a data object. ", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise: \n', - ' Create a new record meant to hold some processed version of the first data record.
**Caution**: Make sure to create it in the correct Collection.
', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - 'new_params = {"hello": "world", "counting": [1, 2, 3, 4]}\n', - "\n", - 'dc2_resp = df_api.dataCreate( "Subsequent Record",\n', - " metadata=json.dumps(new_params),\n", - " parent_id=parent_collection)\n", - "\n", - "clean_rec_id = dc2_resp[0].data[0].id\n", - "print(clean_rec_id)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Specifying Relationships\n", - "Now that we have two records, we can specify the second record's relationship to the first by adding a **dependency** via the ``deps_add`` keyword argument of the ``dataUpdate()`` function.\n", - "\n", - '### Note: \n', - '> As the documentation for ``dataUpdate()`` will reveal, dependencies must be specified as a ``list`` of relationships. Each relationship is expressed as a ``list`` where the first item is a dependency type (a string) and the second is the data record (also a string). \n', - "\n", - "DataFed currently supports three relationship types:\n", - "* `der` - Is derived from\n", - "* `comp` - Is comprised of\n", - "* `ver` - Is new version of", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dep_resp = df_api.dataUpdate(clean_rec_id, \n", - ' deps_add=[["der", record_id]])\n', - "print(dep_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise: \n', - ' Take a look at the records on the DataFed Web Portal in order to see a graphical representation of the data provenance. ', - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise: \n', - '1. Create a new data record to hold a figure in your journal article.
2. Extract the record ID.
3. Now establish a provenance link between this figure record and the processed data record we just created. You may try out a different dependency type if you like.
4. Take a look at the DataFed web portal to see the update to the Provenance of the records
', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# 1\n", - "reply = df_api.dataCreate('Figure 1', parent_id=parent_collection)\n", - "# 2 \n", - "fig_id = reply[0].data[0].id\n", - "# 3 \n", - "provenance_link = df_api.dataUpdate(fig_id, deps_add=[('comp', clean_rec_id)])\n", - "print(provenance_link[0].data[0])", - ], - }, - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3", - }, - "language_info": { - "codemirror_mode": {"name": "ipython", "version": 3}, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.9", - }, - }, - "nbformat": 4, - "nbformat_minor": 4, + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 2. Data Records\n", + "In this notebook, we will be going over how to create, add metadata and other contextual information, edit, establish relationships between ``Data Records`` - the fundamental unit in DataFed\n", + "\n", + "## Setting up:\n", + "Just as in the previous notebook, we start be instantiating the ``datafed.CommandLib.API`` class to communicate with DataFed:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from datafed.CommandLib import API" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "\n", + "df_api = API()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Specifying context:\n", + "Since we want to work within the ``context`` of the Training Project:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api.setContext(\"p/trn001\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To begin with, you will be working within your own private collection whose ``alias`` is the same as your DataFed username.\n", + "\n", + "### Exercise: \n", + " Enter your username into the ``parent_collection`` variable " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "parent_collection = \"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating Data Records:\n", + "Data Records can hold a whole lot of contextual information about the raw data in them. One key component is the scientific metadata. Ideally, we would get this metadata from the headers of the raw data file or some other log file that was generated along with the raw data. \n", + "\n", + "### Note \n", + "> DataFed expects scientific metadata to be specified **like** a python dictionary. \n", + "\n", + "For now, let's set up some dummy metadata:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "parameters = {\n", + " \"a\": 4,\n", + " \"b\": [1, 2, -4, 7.123],\n", + " \"c\": \"Something important\",\n", + " \"d\": {\"x\": 14, \"y\": -19}, # Can use nested dictionaries\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Note \n", + "> DataFed **currently** encodes metadata in JSON strings. The next version will accept python dictonaries as is.\n", + "\n", + "For now, we will need to convert the metadata to a JSON string using the ``dumps()`` function in the ``json`` package" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "json.dumps(parameters)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We use the `dataCreate()` function to make our new record, and the `json.dumps()` function to format the python dictionary to JSON:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# parent_collection The parent collection, whose alias is your username\n", + "dc_resp = df_api.dataCreate(\n", + " \"my important data\",\n", + " metadata=json.dumps(parameters),\n", + " parent_id=parent_collection,\n", + ")\n", + "dc_resp" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### **Note:** \n", + "> In the future, the ``dataCreate()`` function would by default return only the ``ID`` of the record instead of such a verbose response if it successfully created the Data Record. We expect to be able to continue to get this verbose response through an optional argument. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise: \n", + " Extract the ``ID`` of the data record from the message returned from ``dataCreate()`` for future use: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "record_id = dc_resp[0].data[0].id\n", + "print(record_id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Data Records and the information in them are not static and can always be modified at any time\n", + "## Updating Data Records\n", + "Let's add some additional metadata and change the title of our record:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "metadata = {\"appended_metadata\": True}\n", + "du_resp = df_api.dataUpdate(\n", + " record_id,\n", + " title=\"Some new title for the data\",\n", + " metadata=json.dumps(metadata),\n", + ")\n", + "print(du_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### **Note:** \n", + "> In the future, the dataUpdate() command would return only an acknowledgement of the successful execution of the data update. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Viewing Data Records\n", + "We can get full information about a data record including the complete metadata via the ``dataView()`` function. Let us use this function to verify that the changes have been incorporated:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dv_resp = df_api.dataView(record_id)\n", + "print(dv_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### **Note:** \n", + "> Record metadata is always stored as a JSON string. \n", + "\n", + "### Exercise: \n", + " Try isolating the updated metadata and converting it to a python dictionary. \n", + "\n", + "Hint - ``json.loads()`` is the opposite of ``json.dumps()``" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "metadata = json.loads(dv_resp[0].data[0].metadata)\n", + "print(metadata)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the first update, we **merged** new metadata with the existing metadata within the record. However ``dataUpdate()`` is also capable of replacing the metadata as well.\n", + "\n", + "### Exercise: \n", + " Now try to **replace** the metadata.

Hint: look at the `metadata_set` keyword argument in the docstrings.
\n", + "\n", + "### Tip: \n", + "> With the cursor just past the starting parenthesis of ``dataUpdate(``, simultaneously press the ``Shift`` and ``Tab`` keys once, twice, or four times to view more of the documentation about the function. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "new_metadata = {\"key\": \"value\", \"E\": \"mc^2\"}\n", + "du_resp = df_api.dataUpdate(record_id, metadata=json.dumps(new_metadata), metadata_set=True)\n", + "dv_resp = df_api.dataView(record_id)\n", + "print(json.loads(dv_resp[0].data[0].metadata))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Provenance\n", + "Along with in-depth, detailed scientific metadata describing each data record, DataFed also provides a very handy tool for tracking data provenance, i.e. recording the relationships between Data Records which can be used to track the history, lineage, and origins of a data object. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise: \n", + " Create a new record meant to hold some processed version of the first data record.
**Caution**: Make sure to create it in the correct Collection.
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "new_params = {\"hello\": \"world\", \"counting\": [1, 2, 3, 4]}\n", + "\n", + "dc2_resp = df_api.dataCreate(\n", + " \"Subsequent Record\",\n", + " metadata=json.dumps(new_params),\n", + " parent_id=parent_collection,\n", + ")\n", + "\n", + "clean_rec_id = dc2_resp[0].data[0].id\n", + "print(clean_rec_id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Specifying Relationships\n", + "Now that we have two records, we can specify the second record's relationship to the first by adding a **dependency** via the ``deps_add`` keyword argument of the ``dataUpdate()`` function.\n", + "\n", + "### Note: \n", + "> As the documentation for ``dataUpdate()`` will reveal, dependencies must be specified as a ``list`` of relationships. Each relationship is expressed as a ``list`` where the first item is a dependency type (a string) and the second is the data record (also a string). \n", + "\n", + "DataFed currently supports three relationship types:\n", + "* `der` - Is derived from\n", + "* `comp` - Is comprised of\n", + "* `ver` - Is new version of" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dep_resp = df_api.dataUpdate(clean_rec_id, deps_add=[[\"der\", record_id]])\n", + "print(dep_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise: \n", + " Take a look at the records on the DataFed Web Portal in order to see a graphical representation of the data provenance. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise: \n", + "1. Create a new data record to hold a figure in your journal article.
2. Extract the record ID.
3. Now establish a provenance link between this figure record and the processed data record we just created. You may try out a different dependency type if you like.
4. Take a look at the DataFed web portal to see the update to the Provenance of the records
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# 1\n", + "reply = df_api.dataCreate(\"Figure 1\", parent_id=parent_collection)\n", + "# 2\n", + "fig_id = reply[0].data[0].id\n", + "# 3\n", + "provenance_link = df_api.dataUpdate(fig_id, deps_add=[(\"comp\", clean_rec_id)])\n", + "print(provenance_link[0].data[0])" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.9" + } + }, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/jupyter_notebooks/3_Data_Transfer.ipynb b/jupyter_notebooks/3_Data_Transfer.ipynb index bacc83551..0a0c13fff 100644 --- a/jupyter_notebooks/3_Data_Transfer.ipynb +++ b/jupyter_notebooks/3_Data_Transfer.ipynb @@ -1,488 +1,520 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# 3. Transferring Data in DataFed\n", - "In this notebook, we will be going over uploading to & downloading from Data Records and monitoring data transfer tasks.\n", - "\n", - "## Before we begin:\n", - "Import necessary libraries", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "import os\n", - "import time\n", - "from datafed.CommandLib import API", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Instantiate the DataFed API and set ``context`` to the Training project:" - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api = API()\n", "df_api.setContext('p/trn001')"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' Enter your username to work within your personal Collection. ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["parent_collection = # your username here"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' Copy over the ID for the record you created in the previous notebook. ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["record_id = ?"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Uploading raw data\n", - "Shortly, we will learn how to upload data to the record we just created. For demonstration purposes, we will just create a simple text file and use this as the raw data for the Data Record\n", - "\n", - '### **Note:** \n', - '> DataFed does not impose any restrictions on the file extension / format for the raw data ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "with open('./raw_data.txt', mode='w') as file_handle:\n", - " file_handle.write('This is some data')", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Note \n', - '> Always ensure that your Globus endpoint is active and that your files are located in a directory that is visible to the Globus Endpoint ', - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## `dataPut()`\n", - "Uploading data files to DataFed is done using the `dataPut` command.", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "put_resp = df_api.dataPut(record_id,\n", - " './raw_data.txt',\n", - " wait=True, # Waits until transfer completes.\n", - " )\n", - "print(put_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We get two components in the response:\n", - "* Information about the Data Record, data was uploaded to\n", - "* Information about the data transfer ``task`` - more on this later\n", - "\n", - "The ``dataPut()`` method **initiates a Globus transfer** on our behalf from the machine **wherever** the file was present to wherever the default data repository is located. In this case, the file was in our local file system and on the same machine where we are executing the command.\n", - "\n", - '### Note \n', - '> The above data file was specified by its relative local path, so DataFed used our pre-configured default Globus endpoint to find the data file. As long as we have the id for any *active* Globus endpoint that we have authenticated access to, we can transfer data from that endpoint with its full absolute file path – even if the file system is not attached ot the local machine. Look for more information on this in later examples. \n', - "\n", - "Let's view the data record now that we've uploaded our data. Pay attention to the ``ext`` and ``source`` fields which should now populated:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["dv_resp = df_api.dataView(record_id)\n", "print(dv_resp)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Downloading raw data\n", - "DataFed is also capable of getting data stored in a DataFed repository and placing it in the local or other Globus-visible filesystem via the ``dataGet()`` function. \n", - "\n", - "Let us download the content in the data record we have been working on so far for demonstration purposes\n", - "\n", - '### Note \n', - '> The current version of DataFed has a bug where ``dataGet()`` only accepts a list of Data Record or Collection IDs. Until the next version, users are recommended to put their singular ID into a list for ``dataGet().`` ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "get_resp = df_api.dataGet([record_id], # currently only accepts a list of IDs / aliases\n", - " '.', # directory where data should be downloaded\n", - " orig_fname=False, # do not name file by its original name\n", - " wait=True, # Wait until Globus transfer completes\n", - " )\n", - "print(get_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the response we only get back information about the data transfer ``task`` - more on this shortly\n", - "\n", - "The bug in ``dataGet()`` also reveals its capability to **download multiple data records or even Collections.**\n", - "\n", - "Let's confirm that the data has been downloaded successfully:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["os.listdir('.')"], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "expected_file_name = os.path.join('.', record_id.split('d/')[-1]) + '.json'\n", - "print('Does a file with this name: ' + expected_file_name + ' exist?')\n", - "print(os.path.exists(expected_file_name))", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Tasks\n", - "\n", - '### Note \n', - '> A DataFed task may itself contain / be responsible for several Globus file transfers, potentially from / to multiple locations. \n', - " \n", - "DataFed makes it possible to check on the status of transfer tasks in an easy and programmatic manner.\n", - "\n", - "Before we learn more about tasks, first lets try to get the ``id`` of the task in ``get_resp`` from the recent ``dataGet()`` function call:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["task_id = get_resp[0].task[0].id\n", "print(task_id)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Viewing Tasks\n", - "We can get more information about a given transfer via the `taskView()` function:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["task_resp = df_api.taskView(task_id)\n", "print(task_resp)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We get a new kind of message - a ``TaskDataReply``. \n", - "Key fields to keep an eye on:\n", - "* ``status``\n", - "* ``msg``\n", - "* ``source``\n", - "* ``dest``\n", - "\n", - "If we are interested in monitoring tasks, triggering activities or subsequent steps of workflows based on transfers, we would need to know how to get the ``status`` property from the ``TaskDataReply``: ", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["task_resp[0].task[0].status"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Even though the message above says `TS_SUCCEEDED`, we see that this task status codes to the integer `3`.\n", - "\n", - '### **Note:** \n', - '> Cheat sheet for interpreting task statuses:
``2``: in progress
``3``: complete
anything else - problem
\n', - "\n", - '### **Note:** \n', - '> A future version of DataFed may change the nature of the output / type for the status property. In general, the exact return object types and nomenclature may evolve with DataFed. ', - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Listing Tasks\n", - "We can request a listing of all our recently initiated tasks:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api.taskList()"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The output of this listing would be very helpful for the Exercise below" - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Example scenario - Simulations\n", - "Let's say that we want to run a series of simulations where one or more parameters are varied and each simulation is run with a unique set of parameters. Let's also assume that our eventual goal is to build a surrogate model for the computationally expensive simulation using machine learning. So, we **want to capture the metadata and data associated with the series of simulations** to train the machine learning model later on. \n", - "\n", - "We have set up skeleton functions and code snippets to help you mimic the data management for such a simulation. We would like you to take what you have learnt so far and fill in the blanks\n", - "
\n", - "\n", - "\n", - "### Fake simulation\n", - 'Here, we have simulated a computationally "expensive" simulation that simply sleeps for a few seconds.', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def expensive_simulation():\n", - " time.sleep(5)\n", - " # Yes, this simulation is deterministic and always results in the same result:\n", - " path_to_results = 'sdss#public/uufs/chpc.utah.edu/common/home/sdss/dr10/apogee/spectro/data/55574/55574.md5sum'\n", - " # The simulation uses the same combination of parameters\n", - " metadata = {'a': 1, 'b': 2, 'c': 3.14}\n", - " return path_to_results, metadata", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' Define a function that:
1. creates a new Data Record with the provided metadata (as a dictionary) and other details,
2. extracts the record id,
3. puts the raw data into the record,
4. extracts and returns the task ID.

Feel free to print any messages that may help you track things.
\n', - "\n", - '### Note \n', - '> Pay attention to the ``wait`` keyword argument when putting the raw data into record ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def capture_data(simulation_index, # integer - counter to signify the Nth simulation in the series\n", - " metadata, # dictionary - combination of parameters used for this simulation\n", - " raw_data_path, # string - Path to the raw data file that needs to be put into the receord\n", - " parent_collection=parent_collection, # string - Collection to create this Data Record into\n", - " ):\n", - " # 1. Create a new Data Record with the metadata and use the simulation index to provide a unique title\n", - "\n", - " # 2. Extract the record ID from the response\n", - " \n", - " # 3. Put the raw data into this record:\n", - " \n", - " # 4. Extract the ID for the data transfer task\n", - "\n", - " # 5. Return the task ID", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' Try out this function to make sure it works. See what it does on the **DataFed web portal**. ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "capture_data(14, {'param_1': 456, 'param_2': 'Hello', 'param_3': [1, -2.34, 54]})" - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' We will want a simple function to monitor the status of all the data upload tasks. Define a function that accepts a list of task IDs and returns their status after looking them up on DataFed ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def check_xfer_status(task_ids):\n", - " # put singular task ID into a list\n", - " if isinstance(task_ids, str):\n", - " task_ids = [task_ids]\n", - " \n", - " # Create a list to hold the statuses of each of the tasks\n", - " \n", - " # Iterate over each of the task IDs\n", - " \n", - " # For each task ID, get detailed information about it\n", - " \n", - " # Extract the task status from the detailed information\n", - " \n", - " # Append this status to the list of statuses\n", - " \n", - " # Return the list of statuses", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' Try out your function using the IDs of the recent ``dataPut()`` and ``dataGet()`` functions. ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["check_xfer_status(...)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Run the series of simulations:\n", - "Use the three functions defined above to mimic the process of exploring a parameter space using simulations, where for each iteration, we:
1. run a simulation,
2. capture the data + metadata into DataFed,
3. monitor the data upload tasks.", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "xfer_tasks = list()\n", - "for ind in range(3):\n", - " print('Starting simulation #{}'.format(ind))\n", - " # Run the simulation.\n", - " path_to_results, metadata = expensive_simulation()\n", - " # Capture the data and metadata into DataFed\n", - " task_id = capture_data(ind, metadata, path_to_results)\n", - " # Append the task ID for this data upload into xfer_tasks\n", - " xfer_tasks.append(task_id)\n", - " # Print out the status of the data transfers\n", - " print('Transfer status(es): {}'.format(check_xfer_status(xfer_tasks)))\n", - " print('')\n", - "\n", - "print('Simulations complete')\n", - "time.wait(10)\n", - "print('Transfer status(es): {}'.format(check_xfer_status(xfer_tasks)))", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' What happens if you set the ``wait`` in ``dataPut()`` to ``True``? \n', - "\n", - '### **Note:** \n', - '> Users are recommended to perform data orchestration (especially large data movement - upload / download) operations outside the scope of heavy / parallel computation operations in order to avoid wasting precious wall time on compute clusters.', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [], - }, - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python [default]", - "language": "python", - "name": "python3", - }, - "language_info": { - "codemirror_mode": {"name": "ipython", "version": 3}, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.5", - }, - }, - "nbformat": 4, - "nbformat_minor": 4, + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 3. Transferring Data in DataFed\n", + "In this notebook, we will be going over uploading to & downloading from Data Records and monitoring data transfer tasks.\n", + "\n", + "## Before we begin:\n", + "Import necessary libraries" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import time\n", + "from datafed.CommandLib import API" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Instantiate the DataFed API and set ``context`` to the Training project:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api = API()\n", + "df_api.setContext(\"p/trn001\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " Enter your username to work within your personal Collection. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "parent_collection = # your username here" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " Copy over the ID for the record you created in the previous notebook. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "record_id = ?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Uploading raw data\n", + "Shortly, we will learn how to upload data to the record we just created. For demonstration purposes, we will just create a simple text file and use this as the raw data for the Data Record\n", + "\n", + "### **Note:** \n", + "> DataFed does not impose any restrictions on the file extension / format for the raw data " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with open(\"./raw_data.txt\", mode=\"w\") as file_handle:\n", + " file_handle.write(\"This is some data\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Note \n", + "> Always ensure that your Globus endpoint is active and that your files are located in a directory that is visible to the Globus Endpoint " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## `dataPut()`\n", + "Uploading data files to DataFed is done using the `dataPut` command." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "put_resp = df_api.dataPut(\n", + " record_id,\n", + " \"./raw_data.txt\",\n", + " wait=True, # Waits until transfer completes.\n", + ")\n", + "print(put_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We get two components in the response:\n", + "* Information about the Data Record, data was uploaded to\n", + "* Information about the data transfer ``task`` - more on this later\n", + "\n", + "The ``dataPut()`` method **initiates a Globus transfer** on our behalf from the machine **wherever** the file was present to wherever the default data repository is located. In this case, the file was in our local file system and on the same machine where we are executing the command.\n", + "\n", + "### Note \n", + "> The above data file was specified by its relative local path, so DataFed used our pre-configured default Globus endpoint to find the data file. As long as we have the id for any *active* Globus endpoint that we have authenticated access to, we can transfer data from that endpoint with its full absolute file path – even if the file system is not attached ot the local machine. Look for more information on this in later examples. \n", + "\n", + "Let's view the data record now that we've uploaded our data. Pay attention to the ``ext`` and ``source`` fields which should now populated:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dv_resp = df_api.dataView(record_id)\n", + "print(dv_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Downloading raw data\n", + "DataFed is also capable of getting data stored in a DataFed repository and placing it in the local or other Globus-visible filesystem via the ``dataGet()`` function. \n", + "\n", + "Let us download the content in the data record we have been working on so far for demonstration purposes\n", + "\n", + "### Note \n", + "> The current version of DataFed has a bug where ``dataGet()`` only accepts a list of Data Record or Collection IDs. Until the next version, users are recommended to put their singular ID into a list for ``dataGet().`` " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "get_resp = df_api.dataGet(\n", + " [record_id], # currently only accepts a list of IDs / aliases\n", + " \".\", # directory where data should be downloaded\n", + " orig_fname=False, # do not name file by its original name\n", + " wait=True, # Wait until Globus transfer completes\n", + ")\n", + "print(get_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the response we only get back information about the data transfer ``task`` - more on this shortly\n", + "\n", + "The bug in ``dataGet()`` also reveals its capability to **download multiple data records or even Collections.**\n", + "\n", + "Let's confirm that the data has been downloaded successfully:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "os.listdir(\".\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "expected_file_name = os.path.join(\".\", record_id.split(\"d/\")[-1]) + \".json\"\n", + "print(\"Does a file with this name: \" + expected_file_name + \" exist?\")\n", + "print(os.path.exists(expected_file_name))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Tasks\n", + "\n", + "### Note \n", + "> A DataFed task may itself contain / be responsible for several Globus file transfers, potentially from / to multiple locations. \n", + " \n", + "DataFed makes it possible to check on the status of transfer tasks in an easy and programmatic manner.\n", + "\n", + "Before we learn more about tasks, first lets try to get the ``id`` of the task in ``get_resp`` from the recent ``dataGet()`` function call:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "task_id = get_resp[0].task[0].id\n", + "print(task_id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Viewing Tasks\n", + "We can get more information about a given transfer via the `taskView()` function:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "task_resp = df_api.taskView(task_id)\n", + "print(task_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We get a new kind of message - a ``TaskDataReply``. \n", + "Key fields to keep an eye on:\n", + "* ``status``\n", + "* ``msg``\n", + "* ``source``\n", + "* ``dest``\n", + "\n", + "If we are interested in monitoring tasks, triggering activities or subsequent steps of workflows based on transfers, we would need to know how to get the ``status`` property from the ``TaskDataReply``: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "task_resp[0].task[0].status" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Even though the message above says `TS_SUCCEEDED`, we see that this task status codes to the integer `3`.\n", + "\n", + "### **Note:** \n", + "> Cheat sheet for interpreting task statuses:
``2``: in progress
``3``: complete
anything else - problem
\n", + "\n", + "### **Note:** \n", + "> A future version of DataFed may change the nature of the output / type for the status property. In general, the exact return object types and nomenclature may evolve with DataFed. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Listing Tasks\n", + "We can request a listing of all our recently initiated tasks:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api.taskList()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The output of this listing would be very helpful for the Exercise below" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Example scenario - Simulations\n", + "Let's say that we want to run a series of simulations where one or more parameters are varied and each simulation is run with a unique set of parameters. Let's also assume that our eventual goal is to build a surrogate model for the computationally expensive simulation using machine learning. So, we **want to capture the metadata and data associated with the series of simulations** to train the machine learning model later on. \n", + "\n", + "We have set up skeleton functions and code snippets to help you mimic the data management for such a simulation. We would like you to take what you have learnt so far and fill in the blanks\n", + "
\n", + "\n", + "\n", + "### Fake simulation\n", + "Here, we have simulated a computationally \"expensive\" simulation that simply sleeps for a few seconds." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def expensive_simulation():\n", + " time.sleep(5)\n", + " # Yes, this simulation is deterministic and always results in the\n", + " # same result:\n", + " path_to_results = (\n", + " \"sdss#public/uufs/chpc.utah.edu/common/home/\"\n", + " \"sdss/dr10/apogee/spectro/data/55574/55574.md5sum\"\n", + " )\n", + " # The simulation uses the same combination of parameters\n", + " metadata = {\"a\": 1, \"b\": 2, \"c\": 3.14}\n", + " return path_to_results, metadata" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " Define a function that:
1. creates a new Data Record with the provided metadata (as a dictionary) and other details,
2. extracts the record id,
3. puts the raw data into the record,
4. extracts and returns the task ID.

Feel free to print any messages that may help you track things.
\n", + "\n", + "### Note \n", + "> Pay attention to the ``wait`` keyword argument when putting the raw data into record " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def capture_data(simulation_index, # integer - counter to signify the Nth simulation in the series\n", + " metadata, # dictionary - combination of parameters used for this simulation\n", + " raw_data_path, # string - Path to the raw data file that needs to be put into the receord\n", + " parent_collection=parent_collection, # string - Collection to create this Data Record into\n", + " ):\n", + " # 1. Create a new Data Record with the metadata and use the simulation index to provide a unique title\n", + "\n", + " # 2. Extract the record ID from the response\n", + " \n", + " # 3. Put the raw data into this record:\n", + " \n", + " # 4. Extract the ID for the data transfer task\n", + "\n", + " # 5. Return the task ID" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " Try out this function to make sure it works. See what it does on the **DataFed web portal**. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "capture_data(14, {\"param_1\": 456, \"param_2\": \"Hello\", \"param_3\": [1, -2.34, 54]})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " We will want a simple function to monitor the status of all the data upload tasks. Define a function that accepts a list of task IDs and returns their status after looking them up on DataFed " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def check_xfer_status(task_ids):\n", + " # put singular task ID into a list\n", + " if isinstance(task_ids, str):\n", + " task_ids = [task_ids]\n", + "\n", + " # Create a list to hold the statuses of each of the tasks\n", + "\n", + " # Iterate over each of the task IDs\n", + "\n", + " # For each task ID, get detailed information about it\n", + "\n", + " # Extract the task status from the detailed information\n", + "\n", + " # Append this status to the list of statuses\n", + "\n", + " # Return the list of statuses" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " Try out your function using the IDs of the recent ``dataPut()`` and ``dataGet()`` functions. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "check_xfer_status(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Run the series of simulations:\n", + "Use the three functions defined above to mimic the process of exploring a parameter space using simulations, where for each iteration, we:
1. run a simulation,
2. capture the data + metadata into DataFed,
3. monitor the data upload tasks." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "xfer_tasks = list()\n", + "for ind in range(3):\n", + " print(\"Starting simulation #{}\".format(ind))\n", + " # Run the simulation.\n", + " path_to_results, metadata = expensive_simulation()\n", + " # Capture the data and metadata into DataFed\n", + " task_id = capture_data(ind, metadata, path_to_results)\n", + " # Append the task ID for this data upload into xfer_tasks\n", + " xfer_tasks.append(task_id)\n", + " # Print out the status of the data transfers\n", + " print(\"Transfer status(es): {}\".format(check_xfer_status(xfer_tasks)))\n", + " print(\"\")\n", + "\n", + "print(\"Simulations complete\")\n", + "time.wait(10)\n", + "print(\"Transfer status(es): {}\".format(check_xfer_status(xfer_tasks)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " What happens if you set the ``wait`` in ``dataPut()`` to ``True``? \n", + "\n", + "### **Note:** \n", + "> Users are recommended to perform data orchestration (especially large data movement - upload / download) operations outside the scope of heavy / parallel computation operations in order to avoid wasting precious wall time on compute clusters." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/jupyter_notebooks/3_Data_Transfer_with_Solutions.ipynb b/jupyter_notebooks/3_Data_Transfer_with_Solutions.ipynb index 54afa6e67..237737376 100755 --- a/jupyter_notebooks/3_Data_Transfer_with_Solutions.ipynb +++ b/jupyter_notebooks/3_Data_Transfer_with_Solutions.ipynb @@ -1,548 +1,602 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# 3. Transferring Data in DataFed\n", - "In this notebook, we will be going over uploading to & downloading from Data Records and monitoring data transfer tasks.\n", - "\n", - "## Before we begin:\n", - "Import necessary libraries", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "import os\n", - "import time\n", - "from datafed.CommandLib import API", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Instantiate the DataFed API and set ``context`` to the Training project:" - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api = API()\n", "df_api.setContext('p/trn001')"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' Enter your username to work within your personal Collection. ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ['parent_collection = "c/34558900" # your username here'], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' Copy over the ID for the record you created in the previous notebook. ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ['record_id = "d/43650517"'], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Uploading raw data\n", - "Shortly, we will learn how to upload data to the record we just created. For demonstration purposes, we will just create a simple text file and use this as the raw data for the Data Record\n", - "\n", - '### **Note:** \n', - '> DataFed does not impose any restrictions on the file extension / format for the raw data ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "with open('./raw_data.txt', mode='w') as file_handle:\n", - " file_handle.write('This is some data')", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Note \n', - '> Always ensure that your Globus endpoint is active and that your files are located in a directory that is visible to the Globus Endpoint ', - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## `dataPut()`\n", - "Uploading data files to DataFed is done using the `dataPut` command.", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "put_resp = df_api.dataPut(record_id,\n", - " './raw_data.txt',\n", - " wait=True, # Waits until transfer completes.\n", - " )\n", - "print(put_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We get two components in the response:\n", - "* Information about the Data Record, data was uploaded to\n", - "* Information about the data transfer ``task`` - more on this later\n", - "\n", - "The ``dataPut()`` method **initiates a Globus transfer** on our behalf from the machine **wherever** the file was present to wherever the default data repository is located. In this case, the file was in our local file system and on the same machine where we are executing the command.\n", - "\n", - '### Note \n', - '> The above data file was specified by its relative local path, so DataFed used our pre-configured default Globus endpoint to find the data file. As long as we have the id for any *active* Globus endpoint that we have authenticated access to, we can transfer data from that endpoint with its full absolute file path – even if the file system is not attached ot the local machine. Look for more information on this in later examples. \n', - "\n", - "Let's view the data record now that we've uploaded our data. Pay attention to the ``ext`` and ``source`` fields which should now populated:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["dv_resp = df_api.dataView(record_id)\n", "print(dv_resp)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Downloading raw data\n", - "DataFed is also capable of getting data stored in a DataFed repository and placing it in the local or other Globus-visible filesystem via the ``dataGet()`` function. \n", - "\n", - "Let us download the content in the data record we have been working on so far for demonstration purposes", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "get_resp = df_api.dataGet(record_id,\n", - " '.', # directory where data should be downloaded\n", - " orig_fname=False, # do not name file by its original name\n", - " wait=True, # Wait until Globus transfer completes\n", - " )\n", - "print(get_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the response we only get back information about the data transfer ``task`` - more on this shortly\n", - "\n", - "The bug in ``dataGet()`` also reveals its capability to **download multiple data records or even Collections.**\n", - "\n", - "Let's confirm that the data has been downloaded successfully:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["os.listdir('.')"], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "expected_file_name = os.path.join('.', record_id.split('d/')[-1]) + '.txt'\n", - "print('Does a file with this name: ' + expected_file_name + ' exist?')\n", - "print(os.path.exists(expected_file_name))", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Tasks\n", - "\n", - '### Note \n', - '> A DataFed task may itself contain / be responsible for several Globus file transfers, potentially from / to multiple locations. \n', - " \n", - "DataFed makes it possible to check on the status of transfer tasks in an easy and programmatic manner.\n", - "\n", - "Before we learn more about tasks, first lets try to get the ``id`` of the task in ``get_resp`` from the recent ``dataGet()`` function call:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["task_id = get_resp[0].task[0].id\n", "print(task_id)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Viewing Tasks\n", - "We can get more information about a given transfer via the `taskView()` function:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["task_resp = df_api.taskView(task_id)\n", "print(task_resp)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We get a new kind of message - a ``TaskDataReply``. \n", - "Key fields to keep an eye on:\n", - "* ``status``\n", - "* ``msg``\n", - "* ``source``\n", - "* ``dest``\n", - "\n", - "If we are interested in monitoring tasks, triggering activities or subsequent steps of workflows based on transfers, we would need to know how to get the ``status`` property from the ``TaskDataReply``: ", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["task_resp[0].task[0].status"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Even though the message above says `TS_SUCCEEDED`, we see that this task status codes to the integer `3`.\n", - "\n", - '### **Note:** \n', - '> Cheat sheet for interpreting task statuses:
``2``: in progress
``3``: complete
anything else - problem
\n', - "\n", - '### **Note:** \n', - '> A future version of DataFed may change the nature of the output / type for the status property. In general, the exact return object types and nomenclature may evolve with DataFed. ', - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Listing Tasks\n", - "We can request a listing of all our recently initiated tasks:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {"scrolled": true}, - "outputs": [], - "source": ["df_api.taskList()"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The output of this listing would be very helpful for the Exercise below" - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Example scenario - Simulations\n", - "Let's say that we want to run a series of simulations where one or more parameters are varied and each simulation is run with a unique set of parameters. Let's also assume that our eventual goal is to build a surrogate model for the computationally expensive simulation using machine learning. So, we **want to capture the metadata and data associated with the series of simulations** to train the machine learning model later on. \n", - "\n", - "We have set up skeleton functions and code snippets to help you mimic the data management for such a simulation. We would like you to take what you have learnt so far and fill in the blanks\n", - "
\n", - "\n", - "\n", - "### Fake simulation\n", - 'Here, we have simulated a computationally "expensive" simulation that simply sleeps for a few seconds.', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def expensive_simulation():\n", - " time.sleep(5)\n", - " # Yes, this simulation is deterministic and always results in the same result:\n", - " path_to_results = 'sdss#public/uufs/chpc.utah.edu/common/home/sdss/dr10/apogee/spectro/data/55574/55574.md5sum'\n", - " # The simulation uses the same combination of parameters\n", - " metadata = {'a': 1, 'b': 2, 'c': 3.14}\n", - " return path_to_results, metadata", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' Define a function that:
1. creates a new Data Record with the provided metadata (as a dictionary) and other details,
2. extracts the record id,
3. puts the raw data into the record,
4. extracts and returns the task ID.

Feel free to print any messages that may help you track things.
\n', - "\n", - '### Note \n', - '> Pay attention to the ``wait`` keyword argument when putting the raw data into record ', - ], - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "def capture_data(simulation_index, # integer - counter to signify the Nth simulation in the series\n", - " metadata, # dictionary - combination of parameters used for this simulation\n", - " raw_data_path, # string - Path to the raw data file that needs to be put into the receord\n", - " parent_collection=parent_collection, # string - Collection to create this Data Record into\n", - " ):\n", - " \n", - " # 1. Create a new Data Record with the metadata and use the simulation index to provide a unique title\n", - " rec_resp = df_api.dataCreate('Simulation_' + str(simulation_index),\n", - " metadata=json.dumps(metadata),\n", - " parent_id=parent_collection)\n", - " \n", - " # 2. Extract the record ID from the response\n", - " this_rec_id = rec_resp[0].data[0].id\n", - " \n", - " # 3. Put the raw data into this record:\n", - " put_resp = df_api.dataPut(this_rec_id, raw_data_path, wait=False)\n", - " \n", - " # 4. Extract the ID for the data transfer task\n", - " task_id = put_resp[0].task.id\n", - " \n", - " # 5. Return the task ID\n", - " return task_id", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' Try out this function to make sure it works. See what it does on the **DataFed web portal**. ', - ], - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": {"text/plain": ["'task/45433451'"]}, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result", - } - ], - "source": [ - "path_to_results, metadata = expensive_simulation()\n", - "\n", - "task_id = capture_data(14, metadata, path_to_results)\n", - "task_id", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' We will want a simple function to monitor the status of all the data upload tasks. Define a function that accepts a list of task IDs and returns their status after looking them up on DataFed ', - ], - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [], - "source": [ - "def check_xfer_status(task_ids):\n", - " \n", - " # put singular task ID into a list\n", - " if isinstance(task_ids, str):\n", - " task_ids = [task_ids]\n", - " \n", - " # Create a list to hold the statuses of each of the tasks\n", - " statuses = list()\n", - " \n", - " # Iterate over each of the task IDs\n", - " for this_task_id in task_ids:\n", - " \n", - " # For each task ID, get detailed information about it\n", - " task_resp = df_api.taskView(this_task_id)\n", - " \n", - " # Extract the task status from the detailed information\n", - " this_status = task_resp[0].task[0].status\n", - " \n", - " # Append this status to the list of statuses\n", - " statuses.append(this_status)\n", - " \n", - " # Return the list of statuses\n", - " return statuses", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' Try out your function using the IDs of the recent ``dataPut()`` and ``dataGet()`` functions. ', - ], - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": {"text/plain": ["[3]"]}, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result", - } - ], - "source": ["check_xfer_status(task_id)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Run the series of simulations:\n", - "Use the three functions defined above to mimic the process of exploring a parameter space using simulations, where for each iteration, we:
1. run a simulation,
2. capture the data + metadata into DataFed,
3. monitor the data upload tasks.", - ], - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Starting simulation #0\n", - "Transfer status(es): [2]\n", - "\n", - "Starting simulation #1\n", - "Transfer status(es): [2, 2]\n", - "\n", - "Starting simulation #2\n", - "Transfer status(es): [3, 2, 2]\n", - "\n", - "Simulations complete! Waiting for uploads to complete\n", - "\n", - "Transfer status(es): [3, 3, 2]\n", - "Transfer status(es): [3, 3, 2]\n", - "Transfer status(es): [3, 3, 2]\n", - "Transfer status(es): [3, 3, 2]\n", - "Transfer status(es): [3, 3, 3]\n", - "\n", - "Finished uploading all data!\n", - ], - } - ], - "source": [ - "xfer_tasks = list()\n", - "for ind in range(3):\n", - " print('Starting simulation #{}'.format(ind))\n", - " # Run the simulation.\n", - " path_to_results, metadata = expensive_simulation()\n", - " # Capture the data and metadata into DataFed\n", - " task_id = capture_data(ind, metadata, path_to_results)\n", - " # Append the task ID for this data upload into xfer_tasks\n", - " xfer_tasks.append(task_id)\n", - " # Print out the status of the data transfers\n", - " print('Transfer status(es): {}'.format(check_xfer_status(xfer_tasks)))\n", - " print('')\n", - "\n", - "print('Simulations complete! Waiting for uploads to complete\\n')\n", - "\n", - "while True:\n", - " time.sleep(1)\n", - " statuses = check_xfer_status(xfer_tasks)\n", - " print('Transfer status(es): {}'.format(statuses))\n", - " if all([this == 3 for this in statuses]): break\n", - " \n", - "print('\\nFinished uploading all data!')", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' What happens if you set the ``wait`` in ``dataPut()`` to ``True``? \n', - "\n", - '### **Note:** \n', - '> Users are recommended to perform data orchestration (especially large data movement - upload / download) operations outside the scope of heavy / parallel computation operations in order to avoid wasting precious wall time on compute clusters.', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [], - }, - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3", - }, - "language_info": { - "codemirror_mode": {"name": "ipython", "version": 3}, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.3", - }, - }, - "nbformat": 4, - "nbformat_minor": 4, + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 3. Transferring Data in DataFed\n", + "In this notebook, we will be going over uploading to & downloading from Data Records and monitoring data transfer tasks.\n", + "\n", + "## Before we begin:\n", + "Import necessary libraries" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "import os\n", + "import time\n", + "from datafed.CommandLib import API" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Instantiate the DataFed API and set ``context`` to the Training project:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api = API()\n", + "df_api.setContext(\"p/trn001\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " Enter your username to work within your personal Collection. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "parent_collection = \"c/34558900\" # your username here" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " Copy over the ID for the record you created in the previous notebook. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "record_id = \"d/43650517\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Uploading raw data\n", + "Shortly, we will learn how to upload data to the record we just created. For demonstration purposes, we will just create a simple text file and use this as the raw data for the Data Record\n", + "\n", + "### **Note:** \n", + "> DataFed does not impose any restrictions on the file extension / format for the raw data " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with open(\"./raw_data.txt\", mode=\"w\") as file_handle:\n", + " file_handle.write(\"This is some data\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Note \n", + "> Always ensure that your Globus endpoint is active and that your files are located in a directory that is visible to the Globus Endpoint " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## `dataPut()`\n", + "Uploading data files to DataFed is done using the `dataPut` command." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "put_resp = df_api.dataPut(\n", + " record_id,\n", + " \"./raw_data.txt\",\n", + " wait=True, # Waits until transfer completes.\n", + ")\n", + "print(put_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We get two components in the response:\n", + "* Information about the Data Record, data was uploaded to\n", + "* Information about the data transfer ``task`` - more on this later\n", + "\n", + "The ``dataPut()`` method **initiates a Globus transfer** on our behalf from the machine **wherever** the file was present to wherever the default data repository is located. In this case, the file was in our local file system and on the same machine where we are executing the command.\n", + "\n", + "### Note \n", + "> The above data file was specified by its relative local path, so DataFed used our pre-configured default Globus endpoint to find the data file. As long as we have the id for any *active* Globus endpoint that we have authenticated access to, we can transfer data from that endpoint with its full absolute file path – even if the file system is not attached ot the local machine. Look for more information on this in later examples. \n", + "\n", + "Let's view the data record now that we've uploaded our data. Pay attention to the ``ext`` and ``source`` fields which should now populated:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dv_resp = df_api.dataView(record_id)\n", + "print(dv_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Downloading raw data\n", + "DataFed is also capable of getting data stored in a DataFed repository and placing it in the local or other Globus-visible filesystem via the ``dataGet()`` function. \n", + "\n", + "Let us download the content in the data record we have been working on so far for demonstration purposes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "get_resp = df_api.dataGet(\n", + " record_id,\n", + " \".\", # directory where data should be downloaded\n", + " orig_fname=False, # do not name file by its original name\n", + " wait=True, # Wait until Globus transfer completes\n", + ")\n", + "print(get_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the response we only get back information about the data transfer ``task`` - more on this shortly\n", + "\n", + "The bug in ``dataGet()`` also reveals its capability to **download multiple data records or even Collections.**\n", + "\n", + "Let's confirm that the data has been downloaded successfully:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "os.listdir(\".\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "expected_file_name = os.path.join(\".\", record_id.split(\"d/\")[-1]) + \".txt\"\n", + "print(\"Does a file with this name: \" f\"{expected_file_name} exist?\")\n", + "print(os.path.exists(expected_file_name))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Tasks\n", + "\n", + "### Note \n", + "> A DataFed task may itself contain / be responsible for several Globus file transfers, potentially from / to multiple locations. \n", + " \n", + "DataFed makes it possible to check on the status of transfer tasks in an easy and programmatic manner.\n", + "\n", + "Before we learn more about tasks, first lets try to get the ``id`` of the task in ``get_resp`` from the recent ``dataGet()`` function call:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "task_id = get_resp[0].task[0].id\n", + "print(task_id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Viewing Tasks\n", + "We can get more information about a given transfer via the `taskView()` function:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "task_resp = df_api.taskView(task_id)\n", + "print(task_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We get a new kind of message - a ``TaskDataReply``. \n", + "Key fields to keep an eye on:\n", + "* ``status``\n", + "* ``msg``\n", + "* ``source``\n", + "* ``dest``\n", + "\n", + "If we are interested in monitoring tasks, triggering activities or subsequent steps of workflows based on transfers, we would need to know how to get the ``status`` property from the ``TaskDataReply``: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "task_resp[0].task[0].status" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Even though the message above says `TS_SUCCEEDED`, we see that this task status codes to the integer `3`.\n", + "\n", + "### **Note:** \n", + "> Cheat sheet for interpreting task statuses:
``2``: in progress
``3``: complete
anything else - problem
\n", + "\n", + "### **Note:** \n", + "> A future version of DataFed may change the nature of the output / type for the status property. In general, the exact return object types and nomenclature may evolve with DataFed. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Listing Tasks\n", + "We can request a listing of all our recently initiated tasks:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "df_api.taskList()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The output of this listing would be very helpful for the Exercise below" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Example scenario - Simulations\n", + "Let's say that we want to run a series of simulations where one or more parameters are varied and each simulation is run with a unique set of parameters. Let's also assume that our eventual goal is to build a surrogate model for the computationally expensive simulation using machine learning. So, we **want to capture the metadata and data associated with the series of simulations** to train the machine learning model later on. \n", + "\n", + "We have set up skeleton functions and code snippets to help you mimic the data management for such a simulation. We would like you to take what you have learnt so far and fill in the blanks\n", + "
\n", + "\n", + "\n", + "### Fake simulation\n", + "Here, we have simulated a computationally \"expensive\" simulation that simply sleeps for a few seconds." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def expensive_simulation():\n", + " time.sleep(5)\n", + " # Yes, this simulation is deterministic and always\n", + " # results in the same result:\n", + " path_to_results = \"sdss#public/uufs/chpc.utah.edu/common/home/\n", + "sdss/dr10/apogee/spectro/data/55574/55574.md5sum\"\n", + " # The simulation uses the same combination of parameters\n", + " metadata = {\"a\": 1, \"b\": 2, \"c\": 3.14}\n", + " return path_to_results, metadata" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " Define a function that:
1. creates a new Data Record with the provided metadata (as a dictionary) and other details,
2. extracts the record id,
3. puts the raw data into the record,
4. extracts and returns the task ID.

Feel free to print any messages that may help you track things.
\n", + "\n", + "### Note \n", + "> Pay attention to the ``wait`` keyword argument when putting the raw data into record " + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "# simulation_index (integer) - counter to signify the Nth simulation in\n", + "# the series\n", + "# metadata (dictionary) - combination of parameters used for this\n", + "# simulation\n", + "# raw_data_path (string) - Path to the raw data file that needs to\n", + "# be put into the receord\n", + "# parent_collection (string) - Collection to create this Data Record\n", + "# into\n", + "def capture_data(\n", + " simulation_index,\n", + " metadata,\n", + " raw_data_path,\n", + " parent_collection=parent_collection,\n", + "):\n", + "\n", + " # 1. Create a new Data Record with the metadata and use the\n", + " # simulation index to provide a unique title\n", + " rec_resp = df_api.dataCreate(\n", + " \"Simulation_\" + str(simulation_index),\n", + " metadata=json.dumps(metadata),\n", + " parent_id=parent_collection,\n", + " )\n", + "\n", + " # 2. Extract the record ID from the response\n", + " this_rec_id = rec_resp[0].data[0].id\n", + "\n", + " # 3. Put the raw data into this record:\n", + " put_resp = df_api.dataPut(this_rec_id, raw_data_path, wait=False)\n", + "\n", + " # 4. Extract the ID for the data transfer task\n", + " task_id = put_resp[0].task.id\n", + "\n", + " # 5. Return the task ID\n", + " return task_id" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " Try out this function to make sure it works. See what it does on the **DataFed web portal**. " + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'task/45433451'" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "path_to_results, metadata = expensive_simulation()\n", + "\n", + "task_id = capture_data(14, metadata, path_to_results)\n", + "task_id" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " We will want a simple function to monitor the status of all the data upload tasks. Define a function that accepts a list of task IDs and returns their status after looking them up on DataFed " + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "def check_xfer_status(task_ids):\n", + "\n", + " # put singular task ID into a list\n", + " if isinstance(task_ids, str):\n", + " task_ids = [task_ids]\n", + "\n", + " # Create a list to hold the statuses of each of the tasks\n", + " statuses = list()\n", + "\n", + " # Iterate over each of the task IDs\n", + " for this_task_id in task_ids:\n", + "\n", + " # For each task ID, get detailed information about it\n", + " task_resp = df_api.taskView(this_task_id)\n", + "\n", + " # Extract the task status from the detailed information\n", + " this_status = task_resp[0].task[0].status\n", + "\n", + " # Append this status to the list of statuses\n", + " statuses.append(this_status)\n", + "\n", + " # Return the list of statuses\n", + " return statuses" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " Try out your function using the IDs of the recent ``dataPut()`` and ``dataGet()`` functions. " + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[3]" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "check_xfer_status(task_id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Run the series of simulations:\n", + "Use the three functions defined above to mimic the process of exploring a parameter space using simulations, where for each iteration, we:
1. run a simulation,
2. capture the data + metadata into DataFed,
3. monitor the data upload tasks." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Starting simulation #0\n", + "Transfer status(es): [2]\n", + "\n", + "Starting simulation #1\n", + "Transfer status(es): [2, 2]\n", + "\n", + "Starting simulation #2\n", + "Transfer status(es): [3, 2, 2]\n", + "\n", + "Simulations complete! Waiting for uploads to complete\n", + "\n", + "Transfer status(es): [3, 3, 2]\n", + "Transfer status(es): [3, 3, 2]\n", + "Transfer status(es): [3, 3, 2]\n", + "Transfer status(es): [3, 3, 2]\n", + "Transfer status(es): [3, 3, 3]\n", + "\n", + "Finished uploading all data!\n" + ] + } + ], + "source": [ + "xfer_tasks = list()\n", + "for ind in range(3):\n", + " print(\"Starting simulation #{}\".format(ind))\n", + " # Run the simulation.\n", + " path_to_results, metadata = expensive_simulation()\n", + " # Capture the data and metadata into DataFed\n", + " task_id = capture_data(ind, metadata, path_to_results)\n", + " # Append the task ID for this data upload into xfer_tasks\n", + " xfer_tasks.append(task_id)\n", + " # Print out the status of the data transfers\n", + " print(\"Transfer status(es): {}\".format(check_xfer_status(xfer_tasks)))\n", + " print(\"\")\n", + "\n", + "print(\"Simulations complete! Waiting for uploads to complete\\n\")\n", + "\n", + "while True:\n", + " time.sleep(1)\n", + " statuses = check_xfer_status(xfer_tasks)\n", + " print(\"Transfer status(es): {}\".format(statuses))\n", + " if all([this == 3 for this in statuses]):\n", + " break\n", + "\n", + "print(\"\\nFinished uploading all data!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " What happens if you set the ``wait`` in ``dataPut()`` to ``True``? \n", + "\n", + "### **Note:** \n", + "> Users are recommended to perform data orchestration (especially large data movement - upload / download) operations outside the scope of heavy / parallel computation operations in order to avoid wasting precious wall time on compute clusters." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/jupyter_notebooks/4_Collections_Queries.ipynb b/jupyter_notebooks/4_Collections_Queries.ipynb index 4ab8cf8fa..4e47849fa 100644 --- a/jupyter_notebooks/4_Collections_Queries.ipynb +++ b/jupyter_notebooks/4_Collections_Queries.ipynb @@ -1,517 +1,544 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# 4. Collections and Queries in DataFed\n", - "In this notebook, we will be going over creating Collections, viewing contained items, organizing Collections, downloading Collections, and searching for data", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": ["## Before we begin:\n", "Import necessary libraries"], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import json\n", - "from datafed.CommandLib import API", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Instantiate the DataFed API and set ``context`` to the Training project" - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api = API()\n", "df_api.setContext('p/trn001')"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' Reset this variable to your username or Globus ID so that you work within your own collection by default ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ['parent_collection = "breetju" # Name of this user'], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Overview:\n", - "In this notebook, let us assume that we are working on a machine learning problem aimed at putting together training data for a machine learning model. For illustration purposes, we will assume that we aim to train a classifier for classifying animals", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Create Collection\n", - "First, let us create a collection to hold all our data. \n", - "\n", - "We will be using the ``collectionCreate()`` function:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "coll_resp = df_api.collectionCreate('Image classification training data',\n", - " parent_id=parent_collection)\n", - "print(coll_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this case we got back a ``CollDataReply`` object. This is somewhat similar to what you get from ``dataCreate()`` we just saw. \n", - "\n", - "\n", - '### Exercise \n', - ' Extract the ``id`` of this newly created collection: ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["train_coll_id = None"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Populate with training data\n", - "Now that we have a place to put the training data, let us populate this collection with examples of animals\n", - "### Define a function to generate (fake) training data:\n", - "We need a function to:\n", - "* Create a Data Record\n", - "* Put data into this Data Record\n", - "\n", - "For simplicity we will use some dummy data from a public Globus Endpoint This information has been filled in for you via the ``raw_data_path`` variable\n", - "\n", - '### Exercise \n', - ' We have a skeleton function prepared for you along with comments to guide you. ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import random\n", - "\n", - "def generate_animal_data(is_dog=True):\n", - " this_animal = 'cat'\n", - " if is_dog:\n", - " this_animal = 'dog'\n", - " # To mimic a real-life scenario, we append a number to the animal type to denote\n", - " # the N-th example of a cat or dog. In this case, we use a random integer.\n", - " suffix = '_' + str(random.randint(1, 1000))\n", - " \n", - " # Create the record here:\n", - " \n", - " \n", - " # Extract the ID of the Record:\n", - " \n", - " \n", - " # path to the file containing the (dummy) raw data\n", - " raw_data_path = 'sdss#public/uufs/chpc.utah.edu/common/home/sdss/dr10/apogee/spectro/data/55574/55574.md5sum'\n", - " \n", - " # Put the raw data into the record you just created: \n", - " \n", - " \n", - " # Only return the ID of the Data Record you created:\n", - " return this_rec_id", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": ["#### Generate 5 examples of cats and dogs:"], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cat_records = list()\n", - "dog_records = list()\n", - "for _ in range(5):\n", - " dog_records.append(generate_animal_data(is_dog=True))\n", - "for _ in range(5):\n", - " cat_records.append(generate_animal_data(is_dog=False))", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["print(cat_records)"], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["print(dog_records)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Listing items in a Collection:\n", - "Let us take a look at the training data we have assembled so far using the ``colectionItemsList()`` function:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "coll_list_resp = df_api.collectionItemsList(train_coll_id)\n", - "print(coll_list_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Note \n', - '> If we had several dozens, hundreds, or even thousands of items in a Collection, we would need to call ``collectionItemsList()`` multiple times by stepping up the ``offset`` keyword argument each time to get the next “page” of results. \n', - "\n", - '### Discussion \n', - ' Let\'s say that we are only interested in finding records that have cats in this (potentially) large collection of training data. How do we go about doing that? \n', - "\n", - "# Data Query / Search\n", - '### Caution \n', - '> Search vocabulary is likely to change with newer versions of DataFed \n', - "\n", - "Use the DataFed web interface to:\n", - "* Search for cats\n", - "* Specifically in your collection\n", - "* Save the query\n", - "\n", - '### Note \n', - '> Saved queries can be found in the bottom of the navigation (left) pane under ``Project Data`` and ``Saved Queries`` \n', - "\n", - "# Find saved queries:\n", - "We can list all saved queries via ``queryList()``:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["ql_resp = df_api.queryList()\n", "print(ql_resp)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Notice that we again recieved the familiar ``ListingReply`` object as the response\n", - "\n", - '### Exercise \n', - ' Get the ``id`` of the desired query out of the response: ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["query_id = ?\n", "print(query_id)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": ["# View the saved query\n", "Use the ``queryView()`` function:"], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api.queryView(query_id)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": ["# Run the saved query\n", "Use the ``queryExec()`` function:"], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "query_resp = df_api.queryExec(query_id)\n", - "print(query_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Yet again, we get back the ``ListingReply`` message. \n", - "\n", - '### Exercise \n', - ' Extract just the ``id``s from each of the items in the message: ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["# First get IDs from query result\n", "cat_rec_ids = ?"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We already have the ground truth in ``cat_records``. Is this the same as what we got from the query?" - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["print(set(cat_rec_ids) == set(cat_records))"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Separating cats from dogs\n", - "Our goal now is to gather all cat Data Records into a dedicated Collection\n", - "\n", - '### Exercise \n', - ' Create a new collection to hold the Cats record ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' Extract the ``id`` for this Collection: ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["cat_coll_id = ?"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Adding Items to Collection\n", - "Now let us add only the cat Data Records into this new collection using the ``collectionItemsUpdate()`` function:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cup_resp = df_api.collectionItemsUpdate(cat_coll_id, add_ids=cat_rec_ids)\n", - "print(cup_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Unlike most DataFed functions, this function doesn't really return much\n", - "\n", - '### Exercise \n', - ' View the contents of the Cats Collection to make sure that all Cat Data Records are present in this Collection ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' View the contents of the main training data Collection: ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Note \n', - '> Data Records can exist in **multiple** Collections just like video or songs can exist on multiple playlists \n', - "\n", - '### Exercise \n', - ' Remove the cat Data Records from the training data collection. They already exist in the "Cats" Collection ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' View the contents of the training data Collection. Do you see the individual cat Data Records in this collection? ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Search or Organize?\n", - "If you could always search for your data, what is the benefit to organizing them into collections?\n", - "\n", - "# Download entire Collection\n", - "\n", - '### Note \n', - '> Recall that DataFed can download arbitrarily large number of Records regardless of the physical locations of the DataFed repositories containing the data. \n', - "\n", - "Let us first make sure we don't already have a directory with the desired name:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dest_dir = './cat_data'\n", - "\n", - "if os.path.exists(dest_dir):\n", - " import shutil\n", - " shutil.rmtree(dest_dir)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' Download the entire Cat Collection with a single DataFed function call ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": ["Let's verify that we did infact download the data:"], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["os.listdir(dest_dir)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '## Optional Exercise \n', - '1. Create a new Collection to hold the simulation data you created in the previous notebook
2. Use the functions you saw above to ensure that the Data Records only exist in the Simulation Collection
', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [], - }, - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python [default]", - "language": "python", - "name": "python3", - }, - "language_info": { - "codemirror_mode": {"name": "ipython", "version": 3}, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.5", - }, - }, - "nbformat": 4, - "nbformat_minor": 4, + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 4. Collections and Queries in DataFed\n", + "In this notebook, we will be going over creating Collections, viewing contained items, organizing Collections, downloading Collections, and searching for data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Before we begin:\n", + "Import necessary libraries" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import random\n", + "from datafed.CommandLib import API" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Instantiate the DataFed API and set ``context`` to the Training project" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api = API()\n", + "df_api.setContext(\"p/trn001\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " Reset this variable to your username or Globus ID so that you work within your own collection by default " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "parent_collection = \"breetju\" # Name of this user" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Overview:\n", + "In this notebook, let us assume that we are working on a machine learning problem aimed at putting together training data for a machine learning model. For illustration purposes, we will assume that we aim to train a classifier for classifying animals" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Create Collection\n", + "First, let us create a collection to hold all our data. \n", + "\n", + "We will be using the ``collectionCreate()`` function:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "coll_resp = df_api.collectionCreate(\n", + " \"Image classification training data\", parent_id=parent_collection\n", + ")\n", + "print(coll_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this case we got back a ``CollDataReply`` object. This is somewhat similar to what you get from ``dataCreate()`` we just saw. \n", + "\n", + "\n", + "### Exercise \n", + " Extract the ``id`` of this newly created collection: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "train_coll_id = None" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Populate with training data\n", + "Now that we have a place to put the training data, let us populate this collection with examples of animals\n", + "### Define a function to generate (fake) training data:\n", + "We need a function to:\n", + "* Create a Data Record\n", + "* Put data into this Data Record\n", + "\n", + "For simplicity we will use some dummy data from a public Globus Endpoint This information has been filled in for you via the ``raw_data_path`` variable\n", + "\n", + "### Exercise \n", + " We have a skeleton function prepared for you along with comments to guide you. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def generate_animal_data(is_dog=True):\n", + " # this_animal = \"cat\"\n", + " if is_dog:\n", + " this_animal = \"dog\"\n", + " # To mimic a real-life scenario, we append a number to the animal\n", + " # type to denote the N-th example of a cat or dog. In this case, we\n", + " # use a random integer.\n", + " # suffix = \"_\" + str(random.randint(1, 1000))\n", + "\n", + " # Create the record here:\n", + "\n", + " # Extract the ID of the Record:\n", + "\n", + " # path to the file containing the (dummy) raw data\n", + " raw_data_path = (\n", + " \"sdss#public/uufs/chpc.utah.edu/common/home/sdss/dr10/\"\n", + " \"apogee/spectro/data/55574/55574.md5sum\"\n", + " )\n", + "\n", + " # Put the raw data into the record you just created:\n", + "\n", + " # Only return the ID of the Data Record you created:\n", + " return this_rec_id" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Generate 5 examples of cats and dogs:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cat_records = list()\n", + "dog_records = list()\n", + "for _ in range(5):\n", + " dog_records.append(generate_animal_data(is_dog=True))\n", + "for _ in range(5):\n", + " cat_records.append(generate_animal_data(is_dog=False))print(cat_records)print(dog_records)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Listing items in a Collection:\n", + "Let us take a look at the training data we have assembled so far using the ``colectionItemsList()`` function:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "coll_list_resp = df_api.collectionItemsList(train_coll_id)\n", + "print(coll_list_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Note \n", + "> If we had several dozens, hundreds, or even thousands of items in a Collection, we would need to call ``collectionItemsList()`` multiple times by stepping up the ``offset`` keyword argument each time to get the next “page” of results. \n", + "\n", + "### Discussion \n", + " Let's say that we are only interested in finding records that have cats in this (potentially) large collection of training data. How do we go about doing that? \n", + "\n", + "# Data Query / Search\n", + "### Caution \n", + "> Search vocabulary is likely to change with newer versions of DataFed \n", + "\n", + "Use the DataFed web interface to:\n", + "* Search for cats\n", + "* Specifically in your collection\n", + "* Save the query\n", + "\n", + "### Note \n", + "> Saved queries can be found in the bottom of the navigation (left) pane under ``Project Data`` and ``Saved Queries`` \n", + "\n", + "# Find saved queries:\n", + "We can list all saved queries via ``queryList()``:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ql_resp = df_api.queryList()\n", + "print(ql_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that we again recieved the familiar ``ListingReply`` object as the response\n", + "\n", + "### Exercise \n", + " Get the ``id`` of the desired query out of the response: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "query_id = ?\n", + "print(query_id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# View the saved query\n", + "Use the ``queryView()`` function:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_api.queryView(query_id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Run the saved query\n", + "Use the ``queryExec()`` function:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "query_resp = df_api.queryExec(query_id)\n", + "print(query_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Yet again, we get back the ``ListingReply`` message. \n", + "\n", + "### Exercise \n", + " Extract just the ``id``s from each of the items in the message: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# First get IDs from query result\n", + "cat_rec_ids = ?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We already have the ground truth in ``cat_records``. Is this the same as what we got from the query?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(set(cat_rec_ids) == set(cat_records))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Separating cats from dogs\n", + "Our goal now is to gather all cat Data Records into a dedicated Collection\n", + "\n", + "### Exercise \n", + " Create a new collection to hold the Cats record " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " Extract the ``id`` for this Collection: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cat_coll_id = ?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Adding Items to Collection\n", + "Now let us add only the cat Data Records into this new collection using the ``collectionItemsUpdate()`` function:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cup_resp = df_api.collectionItemsUpdate(cat_coll_id, add_ids=cat_rec_ids)\n", + "print(cup_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Unlike most DataFed functions, this function doesn't really return much\n", + "\n", + "### Exercise \n", + " View the contents of the Cats Collection to make sure that all Cat Data Records are present in this Collection " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " View the contents of the main training data Collection: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Note \n", + "> Data Records can exist in **multiple** Collections just like video or songs can exist on multiple playlists \n", + "\n", + "### Exercise \n", + " Remove the cat Data Records from the training data collection. They already exist in the \"Cats\" Collection " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " View the contents of the training data Collection. Do you see the individual cat Data Records in this collection? " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Search or Organize?\n", + "If you could always search for your data, what is the benefit to organizing them into collections?\n", + "\n", + "# Download entire Collection\n", + "\n", + "### Note \n", + "> Recall that DataFed can download arbitrarily large number of Records regardless of the physical locations of the DataFed repositories containing the data. \n", + "\n", + "Let us first make sure we don't already have a directory with the desired name:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dest_dir = \"./cat_data\"\n", + "\n", + "if os.path.exists(dest_dir):\n", + " import shutil\n", + "\n", + " shutil.rmtree(dest_dir)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " Download the entire Cat Collection with a single DataFed function call " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's verify that we did infact download the data:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "os.listdir(dest_dir)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Optional Exercise \n", + "1. Create a new Collection to hold the simulation data you created in the previous notebook
2. Use the functions you saw above to ensure that the Data Records only exist in the Simulation Collection
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/jupyter_notebooks/4_Collections_Queries_with_Solutions.ipynb b/jupyter_notebooks/4_Collections_Queries_with_Solutions.ipynb index 01b42e02c..30daaf6f1 100755 --- a/jupyter_notebooks/4_Collections_Queries_with_Solutions.ipynb +++ b/jupyter_notebooks/4_Collections_Queries_with_Solutions.ipynb @@ -1,793 +1,882 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# 4. Collections and Queries in DataFed\n", - "In this notebook, we will be going over creating Collections, viewing contained items, organizing Collections, downloading Collections, and searching for data", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": ["## Before we begin:\n", "Import necessary libraries"], - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import json\n", - "from datafed.CommandLib import API", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Instantiate the DataFed API and set ``context`` to the Training project" - ], - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": ["df_api = API()\n", "df_api.setContext('p/trn001')"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' Reset this variable to your username or Globus ID so that you work within your own collection by default ', - ], - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": ['parent_collection = "somnaths" # Name of this user'], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Overview:\n", - "In this notebook, let us assume that we are working on a machine learning problem aimed at putting together training data for a machine learning model. For illustration purposes, we will assume that we aim to train a classifier for classifying animals", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Create Collection\n", - "First, let us create a collection to hold all our data. \n", - "\n", - "We will be using the ``collectionCreate()`` function:", - ], - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(coll {\n", - ' id: "c/43657980"\n', - ' title: "Image classification training data"\n', - ' owner: "p/trn001"\n', - " ct: 1615405612\n", - " ut: 1615405612\n", - ' parent_id: "c/34558900"\n', - "}\n", - ", 'CollDataReply')\n", - ], - } - ], - "source": [ - "coll_resp = df_api.collectionCreate('Image classification training data',\n", - " parent_id=parent_collection)\n", - "print(coll_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this case we got back a ``CollDataReply`` object. This is somewhat similar to what you get from ``dataCreate()`` we just saw. \n", - "\n", - "Now, let's Extract the ``id`` of this newly created collection:", - ], - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - {"name": "stdout", "output_type": "stream", "text": ["c/43657980\n"]} - ], - "source": [ - "train_coll_id = coll_resp[0].coll[0].id\n", - "print(train_coll_id)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Populate with training data\n", - "Now that we have a place to put the training data, let us populate this collection with examples of animals\n", - "### Define a function to generate (fake) training data:\n", - "We need a function to:\n", - "* Create a Data Record\n", - "* Put data into this Data Record\n", - "\n", - "For simplicity we will use some dummy data from a public Globus Endpoint This information has been filled in for you via the ``raw_data_path`` variable. \n", - "\n", - '### Exercise \n', - ' We have a skeleton function prepared for you along with comments to guide you. ', - ], - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "import random\n", - "\n", - "def generate_animal_data(is_dog=True):\n", - " this_animal = 'cat'\n", - " if is_dog:\n", - " this_animal = 'dog'\n", - ' # Ideally, we would have more sensible titles such as "Doberman", "Poodle", etc. instead of "Dog_234"\n', - " # To mimic a real-life scenario, we append a number to the animal type to denote\n", - " # the N-th example of a cat or dog. In this case, we use a random integer.\n", - " title = this_animal + '_' + str(random.randint(1, 1000))\n", - " # Create the record here:\n", - " rec_resp = df_api.dataCreate(title,\n", - " metadata=json.dumps({'animal': this_animal}),\n", - " parent_id=train_coll_id) \n", - " \n", - " # Extract the ID of the Record:\n", - " this_rec_id = rec_resp[0].data[0].id \n", - " \n", - " # path to the file containing the (dummy) raw data\n", - " raw_data_path = 'sdss#public/uufs/chpc.utah.edu/common/home/sdss/dr10/apogee/spectro/data/55574/55574.md5sum'\n", - " \n", - " # Put the raw data into the record you just created: \n", - " put_resp = df_api.dataPut(this_rec_id, raw_data_path)\n", - " \n", - " # Only return the ID of the Data Record you created:\n", - " return this_rec_id", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": ["#### Generate 5 examples of cats and dogs:"], - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "cat_records = list()\n", - "dog_records = list()\n", - "for _ in range(5):\n", - " dog_records.append(generate_animal_data(is_dog=True))\n", - "for _ in range(5):\n", - " cat_records.append(generate_animal_data(is_dog=False))", - ], - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['d/43659103', 'd/43659126', 'd/43659149', 'd/43659172', 'd/43659195']\n" - ], - } - ], - "source": ["print(cat_records)"], - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['d/43658988', 'd/43659011', 'd/43659034', 'd/43659057', 'd/43659080']\n" - ], - } - ], - "source": ["print(dog_records)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Listing items in a Collection:\n", - "Let us take a look at the training data we have assembled so far using the ``colectionItemsList()`` function:", - ], - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {"scrolled": true}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(item {\n", - ' id: "d/43658988"\n', - ' title: "dog_196"\n', - ' owner: "p/trn001"\n', - ' creator: "u/somnaths"\n', - " size: 2842.0\n", - " notes: 0\n", - "}\n", - "item {\n", - ' id: "d/43659034"\n', - ' title: "dog_57"\n', - ' owner: "p/trn001"\n', - ' creator: "u/somnaths"\n', - " size: 2842.0\n", - " notes: 0\n", - "}\n", - "item {\n", - ' id: "d/43659080"\n', - ' title: "dog_686"\n', - ' owner: "p/trn001"\n', - ' creator: "u/somnaths"\n', - " size: 2842.0\n", - " notes: 0\n", - "}\n", - "item {\n", - ' id: "d/43659011"\n', - ' title: "dog_689"\n', - ' owner: "p/trn001"\n', - ' creator: "u/somnaths"\n', - " size: 2842.0\n", - " notes: 0\n", - "}\n", - "item {\n", - ' id: "d/43659057"\n', - ' title: "dog_778"\n', - ' owner: "p/trn001"\n', - ' creator: "u/somnaths"\n', - " size: 2842.0\n", - " notes: 0\n", - "}\n", - "offset: 5\n", - "count: 20\n", - "total: 10\n", - ", 'ListingReply')\n", - ], - } - ], - "source": [ - "coll_list_resp = df_api.collectionItemsList(train_coll_id, offset=5)\n", - "print(coll_list_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Note \n', - '> If we had several dozens, hundreds, or even thousands of items in a Collection, we would need to call ``collectionItemsList()`` multiple times by stepping up the ``offset`` keyword argument each time to get the next “page” of results. \n', - "\n", - '### Discussion \n', - ' Let\'s say that we are only interested in finding records that have cats in this (potentially) large collection of training data. How do we go about doing that? \n', - "\n", - "# Data Query / Search\n", - '### Caution \n', - '> Search vocabulary is likely to change with newer versions of DataFed \n', - "\n", - "Use the DataFed web interface to:\n", - "* Search for cats\n", - "* Specifically in your collection\n", - "* Save the query\n", - "\n", - '### Note \n', - '> Saved queries can be found in the bottom of the navigation (left) pane under ``Project Data`` and ``Saved Queries`` \n', - "\n", - "# Find saved queries:\n", - "We can list all saved queries via ``queryList()``:", - ], - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(item {\n", - ' id: "q/43664114"\n', - ' title: "is_cat"\n', - "}\n", - "offset: 0\n", - "count: 20\n", - "total: 1\n", - ", 'ListingReply')\n", - ], - } - ], - "source": ["ql_resp = df_api.queryList()\n", "print(ql_resp)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Notice that we again recieved the familiar ``ListingReply`` object as the response\n", - "\n", - '### Exercise \n', - ' Get the ``id`` of the desired query out of the response: ', - ], - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - {"name": "stdout", "output_type": "stream", "text": ["q/43664114\n"]} - ], - "source": ["query_id = ql_resp[0].item[0].id\n", "print(query_id)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": ["# View the saved query\n", "Use the ``queryView()`` function:"], - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(query {\n", - ' id: "q/43664114"\n', - ' title: "is_cat"\n', - ' query: "{\\"meta\\":\\"md.animal == \\\\\\"cat\\\\\\"\\",\\"scopes\\":[{\\"scope\\":4,\\"id\\":\\"c/43657980\\",\\"recurse\\":true}]}"\n', - ' owner: "u/somnaths"\n', - " ct: 1615406400\n", - " ut: 1615406400\n", - " },\n", - " 'QueryDataReply')", - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result", - } - ], - "source": ["df_api.queryView(query_id)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": ["# Run the saved query\n", "Use the ``queryExec()`` function:"], - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(item {\n", - ' id: "d/43659103"\n', - ' title: "cat_209"\n', - ' owner: "p/trn001"\n', - ' creator: "u/somnaths"\n', - " size: 2842.0\n", - " notes: 0\n", - "}\n", - "item {\n", - ' id: "d/43659126"\n', - ' title: "cat_511"\n', - ' owner: "p/trn001"\n', - ' creator: "u/somnaths"\n', - " size: 2842.0\n", - " notes: 0\n", - "}\n", - "item {\n", - ' id: "d/43659149"\n', - ' title: "cat_341"\n', - ' owner: "p/trn001"\n', - ' creator: "u/somnaths"\n', - " size: 2842.0\n", - " notes: 0\n", - "}\n", - "item {\n", - ' id: "d/43659172"\n', - ' title: "cat_558"\n', - ' owner: "p/trn001"\n', - ' creator: "u/somnaths"\n', - " size: 2842.0\n", - " notes: 0\n", - "}\n", - "item {\n", - ' id: "d/43659195"\n', - ' title: "cat_821"\n', - ' owner: "p/trn001"\n', - ' creator: "u/somnaths"\n', - " size: 2842.0\n", - " notes: 0\n", - "}\n", - ", 'ListingReply')\n", - ], - } - ], - "source": [ - "query_resp = df_api.queryExec(query_id)\n", - "print(query_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Yet again, we get back the ``ListingReply`` message. \n", - "\n", - "Now let us extract just the ``id``s from each of the items in the message:", - ], - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['d/43659103', 'd/43659126', 'd/43659149', 'd/43659172', 'd/43659195']\n" - ], - } - ], - "source": [ - "cat_rec_ids = list()\n", - "for record in query_resp[0].item:\n", - " cat_rec_ids.append(record.id)\n", - "# one could also use list comprehensions to get the answer in one line:\n", - "# cat_rec_ids = [record.id for record in query_resp[0].item]\n", - "print(cat_rec_ids)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We already have the ground truth in ``cat_records``. Is this the same as what we got from the query?" - ], - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - {"name": "stdout", "output_type": "stream", "text": ["True\n"]} - ], - "source": ["print(set(cat_rec_ids) == set(cat_records))"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Separating cats from dogs\n", - "Our goal now is to gather all cat Data Records into a dedicated Collection\n", - "\n", - '### Exercise \n', - ' Create a new collection to hold the Cats record ', - ], - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - {"name": "stdout", "output_type": "stream", "text": ["c/43666045\n"]} - ], - "source": [ - "coll_resp = df_api.collectionCreate('Cats', parent_id=train_coll_id)" - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' Extract the ``id`` for this Collection: ', - ], - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - {"name": "stdout", "output_type": "stream", "text": ["c/43666045\n"]} - ], - "source": ["cat_coll_id = coll_resp[0].coll[0].id\n", "print(cat_coll_id)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Adding Items to Collection\n", - "Now let us add only the cat Data Records into this new collection using the ``collectionItemsUpdate()`` function:", - ], - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": ["(, 'ListingReply')\n"], - } - ], - "source": [ - "cup_resp = df_api.collectionItemsUpdate(cat_coll_id, add_ids=cat_rec_ids)\n", - "print(cup_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Unlike most DataFed functions, this function doesn't really return much\n", - "\n", - "Now, let us view the contents of the Cats Collection to make sure that all Cat Data Records are present in this Collection. \n", - "\n", - "Just to keep the output clean and short, we will only extract the ID and title of the items", - ], - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "d/43659103 cat_209\n", - "d/43659149 cat_341\n", - "d/43659126 cat_511\n", - "d/43659172 cat_558\n", - "d/43659195 cat_821\n", - ], - } - ], - "source": [ - "ls_resp = df_api.collectionItemsList(cat_coll_id)\n", - "# Iterating through the items in the Collection and only extracting a few items:\n", - "for obj in ls_resp[0].item:\n", - " print(obj.id, obj.title)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' View the contents of the main training data Collection.
You may use the snippet above if you like and modify it accordingly
', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ls_resp = df_api.collectionItemsList(train_coll_id)\n", - "# Iterating through the items in the Collection and only extracting a few items:\n", - "for obj in ls_resp[0].item:\n", - " print(obj.id, obj.title)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Note \n', - '> Data Records can exist in **multiple** Collections just like video or songs can exist on multiple playlists \n', - "\n", - '### Exercise \n', - ' Remove the cat Data Records from the training data collection. They already exist in the "Cats" Collection.
**Hint**: The function call is very similar to the function call for adding cats to the "Cats" collection
', - ], - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": ["(, 'ListingReply')\n"], - } - ], - "source": [ - "cup_resp = df_api.collectionItemsUpdate(train_coll_id, rem_ids=cat_rec_ids)\n", - "print(cup_resp)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' View the contents of the training data Collection.
You may reuse a code snippet from an earlier cell.
Do you see the individual cat Data Records in this collection?
', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ls_resp = df_api.collectionItemsList(train_coll_id)\n", - "# Iterating through the items in the Collection and only extracting a few items:\n", - "for obj in ls_resp[0].item:\n", - " print(obj.id, obj.title)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Search or Organize?\n", - "If you could always search for your data, what is the benefit to organizing them into collections?\n", - "\n", - "# Download entire Collection\n", - "\n", - '### Note \n', - '> Recall that DataFed can download arbitrarily large number of Records regardless of the physical locations of the DataFed repositories containing the data. \n', - "\n", - "Let us first make sure we don't already have a directory with the desired name:", - ], - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [], - "source": [ - "dest_dir = './cat_data'\n", - "\n", - "if os.path.exists(dest_dir):\n", - " import shutil\n", - " shutil.rmtree(dest_dir)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '### Exercise \n', - ' Download the entire Cat Collection with a single DataFed function call.
**Hint:** You may want to look at a function we used in the third notebook
', - ], - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(task {\n", - ' id: "task/43667334"\n', - " type: TT_DATA_GET\n", - " status: TS_SUCCEEDED\n", - ' client: "u/somnaths"\n', - " step: 2\n", - " steps: 3\n", - ' msg: "Finished"\n', - " ct: 1615407332\n", - " ut: 1615407338\n", - ' source: "d/43659103, d/43659126, d/43659149, d/43659172, d/43659195, ..."\n', - ' dest: "1646e89e-f4f0-11e9-9944-0a8c187e8c12/Users/syz/OneDrive - Oak Ridge National Laboratory/DataFed_Tutorial/Notebooks/cat_data"\n', - " },\n", - " 'TaskDataReply')", - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result", - } - ], - "source": ["df_api.dataGet(cat_coll_id, './cat_data', wait=True)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": ["Let's verify that we did infact download the data:"], - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['43659195.md5sum',\n", - " '43659103.md5sum',\n", - " '43659172.md5sum',\n", - " '43659126.md5sum',\n", - " '43659149.md5sum']", - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result", - } - ], - "source": ["os.listdir(dest_dir)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '## Optional Exercise \n', - '1. Create a new Collection to hold the simulation data you created in the previous notebook
2. Use the functions you saw above to ensure that the Data Records only exist in the Simulation Collection
', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [], - }, - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3", - }, - "language_info": { - "codemirror_mode": {"name": "ipython", "version": 3}, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.3", - }, - }, - "nbformat": 4, - "nbformat_minor": 4, + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 4. Collections and Queries in DataFed\n", + "In this notebook, we will be going over creating Collections, viewing contained items, organizing Collections, downloading Collections, and searching for data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Before we begin:\n", + "Import necessary libraries" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import random\n", + "import json\n", + "from datafed.CommandLib import API" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Instantiate the DataFed API and set ``context`` to the Training project" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df_api = API()\n", + "df_api.setContext(\"p/trn001\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " Reset this variable to your username or Globus ID so that you work within your own collection by default " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "parent_collection = \"somnaths\" # Name of this user" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Overview:\n", + "In this notebook, let us assume that we are working on a machine learning problem aimed at putting together training data for a machine learning model. For illustration purposes, we will assume that we aim to train a classifier for classifying animals" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Create Collection\n", + "First, let us create a collection to hold all our data. \n", + "\n", + "We will be using the ``collectionCreate()`` function:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(coll {\n", + " id: \"c/43657980\"\n", + " title: \"Image classification training data\"\n", + " owner: \"p/trn001\"\n", + " ct: 1615405612\n", + " ut: 1615405612\n", + " parent_id: \"c/34558900\"\n", + "}\n", + ", 'CollDataReply')\n" + ] + } + ], + "source": [ + "coll_resp = df_api.collectionCreate(\n", + " \"Image classification training data\", parent_id=parent_collection\n", + ")\n", + "print(coll_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this case we got back a ``CollDataReply`` object. This is somewhat similar to what you get from ``dataCreate()`` we just saw. \n", + "\n", + "Now, let's Extract the ``id`` of this newly created collection:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "c/43657980\n" + ] + } + ], + "source": [ + "train_coll_id = coll_resp[0].coll[0].id\n", + "print(train_coll_id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Populate with training data\n", + "Now that we have a place to put the training data, let us populate this collection with examples of animals\n", + "### Define a function to generate (fake) training data:\n", + "We need a function to:\n", + "* Create a Data Record\n", + "* Put data into this Data Record\n", + "\n", + "For simplicity we will use some dummy data from a public Globus Endpoint This information has been filled in for you via the ``raw_data_path`` variable. \n", + "\n", + "### Exercise \n", + " We have a skeleton function prepared for you along with comments to guide you. " + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def generate_animal_data(is_dog=True):\n", + " this_animal = \"cat\"\n", + " if is_dog:\n", + " this_animal = \"dog\"\n", + " # Ideally, we would have more sensible titles such as \"Doberman\",\n", + " # \"Poodle\", etc. instead of \"Dog_234\"\n", + " # To mimic a real-life scenario, we append a number to the animal\n", + " # type to denote the N-th example of a cat or dog. In this case,\n", + " # we use a random integer.\n", + " title = this_animal + \"_\" + str(random.randint(1, 1000))\n", + " # Create the record here:\n", + " rec_resp = df_api.dataCreate(\n", + " title,\n", + " metadata=json.dumps({\"animal\": this_animal}),\n", + " parent_id=train_coll_id,\n", + " )\n", + "\n", + " # Extract the ID of the Record:\n", + " this_rec_id = rec_resp[0].data[0].id\n", + "\n", + " # path to the file containing the (dummy) raw data\n", + " raw_data_path = (\n", + " \"sdss#public/uufs/chpc.utah.edu/common/home/sdss/dr10/\"\n", + " \"apogee/spectro/data/55574/55574.md5sum\"\n", + " )\n", + "\n", + " # Put the raw data into the record you just created:\n", + " put_resp = df_api.dataPut(this_rec_id, raw_data_path)\n", + "\n", + " # Only return the ID of the Data Record you created:\n", + " return this_rec_id" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Generate 5 examples of cats and dogs:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "cat_records = list()\n", + "dog_records = list()\n", + "for _ in range(5):\n", + " dog_records.append(generate_animal_data(is_dog=True))\n", + "for _ in range(5):\n", + " cat_records.append(generate_animal_data(is_dog=False))" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['d/43659103', 'd/43659126', 'd/43659149', 'd/43659172', 'd/43659195']\n" + ] + } + ], + "source": [ + "print(cat_records)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['d/43658988', 'd/43659011', 'd/43659034', 'd/43659057', 'd/43659080']\n" + ] + } + ], + "source": [ + "print(dog_records)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Listing items in a Collection:\n", + "Let us take a look at the training data we have assembled so far using the ``colectionItemsList()`` function:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(item {\n", + " id: \"d/43658988\"\n", + " title: \"dog_196\"\n", + " owner: \"p/trn001\"\n", + " creator: \"u/somnaths\"\n", + " size: 2842.0\n", + " notes: 0\n", + "}\n", + "item {\n", + " id: \"d/43659034\"\n", + " title: \"dog_57\"\n", + " owner: \"p/trn001\"\n", + " creator: \"u/somnaths\"\n", + " size: 2842.0\n", + " notes: 0\n", + "}\n", + "item {\n", + " id: \"d/43659080\"\n", + " title: \"dog_686\"\n", + " owner: \"p/trn001\"\n", + " creator: \"u/somnaths\"\n", + " size: 2842.0\n", + " notes: 0\n", + "}\n", + "item {\n", + " id: \"d/43659011\"\n", + " title: \"dog_689\"\n", + " owner: \"p/trn001\"\n", + " creator: \"u/somnaths\"\n", + " size: 2842.0\n", + " notes: 0\n", + "}\n", + "item {\n", + " id: \"d/43659057\"\n", + " title: \"dog_778\"\n", + " owner: \"p/trn001\"\n", + " creator: \"u/somnaths\"\n", + " size: 2842.0\n", + " notes: 0\n", + "}\n", + "offset: 5\n", + "count: 20\n", + "total: 10\n", + ", 'ListingReply')\n" + ] + } + ], + "source": [ + "coll_list_resp = df_api.collectionItemsList(train_coll_id, offset=5)\n", + "print(coll_list_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Note \n", + "> If we had several dozens, hundreds, or even thousands of items in a Collection, we would need to call ``collectionItemsList()`` multiple times by stepping up the ``offset`` keyword argument each time to get the next “page” of results. \n", + "\n", + "### Discussion \n", + " Let's say that we are only interested in finding records that have cats in this (potentially) large collection of training data. How do we go about doing that? \n", + "\n", + "# Data Query / Search\n", + "### Caution \n", + "> Search vocabulary is likely to change with newer versions of DataFed \n", + "\n", + "Use the DataFed web interface to:\n", + "* Search for cats\n", + "* Specifically in your collection\n", + "* Save the query\n", + "\n", + "### Note \n", + "> Saved queries can be found in the bottom of the navigation (left) pane under ``Project Data`` and ``Saved Queries`` \n", + "\n", + "# Find saved queries:\n", + "We can list all saved queries via ``queryList()``:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(item {\n", + " id: \"q/43664114\"\n", + " title: \"is_cat\"\n", + "}\n", + "offset: 0\n", + "count: 20\n", + "total: 1\n", + ", 'ListingReply')\n" + ] + } + ], + "source": [ + "ql_resp = df_api.queryList()\n", + "print(ql_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that we again recieved the familiar ``ListingReply`` object as the response\n", + "\n", + "### Exercise \n", + " Get the ``id`` of the desired query out of the response: " + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "q/43664114\n" + ] + } + ], + "source": [ + "query_id = ql_resp[0].item[0].id\n", + "print(query_id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# View the saved query\n", + "Use the ``queryView()`` function:" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(query {\n", + " id: \"q/43664114\"\n", + " title: \"is_cat\"\n", + " query: \"{\\\"meta\\\":\\\"md.animal == \\\\\\\"cat\\\\\\\"\\\",\\\"scopes\\\":[{\\\"scope\\\":4,\\\"id\\\":\\\"c/43657980\\\",\\\"recurse\\\":true}]}\"\n", + " owner: \"u/somnaths\"\n", + " ct: 1615406400\n", + " ut: 1615406400\n", + " },\n", + " 'QueryDataReply')" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df_api.queryView(query_id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Run the saved query\n", + "Use the ``queryExec()`` function:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(item {\n", + " id: \"d/43659103\"\n", + " title: \"cat_209\"\n", + " owner: \"p/trn001\"\n", + " creator: \"u/somnaths\"\n", + " size: 2842.0\n", + " notes: 0\n", + "}\n", + "item {\n", + " id: \"d/43659126\"\n", + " title: \"cat_511\"\n", + " owner: \"p/trn001\"\n", + " creator: \"u/somnaths\"\n", + " size: 2842.0\n", + " notes: 0\n", + "}\n", + "item {\n", + " id: \"d/43659149\"\n", + " title: \"cat_341\"\n", + " owner: \"p/trn001\"\n", + " creator: \"u/somnaths\"\n", + " size: 2842.0\n", + " notes: 0\n", + "}\n", + "item {\n", + " id: \"d/43659172\"\n", + " title: \"cat_558\"\n", + " owner: \"p/trn001\"\n", + " creator: \"u/somnaths\"\n", + " size: 2842.0\n", + " notes: 0\n", + "}\n", + "item {\n", + " id: \"d/43659195\"\n", + " title: \"cat_821\"\n", + " owner: \"p/trn001\"\n", + " creator: \"u/somnaths\"\n", + " size: 2842.0\n", + " notes: 0\n", + "}\n", + ", \"ListingReply\")\n" + ] + } + ], + "source": [ + "query_resp = df_api.queryExec(query_id)\n", + "print(query_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Yet again, we get back the ``ListingReply`` message. \n", + "\n", + "Now let us extract just the ``id``s from each of the items in the message:" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['d/43659103', 'd/43659126', 'd/43659149', 'd/43659172', 'd/43659195']\n" + ] + } + ], + "source": [ + "cat_rec_ids = list()\n", + "for record in query_resp[0].item:\n", + " cat_rec_ids.append(record.id)\n", + "# one could also use list comprehensions to get the answer in one line:\n", + "# cat_rec_ids = [record.id for record in query_resp[0].item]\n", + "print(cat_rec_ids)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We already have the ground truth in ``cat_records``. Is this the same as what we got from the query?" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], + "source": [ + "print(set(cat_rec_ids) == set(cat_records))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Separating cats from dogs\n", + "Our goal now is to gather all cat Data Records into a dedicated Collection\n", + "\n", + "### Exercise \n", + " Create a new collection to hold the Cats record " + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "c/43666045\n" + ] + } + ], + "source": [ + "coll_resp = df_api.collectionCreate(\"Cats\", parent_id=train_coll_id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " Extract the ``id`` for this Collection: " + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "c/43666045\n" + ] + } + ], + "source": [ + "cat_coll_id = coll_resp[0].coll[0].id\n", + "print(cat_coll_id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Adding Items to Collection\n", + "Now let us add only the cat Data Records into this new collection using the ``collectionItemsUpdate()`` function:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(, 'ListingReply')\n" + ] + } + ], + "source": [ + "cup_resp = df_api.collectionItemsUpdate(cat_coll_id, add_ids=cat_rec_ids)\n", + "print(cup_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Unlike most DataFed functions, this function doesn't really return much\n", + "\n", + "Now, let us view the contents of the Cats Collection to make sure that all Cat Data Records are present in this Collection. \n", + "\n", + "Just to keep the output clean and short, we will only extract the ID and title of the items" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "d/43659103 cat_209\n", + "d/43659149 cat_341\n", + "d/43659126 cat_511\n", + "d/43659172 cat_558\n", + "d/43659195 cat_821\n" + ] + } + ], + "source": [ + "ls_resp = df_api.collectionItemsList(cat_coll_id)\n", + "# Iterating through the items in the Collection and only extracting\n", + "# a few items:\n", + "for obj in ls_resp[0].item:\n", + " print(obj.id, obj.title)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " View the contents of the main training data Collection.
You may use the snippet above if you like and modify it accordingly
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ls_resp = df_api.collectionItemsList(train_coll_id)\n", + "# Iterating through the items in the Collection and only extracting a\n", + "# few items:\n", + "for obj in ls_resp[0].item:\n", + " print(obj.id, obj.title)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Note \n", + "> Data Records can exist in **multiple** Collections just like video or songs can exist on multiple playlists \n", + "\n", + "### Exercise \n", + " Remove the cat Data Records from the training data collection. They already exist in the \"Cats\" Collection.
**Hint**: The function call is very similar to the function call for adding cats to the \"Cats\" collection
" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(, 'ListingReply')\n" + ] + } + ], + "source": [ + "cup_resp = df_api.collectionItemsUpdate(train_coll_id, rem_ids=cat_rec_ids)\n", + "print(cup_resp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " View the contents of the training data Collection.
You may reuse a code snippet from an earlier cell.
Do you see the individual cat Data Records in this collection?
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ls_resp = df_api.collectionItemsList(train_coll_id)\n", + "# Iterating through the items in the Collection and only extracting\n", + "# a few items:\n", + "for obj in ls_resp[0].item:\n", + " print(obj.id, obj.title)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Search or Organize?\n", + "If you could always search for your data, what is the benefit to organizing them into collections?\n", + "\n", + "# Download entire Collection\n", + "\n", + "### Note \n", + "> Recall that DataFed can download arbitrarily large number of Records regardless of the physical locations of the DataFed repositories containing the data. \n", + "\n", + "Let us first make sure we don't already have a directory with the desired name:" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "dest_dir = \"./cat_data\"\n", + "\n", + "if os.path.exists(dest_dir):\n", + " import shutil\n", + "\n", + " shutil.rmtree(dest_dir)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise \n", + " Download the entire Cat Collection with a single DataFed function call.
**Hint:** You may want to look at a function we used in the third notebook
" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(task {\n", + " id: \"task/43667334\"\n", + " type: TT_DATA_GET\n", + " status: TS_SUCCEEDED\n", + " client: \"u/somnaths\"\n", + " step: 2\n", + " steps: 3\n", + " msg: \"Finished\"\n", + " ct: 1615407332\n", + " ut: 1615407338\n", + " source: \"d/43659103, d/43659126, d/43659149, d/43659172, d/43659195, ...\"\n", + " dest: \"1646e89e-f4f0-11e9-9944-0a8c187e8c12/Users/syz/OneDrive - Oak Ridge National Laboratory/DataFed_Tutorial/Notebooks/cat_data\"\n", + " },\n", + " 'TaskDataReply')" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df_api.dataGet(cat_coll_id, \"./cat_data\", wait=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's verify that we did infact download the data:" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['43659195.md5sum',\n", + " '43659103.md5sum',\n", + " '43659172.md5sum',\n", + " '43659126.md5sum',\n", + " '43659149.md5sum']" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "os.listdir(dest_dir)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Optional Exercise \n", + "1. Create a new Collection to hold the simulation data you created in the previous notebook
2. Use the functions you saw above to ensure that the Data Records only exist in the Simulation Collection
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/jupyter_notebooks/5_Collaborative_Exercise.ipynb b/jupyter_notebooks/5_Collaborative_Exercise.ipynb index a3e1bd71e..ca65c19f4 100644 --- a/jupyter_notebooks/5_Collaborative_Exercise.ipynb +++ b/jupyter_notebooks/5_Collaborative_Exercise.ipynb @@ -1,161 +1,162 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - '# Collaborative Exercise: DataFed Zoo ' - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this exercise, you are encouraged to refer back to the examples and exercises in previous notebooks, feel free to re-use as much code as you'd like. " - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from datafed.CommandLib import API\n", - "df_api = API()\n", - "df_api.setContext('p/trn001')", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Animal Generator: Create 5 records\n", - 'Similar to the cat/dog creator, define a function that creates a record with the title "animal" + "_" + "random numeric suffix". \n', - "\n", - 'The key difference is that your record metadata **must** contain a standardized field called "height".\n', - "\n", - "Here is sample code for generating random animal heights to 2 decimal places: \n", - "\n", - " import random \n", - ' metadata = {"height": round(random.uniform(min_height, max_height), 2)\n', - "\n", - "These records should be created in the 'projshare' collection, to which everyone has access.\n", - "\n", - "Use your function to create 5 new records for the animal of your choice.", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["def animal_generator(...):\n", " "], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Search for New Animals: Create a Query\n", - "Take a quick look at the 'projshare' collection (either using the API) or the web interface, and pick another animal someone else has made records for, *or* another user whose data you'd like to use. \n", - "\n", - "Use the web interface to create a query that searches the data for the records made for that animal, or for that user's records.\n", - "\n", - "Run your query below:", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["query_results = df_api.queryExec(...)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Isolate New Animals: Find the Record IDs\n", - "Iterate over the query_results protobuf message to create a list of IDs for the records that matched your search criteria.", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["rec_ids = list(...)"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Gather Height Data: Extract Metadata from the Records\n", - "Use the dataView() command to get and extract the height metadata for each of the records in your list. ", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["heights = list()\n", "for rec_id in rec_ids:\n", " ...\n"], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Make New Data: Find the Average Height\n", - 'Find the average animal height, and create a new record for the with this value in its metadata, i.e. `metadata={"average_height": x}`. ', - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "average_height = ?\n", - "\n", - "avg_rec = df_api.dataCreate(...)", - ], - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Track Provenance: Add References to the Input Data Records\n", - "Using the `deps_add` keyword argument, update your average record so that it shows which records its data was derived from.\n", - "\n", - "The deps_add argument is an array of lists or tuples whose elements are: [0] the type of relationship, and [1] the id or alias of the record to whom the relationship will be connected. \n", - "For example:\n", - "\n", - " deps_add = [('der', record_id_1), ('comp', record_id_2), ...]", - ], - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": ["df_api.dataUpdate(avg_rec, ...)"], - }, - ], - "metadata": { - "kernelspec": { - "display_name": "Python [default]", - "language": "python", - "name": "python3", - }, - "language_info": { - "codemirror_mode": {"name": "ipython", "version": 3}, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.5", - }, - }, - "nbformat": 4, - "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Collaborative Exercise: DataFed Zoo " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this exercise, you are encouraged to refer back to the examples and exercises in previous notebooks, feel free to re-use as much code as you'd like. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from datafed.CommandLib import API\n", + "\n", + "df_api = API()\n", + "df_api.setContext(\"p/trn001\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Animal Generator: Create 5 records\n", + "Similar to the cat/dog creator, define a function that creates a record with the title \"animal\" + \"_\" + \"random numeric suffix\". \n", + "\n", + "The key difference is that your record metadata **must** contain a standardized field called \"height\".\n", + "\n", + "Here is sample code for generating random animal heights to 2 decimal places: \n", + "\n", + " import random \n", + " metadata = {\"height\": round(random.uniform(min_height, max_height), 2)\n", + "\n", + "These records should be created in the 'projshare' collection, to which everyone has access.\n", + "\n", + "Use your function to create 5 new records for the animal of your choice." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def animal_generator(...):\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Search for New Animals: Create a Query\n", + "Take a quick look at the 'projshare' collection (either using the API) or the web interface, and pick another animal someone else has made records for, *or* another user whose data you'd like to use. \n", + "\n", + "Use the web interface to create a query that searches the data for the records made for that animal, or for that user's records.\n", + "\n", + "Run your query below:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "query_results = df_api.queryExec(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Isolate New Animals: Find the Record IDs\n", + "Iterate over the query_results protobuf message to create a list of IDs for the records that matched your search criteria." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "rec_ids = list(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Gather Height Data: Extract Metadata from the Records\n", + "Use the dataView() command to get and extract the height metadata for each of the records in your list. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "heights = list()\n", + "for rec_id in rec_ids:\n", + " ..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Make New Data: Find the Average Height & Then Track Provenance: Add references to input Data Records\n", + "Find the average animal height, and create a new record for the with this value in its metadata, i.e. `metadata={\"average_height\": x}`. ", + "Using the `deps_add` keyword argument, update your average record so that it shows which records its data was derived from.\n", + "\n", + "The deps_add argument is an array of lists or tuples whose elements are: [0] the type of relationship, and [1] the id or alias of the record to whom the relationship will be connected. \n", + "For example:\n", + "\n", + " deps_add = [('der', record_id_1), ('comp', record_id_2), ...]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "average_height = ?\n", + "\n", + "avg_rec = df_api.dataCreate(...)df_api.dataUpdate(avg_rec, ...)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..e5870c2e0 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,11 @@ +[tool.black] +line-length = 100 +target-version = ['py38', 'py39', 'py310'] +include = '\.pyi?$' +exclude = ''' +/( + \.git + | \.venv + | build +) +''' diff --git a/python/datafed_pkg/README b/python/datafed_pkg/README index 5994705d3..037682ee3 100644 --- a/python/datafed_pkg/README +++ b/python/datafed_pkg/README @@ -1,2 +1,43 @@ +# Description -DataFed is a federated scientific data management system developed by Oak Ridge National Laboratories to facilitate FAIR data practices within supported experimental, compute, and analytics environments. The DataFed Python package provides both a command-line-interface (CLI) and a programming API for interacting with DataFed services. +DataFed is a federated scientific data management system developed by Oak Ridge +National Laboratories to facilitate FAIR data practices within supported +experimental, compute, and analytics environments. The DataFed Python package +provides both a command-line-interface (CLI) and a programming API for +interacting with DataFed services. + +# Developers + +For running datafed directly from the source folder located in the DataFed +GitHub repository, without running a pip install of the package. Activate the +python env. This might be installed at /opt/datafed/dependencies/python/bin if +you used DataFed's provided dependency install scripts with the default +location. + +``` +source /opt/datafed/dependencies/python/bin/activate +``` + +Run the following from the root of the DataFed repo. The generate_datafed +script will generate default settings. the ENABLE_PYTHON_CLIENT is to make +sure you actually build the python client. Many other default flags may be +turned on, you can disable them if needed. + +The build target will "pydatafed" is needed for compiling the protobuf files +to python, you will need protobuf to be installed. + +NOTE - You will need to rerun this command any times changes are made to the +.proto files. + +``` +./scripts/generated_datafed.sh +/opt/datafed/dependencies/bin/cmake -S. -B build -DENABLE_PYTHON_CLIENT=ON +/opt/datafed/dependencies/bin/cmake --build build --target pydatafed +``` + +Move into the python/datafed_pkg folder and then you can execute the python +cli tool directly with. + +``` +PYTHON_PATH=. ./scripts/datafed +``` diff --git a/python/datafed_pkg/datafed/Connection.py b/python/datafed_pkg/datafed/Connection.py index 3c67574e4..d34dd1e1c 100644 --- a/python/datafed_pkg/datafed/Connection.py +++ b/python/datafed_pkg/datafed/Connection.py @@ -14,7 +14,7 @@ # registerProtocol() method then loads uses this information to create # consistent message type framing for python send/recv methods. -import google.protobuf.reflection +from google.protobuf.message_factory import GetMessageClass import logging import zmq import zmq.utils.z85 @@ -197,11 +197,12 @@ def recv(self, a_timeout=1000): if frame_values[0] > 0: # Create message by parsing content data = self._socket.recv(0) - reply = google.protobuf.reflection.ParseMessage(desc, data) + reply = GetMessageClass(desc)() + reply.ParseFromString(data) else: # No content, just create message instance data = self._socket.recv(0) - reply = google.protobuf.reflection.MakeClass(desc)() + reply = GetMessageClass(desc)() return reply, desc.name, frame_values[3] else: @@ -271,8 +272,6 @@ def reset(self): def makeMessage(self, msg_name): # find message descriptor based on type (descriptor index) if msg_name in self._msg_desc_by_name: - return google.protobuf.reflection.MakeClass( - self._msg_desc_by_name[msg_name] - )() + return GetMessageClass(self._msg_desc_by_name[msg_name])() else: return None diff --git a/python/datafed_pkg/datafed/MessageLib.py b/python/datafed_pkg/datafed/MessageLib.py index 6216707b4..62354c0eb 100644 --- a/python/datafed_pkg/datafed/MessageLib.py +++ b/python/datafed_pkg/datafed/MessageLib.py @@ -11,8 +11,6 @@ # secure ZeroMQ link. -import xmlrpc.client -import re import zmq from . import Version_pb2 from . import SDMS_Anon_pb2 as anon @@ -20,38 +18,7 @@ from . import Connection from . import VERSION - -# Function to check if a string contains any letters -def contains_letters(s): - return bool(re.search("[a-zA-Z]", s)) - - -def remove_after_prefix_with_numbers(s): - # Use regular expression to match the prefix with numbers - match = re.match(r"(\d+.*?)(\D.*)", s) - if match: - return match.group(1) # Return the part before the remaining string - return s # If no match is found, return the original string - - -# Check with pypi if a newer release is available, only look for stable -# versions -def get_latest_stable_version(package_name): - try: - client = xmlrpc.client.ServerProxy("https://pypi.org/pypi") - releases = client.package_releases(package_name) - - # Filter the list to remove entries that contain any letters, we don't - # want to look at entries that could be a pre-release of some sort and - # recommend that the user use for instance a beta version. - releases = [release for release in releases if not contains_letters(release)] - if not releases: - return None - - return releases[0] - except Exception as e: - print(f"Unable to connect to pypi: {e}") - return None +from . import VersionUtils ## @@ -204,7 +171,7 @@ def __init__( # Make a request to pypi package_name = "datafed" # Replace with the package name you want to check - latest_version_on_pypi = get_latest_stable_version(package_name) + latest_version_on_pypi = VersionUtils.get_latest_stable_version(package_name) self.new_client_avail = False if latest_version_on_pypi: @@ -212,7 +179,7 @@ def __init__( major, minor, patch_w_prerelease = VERSION.__version__.split(".") # Remove prerelease part from patch - patch = remove_after_prefix_with_numbers(patch_w_prerelease) + patch = VersionUtils.remove_after_prefix_with_numbers(patch_w_prerelease) if pypi_major > major: self.new_client_avail = latest_version_on_pypi diff --git a/python/datafed_pkg/datafed/VersionUtils.py b/python/datafed_pkg/datafed/VersionUtils.py new file mode 100644 index 000000000..cb25436d7 --- /dev/null +++ b/python/datafed_pkg/datafed/VersionUtils.py @@ -0,0 +1,59 @@ +# @package datafed.VersionUtils +# version utilities for ensuring updated version of package are being used +# +# The functions included in here are to do version comparisons and to grab +# the registered versions that are available on pypi. + +import re +import requests + + +# Function to convert version string into a tuple of integers for comparison +def version_key(version): + # Split main version and optional build number (e.g., "1.1.0-4" -> ["1.1.0", "4"]) + main_version, *build = version.split("-") + # Convert main version part to tuple of integers for correct comparison + main_version_tuple = tuple(map(int, main_version.split("."))) + # Convert build part to integer if it exists, or set to -1 for non-build versions + build_number = int(build[0]) if build else -1 + # Return full tuple for sorting, making sure 0.x.y is distinct from x.y.z + return main_version_tuple + (build_number,) + + +# Function to check if a string contains any letters +def contains_letters(s): + return bool(re.search("[a-zA-Z]", s)) + + +def remove_after_prefix_with_numbers(s): + # Use regular expression to match the prefix with numbers + match = re.match(r"(\d+.*?)(\D.*)", s) + if match: + return match.group(1) # Return the part before the remaining string + return s # If no match is found, return the original string + + +# Check with pypi if a newer release is available, only look for stable +# versions +def get_latest_stable_version(package_name): + try: + url = f"https://pypi.org/pypi/{package_name}/json" + response = requests.get(url) + response.raise_for_status() + data = response.json() + + # Extract release versions + releases = list(data.get("releases", {}).keys()) + # Filter the list to remove entries that contain any letters, we don't + # want to look at entries that could be a pre-release of some sort and + # recommend that the user use for instance a beta version. + releases = [release for release in releases if not contains_letters(release)] + if not releases: + return None + + # Sort versions using the custom key function + sorted_releases = sorted(releases, key=version_key) + return sorted_releases[-1] + except Exception as e: + print(f"Unable to connect to pypi: {e}") + return None diff --git a/python/datafed_pkg/requirements.txt b/python/datafed_pkg/requirements.txt index 011143126..ab83b039c 100644 --- a/python/datafed_pkg/requirements.txt +++ b/python/datafed_pkg/requirements.txt @@ -1,4 +1,4 @@ -protobuf>=4.21.1 +protobuf>=5.27.1 pyzmq>=16 wget>=3 requests>=2 diff --git a/repository/CMakeLists.txt b/repository/CMakeLists.txt index 7d8b33822..e133344d7 100644 --- a/repository/CMakeLists.txt +++ b/repository/CMakeLists.txt @@ -9,4 +9,3 @@ endif() if( BUILD_AUTHZ ) add_subdirectory( gridftp ) endif() -#add_subdirectory( filesys EXCLUDE_FROM_ALL ) diff --git a/repository/docker/Dockerfile.gcs b/repository/docker/Dockerfile.gcs index 563026bd2..09d2ee4cf 100644 --- a/repository/docker/Dockerfile.gcs +++ b/repository/docker/Dockerfile.gcs @@ -66,10 +66,7 @@ COPY ./scripts/install_authz_dependencies.sh ${BUILD_DIR}/scripts/ COPY ./scripts/copy_dependency.sh ${BUILD_DIR}/scripts/ RUN ${BUILD_DIR}/scripts/generate_datafed.sh -RUN DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC ${BUILD_DIR}/scripts/install_authz_dependencies.sh unify - -# All files should be owned by the datafed user -RUN chown -R datafed:root ${DATAFED_DIR} +RUN DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC ${BUILD_DIR}/scripts/install_authz_dependencies.sh COPY --chown=datafed:root ./scripts/dependency_versions.sh ${BUILD_DIR}/scripts/ COPY --chown=datafed:root ./scripts/generate_authz_config.sh ${BUILD_DIR}/scripts/generate_authz_config.sh @@ -127,6 +124,7 @@ RUN ${BUILD_DIR}/scripts/generate_gsi-authz_config.sh RUN ${BUILD_DIR}/scripts/generate_authz_config.sh && \ ${DATAFED_DEPENDENCIES_INSTALL_PATH}/bin/cmake -S. -B build \ -DBUILD_REPO_SERVER=False \ + -DBUILD_AUTHZ_TESTS=True \ -DBUILD_AUTHZ=True \ -DBUILD_AUTHZ_WITH_SYSLOG=False \ -DBUILD_CORE_SERVER=False \ diff --git a/repository/docker/entrypoint_authz.sh b/repository/docker/entrypoint_authz.sh index d6bd79e7d..f26be0c33 100755 --- a/repository/docker/entrypoint_authz.sh +++ b/repository/docker/entrypoint_authz.sh @@ -69,6 +69,9 @@ fi if [ -n "$UID" ]; then echo "Switching datafed user to UID: ${UID}" usermod -u $UID datafed + # All files should be owned by the datafed user + chown -R datafed:root ${DATAFED_DIR} + chown -R datafed:root ${DATAFED_INSTALL_PATH}/authz fi if [ ! -f "${DATAFED_INSTALL_PATH}/keys/datafed-core-key.pub" ] @@ -200,6 +203,8 @@ fi su -m -c "${BUILD_DIR}/scripts/globus/setup_globus.sh" datafed source "${DATAFED_PYTHON_ENV}/bin/activate" +source "${BUILD_DIR}/scripts/dependency_versions.sh" + # Must be passed in directly GCS_CLI_ENDPOINT_ID="$GCS_CLI_ENDPOINT_ID" \ DATAFED_GCS_COLLECTION_BASE_PATH="$DATAFED_GCS_COLLECTION_BASE_PATH" \ @@ -207,7 +212,7 @@ DATAFED_GCS_URL="$DATAFED_GCS_URL" \ GCS_CLI_CLIENT_ID="$GCS_CLI_CLIENT_ID" \ GCS_CLI_CLIENT_SECRET="$GCS_CLI_CLIENT_SECRET" \ DATAFED_REPO_USER="$DATAFED_REPO_USER" \ - python3 "${BUILD_DIR}/scripts/globus/create_guest_collection.py" + "python${DATAFED_PYTHON_VERSION}" "${BUILD_DIR}/scripts/globus/create_guest_collection.py" "${BUILD_DIR}/scripts/globus/generate_repo_form.sh" -j -s diff --git a/repository/gridftp/globus5/authz/CMakeLists.txt b/repository/gridftp/globus5/authz/CMakeLists.txt index 668592821..97a3cd35e 100644 --- a/repository/gridftp/globus5/authz/CMakeLists.txt +++ b/repository/gridftp/globus5/authz/CMakeLists.txt @@ -1 +1,6 @@ add_subdirectory( source ) + +if( BUILD_AUTHZ_TESTS ) + add_subdirectory( mock_core ) + add_subdirectory( tests ) +endif() diff --git a/repository/gridftp/globus5/authz/mock_core/AuthMap.cpp b/repository/gridftp/globus5/authz/mock_core/AuthMap.cpp new file mode 100644 index 000000000..826f10a63 --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/AuthMap.cpp @@ -0,0 +1,272 @@ + +// Local private includes +#include "AuthMap.hpp" +#include "MockGlobals.hpp" +#include "common/TraceException.hpp" + +using namespace std; + +namespace SDMS { + +namespace MockCore { +AuthMap::AuthMap(const AuthMap &auth_map) + : m_trans_active_increment(auth_map.m_trans_active_increment), + m_session_active_increment(auth_map.m_session_active_increment) { + + auth_map.m_trans_clients_mtx.lock(); + m_trans_auth_clients = auth_map.m_trans_auth_clients; + auth_map.m_trans_clients_mtx.unlock(); + + auth_map.m_session_clients_mtx.lock(); + m_session_auth_clients = auth_map.m_session_auth_clients; + auth_map.m_session_clients_mtx.unlock(); + + auth_map.m_persistent_clients_mtx.lock(); + m_persistent_auth_clients = auth_map.m_persistent_auth_clients; + auth_map.m_persistent_clients_mtx.unlock(); +} + +AuthMap &AuthMap::operator=(const AuthMap &&auth_map) { + + m_trans_active_increment = auth_map.m_trans_active_increment; + m_session_active_increment = auth_map.m_session_active_increment; + + auth_map.m_trans_clients_mtx.lock(); + const auto trans = auth_map.m_trans_auth_clients; + auth_map.m_trans_clients_mtx.unlock(); + + m_trans_clients_mtx.lock(); + m_trans_auth_clients = trans; + m_trans_clients_mtx.unlock(); + + auth_map.m_session_clients_mtx.lock(); + const auto session = auth_map.m_session_auth_clients; + auth_map.m_session_clients_mtx.unlock(); + + m_session_clients_mtx.lock(); + m_session_auth_clients = session; + m_session_clients_mtx.unlock(); + + auth_map.m_persistent_clients_mtx.lock(); + const auto persistent = auth_map.m_persistent_auth_clients; + auth_map.m_persistent_clients_mtx.unlock(); + + m_persistent_clients_mtx.lock(); + m_persistent_auth_clients = persistent; + m_persistent_clients_mtx.unlock(); + + return *this; +} + +std::vector +AuthMap::getExpiredKeys(const PublicKeyType pub_key_type, + const time_t threshold) const noexcept { + + auto expiredKeys = [=](const AuthMap::client_map_t &client_map, + const time_t expire_time) -> std::vector { + std::vector expired_keys; + for (const auto &element : client_map) { + if (element.second.expiration_time >= expire_time) { + expired_keys.push_back(element.first); + } + } + return expired_keys; + }; + + if (PublicKeyType::TRANSIENT == pub_key_type) { + lock_guard lock(m_trans_clients_mtx); + return expiredKeys(m_trans_auth_clients, threshold); + } else if (PublicKeyType::SESSION == pub_key_type) { + lock_guard lock(m_session_clients_mtx); + return expiredKeys(m_session_auth_clients, threshold); + } + return std::vector(); +} + +void AuthMap::removeKey(const PublicKeyType pub_key_type, + const std::string &pub_key) { + + if (PublicKeyType::TRANSIENT == pub_key_type) { + lock_guard lock(m_trans_clients_mtx); + if (m_trans_auth_clients.count(pub_key)) { + m_trans_auth_clients.erase(pub_key); + } + } else if (PublicKeyType::SESSION == pub_key_type) { + lock_guard lock(m_session_clients_mtx); + if (m_session_auth_clients.count(pub_key)) { + m_session_auth_clients.erase(pub_key); + } + } else { + EXCEPT(1, "Unsupported PublicKey Type during execution of removeKey."); + } +} + +void AuthMap::resetKey(const PublicKeyType pub_key_type, + const std::string &public_key) { + if (pub_key_type == PublicKeyType::TRANSIENT) { + lock_guard lock(m_trans_clients_mtx); + if (m_trans_auth_clients.count(public_key)) { + m_trans_auth_clients[public_key].expiration_time = + time(0) + m_trans_active_increment; + m_trans_auth_clients[public_key].access_count = 0; + } else { + EXCEPT(1, "Missing public key cannot reset transient expiration."); + } + } else if (pub_key_type == PublicKeyType::SESSION) { + lock_guard lock(m_session_clients_mtx); + if (m_session_auth_clients.count(public_key)) { + m_session_auth_clients[public_key].expiration_time = + time(0) + m_session_active_increment; + m_session_auth_clients[public_key].access_count = 0; + } else { + EXCEPT(1, "Missing public key cannot reset session expiration."); + } + } else { + EXCEPT(1, "Unsupported PublicKey Type during execution of addKey."); + } +} + +void AuthMap::addKey(const PublicKeyType pub_key_type, + const std::string &public_key, const std::string &id) { + if (pub_key_type == PublicKeyType::TRANSIENT) { + lock_guard lock(m_trans_clients_mtx); + AuthElement element = {id, time(0) + m_trans_active_increment, 0}; + m_trans_auth_clients[public_key] = element; + } else if (pub_key_type == PublicKeyType::SESSION) { + lock_guard lock(m_session_clients_mtx); + AuthElement element = {id, time(0) + m_session_active_increment, 0}; + m_session_auth_clients[public_key] = element; + } else if (pub_key_type == PublicKeyType::PERSISTENT) { + lock_guard lock(m_persistent_clients_mtx); + m_persistent_auth_clients[public_key] = id; + } else { + EXCEPT(1, "Unsupported PublicKey Type during execution of addKey."); + } +} + +size_t AuthMap::size(const PublicKeyType pub_key_type) const { + if (pub_key_type == PublicKeyType::TRANSIENT) { + lock_guard lock(m_trans_clients_mtx); + return m_trans_auth_clients.size(); + } else if (pub_key_type == PublicKeyType::SESSION) { + lock_guard lock(m_session_clients_mtx); + return m_session_auth_clients.size(); + } else { + // Don't support size of persistent keys + EXCEPT(1, "Unsupported PublicKey Type during execution of size."); + } +} + +void AuthMap::incrementKeyAccessCounter(const PublicKeyType pub_key_type, + const std::string &public_key) { + if (pub_key_type == PublicKeyType::TRANSIENT) { + lock_guard lock(m_trans_clients_mtx); + if (m_trans_auth_clients.count(public_key)) { + m_trans_auth_clients.at(public_key).access_count++; + } + } else if (pub_key_type == PublicKeyType::SESSION) { + lock_guard lock(m_session_clients_mtx); + if (m_session_auth_clients.count(public_key)) { + m_session_auth_clients.at(public_key).access_count++; + } + } +} + +bool AuthMap::hasKey(const PublicKeyType pub_key_type, + const std::string &public_key) const { + + if (pub_key_type == PublicKeyType::TRANSIENT) { + lock_guard lock(m_trans_clients_mtx); + if (m_trans_auth_clients.count(public_key)) { + return true; + } + } else if (pub_key_type == PublicKeyType::SESSION) { + lock_guard lock(m_session_clients_mtx); + if (m_session_auth_clients.count(public_key)) + return true; + } else if (pub_key_type == PublicKeyType::PERSISTENT) { + // Check to see if it is a repository key + if (m_persistent_auth_clients.count(public_key)) + return true; + + if (public_key.compare(MockGlobals::pub_repo_key) == 0) { + return true; + } else { + return false; + } + EXCEPT( + 1, + "Probably need to put something here for the mock to work. key is: " + + public_key); + } else { + EXCEPT(1, "Unrecognized PublicKey Type during execution of hasKey."); + } + return false; +} + +std::string AuthMap::getUID(const PublicKeyType pub_key_type, + const std::string &public_key) const { + if (pub_key_type == PublicKeyType::TRANSIENT) { + lock_guard lock(m_trans_clients_mtx); + if (m_trans_auth_clients.count(public_key)) { + return m_trans_auth_clients.at(public_key).uid; + } else { + EXCEPT(1, "Missing transient public key unable to map to uid."); + } + + } else if (pub_key_type == PublicKeyType::SESSION) { + lock_guard lock(m_session_clients_mtx); + if (m_session_auth_clients.count(public_key)) { + return m_session_auth_clients.at(public_key).uid; + } else { + EXCEPT(1, "Missing session public key unable to map to uid."); + } + + } else if (pub_key_type == PublicKeyType::PERSISTENT) { + // If it is a repository key get it + if (m_persistent_auth_clients.count(public_key)) { + return m_persistent_auth_clients.at(public_key); + } + + if (public_key.compare(MockGlobals::pub_repo_key) == 0) { + return "repo/"; + } + EXCEPT(1, "Missing persistent public key unable to map to user id or " + "repo id. Possibly, cannot connect to database."); + } + EXCEPT(1, "Unrecognized PublicKey Type during execution of getId."); +} + +bool AuthMap::hasKeyType(const PublicKeyType pub_key_type, + const std::string &public_key) const { + if (pub_key_type == PublicKeyType::TRANSIENT) { + lock_guard lock(m_trans_clients_mtx); + return m_trans_auth_clients.count(public_key); + } else if (pub_key_type == PublicKeyType::SESSION) { + lock_guard lock(m_session_clients_mtx); + return m_session_auth_clients.count(public_key); + } else { + EXCEPT(1, "Unsupported PublicKey Type during execution of hasKeyType."); + } +} + +size_t AuthMap::getAccessCount(const PublicKeyType pub_key_type, + const std::string &public_key) const { + if (pub_key_type == PublicKeyType::TRANSIENT) { + lock_guard lock(m_trans_clients_mtx); + if (m_trans_auth_clients.count(public_key)) { + return m_trans_auth_clients.at(public_key).access_count; + } + } else if (pub_key_type == PublicKeyType::SESSION) { + lock_guard lock(m_session_clients_mtx); + if (m_session_auth_clients.count(public_key)) { + return m_session_auth_clients.at(public_key).access_count; + } + } else { + EXCEPT(1, "Unsupported PublicKey Type during execution of hasKeyType."); + } + return 0; +} + +} // namespace MockCore +} // namespace SDMS diff --git a/repository/gridftp/globus5/authz/mock_core/AuthMap.hpp b/repository/gridftp/globus5/authz/mock_core/AuthMap.hpp new file mode 100644 index 000000000..7ebbeb4b4 --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/AuthMap.hpp @@ -0,0 +1,146 @@ +#ifndef IDENTITYMAP_HPP +#define IDENTITYMAP_HPP +#pragma once + +// Local includes +#include "PublicKeyTypes.hpp" + +// Local common includes +#include "common/IAuthenticationManager.hpp" + +// Standard includes +#include +#include +#include +#include + +namespace SDMS { +namespace MockCore { + +class AuthMap { +public: + struct AuthElement { + std::string uid = ""; + time_t expiration_time = 0; + size_t access_count = 0; + }; + + typedef std::map client_map_t; + typedef std::map persistent_client_map_t; + +private: + time_t m_trans_active_increment = 0; + time_t m_session_active_increment = 0; + + mutable std::mutex + m_trans_clients_mtx; ///< Mutex for transient client data access + mutable std::mutex + m_session_clients_mtx; ///< Mutex for session client data access + mutable std::mutex + m_persistent_clients_mtx; ///< Mutex for persistent client data access + + client_map_t m_trans_auth_clients; ///< Map of transient authenticated clients + client_map_t m_session_auth_clients; ///< Map of session authenticated clients + persistent_client_map_t + m_persistent_auth_clients; ///< Map of known persistent authenticated + ///< clients + +public: + AuthMap(){}; + + AuthMap(time_t trans_active_inc, time_t session_active_inc) + : m_trans_active_increment(trans_active_inc), + m_session_active_increment(session_active_inc){}; + + AuthMap(const AuthMap &); + + AuthMap &operator=(const AuthMap &&); + /*********************************************************************************** + * Getters + ***********************************************************************************/ + + /** + * Determines if the key has the specified type + * + * There are 3 supported types: + * 1. TRANSIENT + * 2. SESSION + * 3. PERSISTENT + * + * Will return true if the public key does have the type, if the type is a + *user persistent type it will return true if it can verify with the database, + *if the database in unreachable it will return false. + **/ + bool hasKeyType(const PublicKeyType pub_key_type, + const std::string &public_key) const; + + /** + * Will grab all the public keys that have expired. + **/ + std::vector + getExpiredKeys(const PublicKeyType pub_key_type, + const time_t threshold) const noexcept; + + /** + * Return how many times the key has been accessed since the count was last + *reset. + **/ + size_t getAccessCount(const PublicKeyType pub_key_type, + const std::string &public_key) const; + + /** + * Will return the users Unique ID if it exists, will throw an error if it + *does not exist. Best to call hasKey first. + **/ + std::string getUID(const PublicKeyType pub_key_type, + const std::string &public_key) const; + + /** + * Will return the number of keys of the provided type. Does not currently + *support the Persistent keys + **/ + size_t size(const PublicKeyType pub_key_type) const; + + bool hasKey(const PublicKeyType pub_key_type, + const std::string &public_key) const; + + /*********************************************************************************** + * Manipulators + ***********************************************************************************/ + + /** + * Increase the recorded times the the public key has been accessed by one. + **/ + void incrementKeyAccessCounter(const PublicKeyType pub_key_type, + const std::string &public_key); + + /** + * Adds the key to the AuthMap object + * + * Example + * + * ```c++ + * AuthMap auth_map(30,60*60, "https://db_/api_/sdms/..blah", "henry", "42"); + * auth_map.addKey(PublicKeyType::TRANSIENT, "243djgq349j08xd24393#", + *"u/henry"); + * ``` + **/ + void addKey(const PublicKeyType pub_key_type, const std::string &public_key, + const std::string &id); + + void removeKey(const PublicKeyType pub_key_type, + const std::string &public_key); + + /** + * Will reset the access counter of the key to 0 and the allowed expiration + *time of the key.. + * + * Persistent keys are not supported with this function. + **/ + void resetKey(const PublicKeyType pub_key_type, + const std::string &public_key); +}; + +} // namespace MockCore +} // namespace SDMS +#endif // IDENTITYMAP diff --git a/repository/gridftp/globus5/authz/mock_core/AuthenticationManager.cpp b/repository/gridftp/globus5/authz/mock_core/AuthenticationManager.cpp new file mode 100644 index 000000000..1574881e1 --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/AuthenticationManager.cpp @@ -0,0 +1,112 @@ + +// Local include +#include "AuthenticationManager.hpp" + +// Common includes +#include "common/TraceException.hpp" + +// Standard includes +#include + +namespace SDMS { +namespace MockCore { + +AuthenticationManager::AuthenticationManager( + std::map purge_intervals, + std::map>> + &&purge_conditions) + : m_purge_interval(purge_intervals), + m_purge_conditions(std::move(purge_conditions)) { + m_auth_mapper = std::move(AuthMap(m_purge_interval[PublicKeyType::TRANSIENT], + m_purge_interval[PublicKeyType::SESSION])); + + for (const auto &purge_int : m_purge_interval) { + m_next_purge[purge_int.first] = time(0) + purge_int.second; + } +} + +AuthenticationManager & +AuthenticationManager::operator=(AuthenticationManager &&other) { + // Only need to lock the mutex moving from + if (this != &other) { + std::lock_guard lock(other.m_lock); + m_next_purge = other.m_next_purge; + m_purge_interval = other.m_purge_interval; + m_purge_conditions = std::move(other.m_purge_conditions); + } + return *this; +} + +void AuthenticationManager::purge() { + purge(PublicKeyType::TRANSIENT); + purge(PublicKeyType::SESSION); +} + +void AuthenticationManager::purge(const PublicKeyType pub_key_type) { + + std::lock_guard lock(m_lock); + if (m_auth_mapper.size(pub_key_type)) { + const time_t now = time(0); + if (now >= m_next_purge[pub_key_type]) { + const std::vector expired_keys = + m_auth_mapper.getExpiredKeys(pub_key_type, now); + for (const auto &pub_key : expired_keys) { + if (m_purge_conditions[pub_key_type].size()) { + for (std::unique_ptr &condition : + m_purge_conditions[pub_key_type]) { + condition->enforce(m_auth_mapper, pub_key); + } + } else { + m_auth_mapper.removeKey(pub_key_type, pub_key); + } + } + m_next_purge[pub_key_type] = now + m_purge_interval[pub_key_type]; + } + } +} + +void AuthenticationManager::incrementKeyAccessCounter( + const std::string &public_key) { + std::lock_guard lock(m_lock); + if (m_auth_mapper.hasKey(PublicKeyType::TRANSIENT, public_key)) { + m_auth_mapper.incrementKeyAccessCounter(PublicKeyType::TRANSIENT, + public_key); + } else if (m_auth_mapper.hasKey(PublicKeyType::SESSION, public_key)) { + m_auth_mapper.incrementKeyAccessCounter(PublicKeyType::SESSION, public_key); + } + // Ignore persistent cases because counter does nothing for them +} + +bool AuthenticationManager::hasKey(const std::string &public_key) const { + std::lock_guard lock(m_lock); + if (m_auth_mapper.hasKey(PublicKeyType::TRANSIENT, public_key)) { + return true; + } else if (m_auth_mapper.hasKey(PublicKeyType::SESSION, public_key)) { + return true; + } else if (m_auth_mapper.hasKey(PublicKeyType::PERSISTENT, public_key)) { + return true; + } + return false; +} + +std::string AuthenticationManager::getUID(const std::string &public_key) const { + std::lock_guard lock(m_lock); + + if (m_auth_mapper.hasKey(PublicKeyType::TRANSIENT, public_key)) + return m_auth_mapper.getUID(PublicKeyType::TRANSIENT, public_key); + if (m_auth_mapper.hasKey(PublicKeyType::SESSION, public_key)) + return m_auth_mapper.getUID(PublicKeyType::SESSION, public_key); + if (m_auth_mapper.hasKey(PublicKeyType::PERSISTENT, public_key)) + return m_auth_mapper.getUID(PublicKeyType::PERSISTENT, public_key); + EXCEPT(1, "Unrecognized public_key during execution of getUID."); +} + +void AuthenticationManager::addKey(const PublicKeyType &pub_key_type, + const std::string &public_key, + const std::string &uid) { + std::lock_guard lock(m_lock); + m_auth_mapper.addKey(pub_key_type, public_key, uid); +} + +} // namespace MockCore +} // namespace SDMS diff --git a/repository/gridftp/globus5/authz/mock_core/AuthenticationManager.hpp b/repository/gridftp/globus5/authz/mock_core/AuthenticationManager.hpp new file mode 100644 index 000000000..cc9b14c32 --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/AuthenticationManager.hpp @@ -0,0 +1,97 @@ + +#ifndef AUTHENTICATION_MANAGER_HPP +#define AUTHENTICATION_MANAGER_HPP +#pragma once + +// Local includes +#include "Condition.hpp" +#include "PublicKeyTypes.hpp" + +// Common includes +#include "common/IAuthenticationManager.hpp" + +// Standard includes +#include +#include +#include +#include + +namespace SDMS { +namespace MockCore { + +class AuthenticationManager : public IAuthenticationManager { +private: + // The next purge time for each type of public key + std::map m_next_purge; + // The purge interval for each type of public key + std::map m_purge_interval; + // The purge conditions for each type of public key + std::map>> + m_purge_conditions; + + AuthMap m_auth_mapper; + + mutable std::mutex m_lock; + +public: + AuthenticationManager(){}; + + AuthenticationManager &operator=(AuthenticationManager &&other); + + AuthenticationManager( + std::map purge_intervals, + std::map>> + &&purge_conditions); + /** + * Increments the number of times that the key has been accessed, this is used + *by the transient key to know when it needs to be converted to a session key. + * + * It is used by the session key to know if it has been accesses within an + *allotted purge time frame. If the count is above one then the session key + *not be purged. + **/ + virtual void incrementKeyAccessCounter(const std::string &public_key) final; + + /** + * This will purge all keys of a particular type that have expired. + * + * The session key counter will be set back to 0 if it has been used and is + *not purged. + **/ + virtual void purge(const PublicKeyType pub_key_type) final; + + /** + * Calls purge for both TRANSIENT and SESSION keys. If they need to be + * purged they are. + */ + virtual void purge() final; + + /** + * Will return true if the public key is known is associated with a user + *account. + * + * Will look at all keys: + * - TRANSIENT + * - SESSION + * - PERSISTENT + **/ + virtual bool hasKey(const std::string &pub_key) const final; + + void addKey(const PublicKeyType &pub_key_type, const std::string &public_key, + const std::string &uid); + + /** + * Will the id or throw an error + * + * Will look at all keys: + * - TRANSIENT + * - SESSION + * - PERSISTENT + **/ + virtual std::string getUID(const std::string &pub_key) const final; +}; + +} // namespace MockCore +} // namespace SDMS + +#endif // AUTHENTICATION_MANAGER diff --git a/repository/gridftp/globus5/authz/mock_core/CMakeLists.txt b/repository/gridftp/globus5/authz/mock_core/CMakeLists.txt new file mode 100644 index 000000000..d94cd1fd3 --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required (VERSION 3.17.0) + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/Version.hpp.in" + "${CMAKE_CURRENT_SOURCE_DIR}/Version.hpp" + @ONLY) + +file( GLOB Sources "*.cpp" ) +file( GLOB Main "main.cpp") +list(REMOVE_ITEM Sources files ${Main}) + +# Must be public for unit tests to import them +if(BUILD_SHARED_LIBS) + add_library( datafed-mock-core-lib SHARED ${Sources} ) + target_link_libraries( datafed-mock-core-lib PRIVATE protobuf::libprotobuf Threads::Threads + ${DATAFED_BOOST_LIBRARIES} libzmq -ldl ) +else() + add_library( datafed-mock-core-lib STATIC ${Sources} ) + target_link_libraries( datafed-mock-core-lib PRIVATE protobuf::libprotobuf Threads::Threads + "${DATAFED_BOOST_LIBRARIES}" libzmq-static + -ldl ) +endif() +target_include_directories( datafed-mock-core-lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ) +set_target_properties(datafed-mock-core-lib PROPERTIES POSITION_INDEPENDENT_CODE ON) +target_link_libraries( datafed-mock-core-lib PUBLIC common datafed-protobuf ) +add_executable( datafed-mock-core ${Main} ) +target_link_libraries( datafed-mock-core datafed-mock-core-lib ) diff --git a/repository/gridftp/globus5/authz/mock_core/ClientWorker.cpp b/repository/gridftp/globus5/authz/mock_core/ClientWorker.cpp new file mode 100644 index 000000000..07eb5945a --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/ClientWorker.cpp @@ -0,0 +1,375 @@ + +// Local DataFed includes +#include "ClientWorker.hpp" +#include "Version.hpp" + +// DataFed Common includes +#include "common/CommunicatorFactory.hpp" +#include "common/CredentialFactory.hpp" +#include "common/DynaLog.hpp" +#include "common/ProtoBufMap.hpp" +#include "common/TraceException.hpp" +#include "common/Util.hpp" +#include "common/libjson.hpp" + +// Proto files +#include "common/SDMS.pb.h" +#include "common/SDMS_Anon.pb.h" +#include "common/SDMS_Auth.pb.h" +#include "common/Version.pb.h" + +// Third party includes +#include + +// Standard includes +#include +#include + +using namespace std; + +namespace SDMS { + +using namespace SDMS::Anon; +using namespace SDMS::Auth; + +namespace MockCore { + +map ClientWorker::m_msg_handlers; + +// TODO - This should be defined in proto files +#define NOTE_MASK_MD_ERR 0x2000 + +ClientWorker::ClientWorker(IMockCoreServer &a_core, size_t a_tid, + LogContext log_context_in) + : m_config(Config::getInstance()), m_tid(a_tid), m_run(true), + m_log_context(log_context_in), + m_msg_mapper(std::unique_ptr(new ProtoBufMap)) { + setupMsgHandlers(); + LogContext log_context = m_log_context; + log_context.thread_name += + std::to_string(log_context.thread_id) + "-WorkerThread"; + log_context.thread_id = 0; + m_worker_thread = std::make_unique(&ClientWorker::workerThread, + this, log_context); +} + +ClientWorker::~ClientWorker() { + stop(); + wait(); +} + +bool ClientWorker::isRunning() const { + std::lock_guard lock(m_run_mutex); + return m_run; +} + +void ClientWorker::stop() { + std::lock_guard lock(m_run_mutex); + m_run = false; +} + +void ClientWorker::wait() { + if (m_worker_thread) { + m_worker_thread->join(); + // delete m_worker_thread; + m_worker_thread = 0; + } +} + +#define SET_MSG_HANDLER(proto_id, msg, func) \ + m_msg_handlers[m_msg_mapper->getMessageType(proto_id, #msg)] = func + +/** + * This method configures message handling by creating a map from message type + * to handler function. There are currently two protocol levels: anonymous and + * authenticated. Each is supported by a Google protobuf interface (in + * /common/proto). Most requests can be handled directly by the DB (via + * DatabaseAPI class), but some require local processing. This method maps the + * two classes of requests using the macros SET_MSG_HANDLER (for local) and + * SET_MSG_HANDLER_DB (for DB only). + */ +void ClientWorker::setupMsgHandlers() { + static std::atomic_flag lock = ATOMIC_FLAG_INIT; + + // Only perform the processing once as it affects global state in the + // messaging libraries + if (lock.test_and_set()) + return; + + try { + // Register and setup handlers for the Anonymous interface + + uint8_t proto_id = m_msg_mapper->getProtocolID( + MessageProtocol::GOOGLE_ANONONYMOUS); // REG_PROTO( SDMS::Anon ); + // Requests that require the server to take action + SET_MSG_HANDLER(proto_id, VersionRequest, + &ClientWorker::procVersionRequest); + + // Register and setup handlers for the Authenticated interface + proto_id = m_msg_mapper->getProtocolID(MessageProtocol::GOOGLE_AUTHORIZED); + SET_MSG_HANDLER(proto_id, RepoAuthzRequest, + &ClientWorker::procRepoAuthzRequest); + + } catch (TraceException &e) { + DL_ERROR(m_log_context, "exception: " << e.toString()); + throw; + } +} + +/** + * ClientWorker message handling thread. + */ +void ClientWorker::workerThread(LogContext log_context) { + + DL_DEBUG(log_context, "W" << m_tid << " thread started"); + CommunicatorFactory factory(log_context); + + const std::string client_id = "client_worker_" + std::to_string(m_tid); + auto client = [&]() { + /// Creating input parameters for constructing Communication Instance + SocketOptions socket_options; + socket_options.scheme = URIScheme::INPROC; + socket_options.class_type = SocketClassType::CLIENT; + socket_options.direction_type = SocketDirectionalityType::BIDIRECTIONAL; + socket_options.communication_type = SocketCommunicationType::ASYNCHRONOUS; + socket_options.connection_life = SocketConnectionLife::INTERMITTENT; + socket_options.connection_security = SocketConnectionSecurity::INSECURE; + socket_options.protocol_type = ProtocolType::ZQTP; + socket_options.host = "workers"; + socket_options.local_id = client_id; + + std::unordered_map cred_options; + + CredentialFactory cred_factory; + auto credentials = cred_factory.create(ProtocolType::ZQTP, cred_options); + + uint32_t timeout_on_receive = 1000; + long timeout_on_poll = 1000; + + // When creating a communication channel with a server application we need + // to locally have a client socket. So though we have specified a client + // socket we will actually be communicating with the server. + return factory.create(socket_options, *credentials, timeout_on_receive, + timeout_on_poll); + }(); + + ProtoBufMap proto_map; + uint16_t task_list_msg_type = proto_map.getMessageType(2, "TaskListRequest"); + + DL_DEBUG(log_context, "W" << m_tid << " m_run " << m_run); + + LogContext message_log_context = log_context; + while (isRunning()) { + message_log_context.correlation_id = ""; + try { + ICommunicator::Response response = + client->receive(MessageType::GOOGLE_PROTOCOL_BUFFER); + if (response.time_out == false and response.error == false) { + if (not response.message) { + DL_ERROR( + message_log_context, + "No timeout or error was reported but message is not defined.") + } + + IMessage &message = *response.message; + uint16_t msg_type = std::get( + message.get(constants::message::google::MSG_TYPE)); + message_log_context.correlation_id = std::get( + message.get(MessageAttribute::CORRELATION_ID)); + DL_DEBUG(message_log_context, "W" << m_tid << " received message: " + << proto_map.toString(msg_type)); + + const std::string uid = + std::get(message.get(MessageAttribute::ID)); + if (msg_type != task_list_msg_type) { + DL_DEBUG(message_log_context, + "W" << m_tid << " msg " << msg_type << " [" << uid << "]"); + } + + if (uid.compare("anon") == 0 && msg_type > 0x1FF) { + DL_WARNING(message_log_context, + "W" << m_tid + << " unauthorized access attempt from anon user"); + auto response_msg = m_msg_factory.createResponseEnvelope(message); + + // I know this is not great... allocating memory here slow + // This will need to be fixed + auto nack = std::make_unique(); + nack->set_err_code(ID_AUTHN_REQUIRED); + nack->set_err_msg("Authentication required"); + response_msg->setPayload(std::move(nack)); + client->send(*response_msg); + } else { + DL_DEBUG(message_log_context, + "W" << m_tid << " getting handler from map: msg_type = " + << proto_map.toString(msg_type)); + if (m_msg_handlers.count(msg_type)) { + + auto handler = m_msg_handlers.find(msg_type); + + DL_TRACE(message_log_context, + "W" << m_tid + << " calling handler/attempting to call " + "function of worker"); + + // Have to move the actual unique_ptr, change ownership not simply + // passing a reference + auto response_msg = (this->*handler->second)( + uid, std::move(response.message), message_log_context); + if (response_msg) { + // Gather msg metrics except on task lists (web clients poll) + + DL_DEBUG(message_log_context, + "W" << m_tid << " sending msg of type " + << proto_map.toString(msg_type)); + client->send(*response_msg); + DL_TRACE(message_log_context, "Message sent "); + } + } else { + DL_ERROR(message_log_context, + "W" << m_tid << " recvd unregistered msg: " << msg_type); + } + } + } + } catch (TraceException &e) { + DL_ERROR(message_log_context, "W" << m_tid << " " << e.toString()); + } catch (exception &e) { + DL_ERROR(message_log_context, "W" << m_tid << " " << e.what()); + } catch (...) { + DL_ERROR(message_log_context, "W" << m_tid << " unknown exception type"); + } + } + + DL_DEBUG(log_context, "W exiting loop"); +} + +// TODO The macros below should be replaced with templates + +/// This macro defines the begining of the common message handling code for all +/// local handlers +#define PROC_MSG_BEGIN(msgclass, replyclass, log_context) \ + msgclass *request = 0; \ + bool send_reply = true; \ + ::google::protobuf::Message *base_msg = \ + std::get(msg_request->getPayload()); \ + if (base_msg) { \ + request = dynamic_cast(base_msg); \ + if (request) { \ + DL_TRACE(log_context, "Rcvd [" << request->DebugString() << "]"); \ + std::unique_ptr reply_ptr = \ + std::make_unique(); \ + replyclass &reply = *(dynamic_cast(reply_ptr.get())); \ + try { + +/// This macro defines the end of the common message handling code for all local +/// handlers + +#define PROC_MSG_END(log_context) \ + if (send_reply) { \ + auto msg_reply = m_msg_factory.createResponseEnvelope(*msg_request); \ + msg_reply->setPayload(std::move(reply_ptr)); \ + return msg_reply; \ + } \ + } \ + catch (TraceException & e) { \ + DL_ERROR(log_context, "W" << m_tid << " " << e.toString()); \ + if (send_reply) { \ + auto msg_reply = m_msg_factory.createResponseEnvelope(*msg_request); \ + auto nack = std::make_unique(); \ + nack->set_err_code((ErrorCode)e.getErrorCode()); \ + nack->set_err_msg(e.toString(true)); \ + msg_reply->setPayload(std::move(nack)); \ + return msg_reply; \ + } \ + } \ + catch (exception & e) { \ + DL_ERROR(log_context, "W" << m_tid << " " << e.what()); \ + if (send_reply) { \ + auto msg_reply = m_msg_factory.createResponseEnvelope(*msg_request); \ + auto nack = std::make_unique(); \ + nack->set_err_code(ID_INTERNAL_ERROR); \ + nack->set_err_msg(e.what()); \ + msg_reply->setPayload(std::move(nack)); \ + return msg_reply; \ + } \ + } \ + catch (...) { \ + DL_ERROR(log_context, \ + "W" << m_tid << " unkown exception while processing message!"); \ + if (send_reply) { \ + auto msg_reply = m_msg_factory.createResponseEnvelope(*msg_request); \ + auto nack = std::make_unique(); \ + nack->set_err_code(ID_INTERNAL_ERROR); \ + nack->set_err_msg("Unknown exception type"); \ + msg_reply->setPayload(std::move(nack)); \ + return msg_reply; \ + } \ + } \ + DL_TRACE(log_context, "Sent: " << reply.DebugString()); \ + } \ + else { \ + DL_ERROR(log_context, \ + "W" << m_tid << ": dynamic cast of msg buffer failed!"); \ + } \ + } \ + else { \ + DL_ERROR(log_context, "W" << m_tid \ + << ": message parse failed (malformed or " \ + "unregistered msg type)."); \ + auto msg_reply = m_msg_factory.createResponseEnvelope(*msg_request); \ + auto nack = std::make_unique(); \ + nack->set_err_code(ID_BAD_REQUEST); \ + nack->set_err_msg( \ + "Message parse failed (malformed or unregistered msg type)"); \ + msg_reply->setPayload(std::move(nack)); \ + return msg_reply; \ + } \ + return std::unique_ptr(); + +std::unique_ptr +ClientWorker::procVersionRequest(const std::string &a_uid, + std::unique_ptr &&msg_request, + LogContext log_context) { + log_context.correlation_id = + std::get(msg_request->get(MessageAttribute::CORRELATION_ID)); + PROC_MSG_BEGIN(VersionRequest, VersionReply, log_context) + (void)a_uid; + DL_INFO(log_context, "Version request received."); + + reply.set_release_year(DATAFED_RELEASE_YEAR); + reply.set_release_month(DATAFED_RELEASE_MONTH); + reply.set_release_day(DATAFED_RELEASE_DAY); + reply.set_release_hour(DATAFED_RELEASE_HOUR); + reply.set_release_minute(DATAFED_RELEASE_MINUTE); + + reply.set_api_major(DATAFED_COMMON_PROTOCOL_API_MAJOR); + reply.set_api_minor(DATAFED_COMMON_PROTOCOL_API_MINOR); + reply.set_api_patch(DATAFED_COMMON_PROTOCOL_API_PATCH); + + reply.set_component_major(MockCore::version::MAJOR); + reply.set_component_minor(MockCore::version::MINOR); + reply.set_component_patch(MockCore::version::PATCH); + + PROC_MSG_END(log_context); +} + +std::unique_ptr +ClientWorker::procRepoAuthzRequest(const std::string &a_uid, + std::unique_ptr &&msg_request, + LogContext log_context) { + (void)a_uid; + log_context.correlation_id = + std::get(msg_request->get(MessageAttribute::CORRELATION_ID)); + PROC_MSG_BEGIN(RepoAuthzRequest, AckReply, log_context) + + DL_INFO(log_context, "AUTHZ repo request received: " + << a_uid << ", usr: " << request->client() + << ", file: " << request->file() + << ", act: " << request->action()); + + EXCEPT(1, "This function needs to be mocked before testing repo request."); + PROC_MSG_END(log_context); +} + +} // namespace MockCore +} // namespace SDMS diff --git a/repository/gridftp/globus5/authz/mock_core/ClientWorker.hpp b/repository/gridftp/globus5/authz/mock_core/ClientWorker.hpp new file mode 100644 index 000000000..147ee4bf3 --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/ClientWorker.hpp @@ -0,0 +1,89 @@ +#ifndef COREWORKER_HPP +#define COREWORKER_HPP +#pragma once + +// Local private includes +#include "Config.hpp" +#include "IMockCoreServer.hpp" + +// DataFed Common public includes +#include "common/DynaLog.hpp" +#include "common/IMessage.hpp" +#include "common/IMessageMapper.hpp" +#include "common/MessageFactory.hpp" +#include "common/Util.hpp" + +// Third party includes +#include + +// Standard includes +#include +#include +#include +#include +#include +#include + +namespace SDMS { +namespace MockCore { + +/** + * The ClientWorker class provides client message processing on a dedicated + * thread. + * + * The ClientWorker class handles client-originating messages and either + * processes requests directly or passes them on to the DB. Most requests can be + * handled by the database alone, but requests that require orchestration with + * other parts of the system are handled by the ClientWorker. + */ +class ClientWorker { +public: + /// ClientWorker constructor + ClientWorker(IMockCoreServer &a_core, size_t a_tid, LogContext log_context); + + /// ClientWorker destructor + ~ClientWorker(); + + /// Request ClientWorker to stop processing requests + void stop(); + + /// Wait for ClientWorker thread to exit after stop() + void wait(); + +private: + void setupMsgHandlers(); + void workerThread(LogContext log_context); + + // Routing functions + std::unique_ptr + procVersionRequest(const std::string &a_uid, + std::unique_ptr &&msg_request, + LogContext log_context); + + std::unique_ptr + procRepoAuthzRequest(const std::string &a_uid, + std::unique_ptr &&msg_request, + LogContext log_context); + + typedef std::unique_ptr (ClientWorker::*msg_fun_t)( + const std::string &a_uid, std::unique_ptr &&request, + LogContext log_context); + + bool isRunning() const; + + Config &m_config; ///< Ref to configuration singleton + size_t m_tid; ///< Thread ID + std::unique_ptr m_worker_thread; ///< Local thread handle + mutable std::mutex m_run_mutex; + bool m_run; ///< Thread run flag + LogContext m_log_context; + MessageFactory m_msg_factory; + std::unique_ptr m_msg_mapper; + /// Map of message type to message handler functions + static std::map m_msg_handlers; +}; + +} // namespace MockCore +} // namespace SDMS + +#endif diff --git a/repository/gridftp/globus5/authz/mock_core/Condition.cpp b/repository/gridftp/globus5/authz/mock_core/Condition.cpp new file mode 100644 index 000000000..be0c6625b --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/Condition.cpp @@ -0,0 +1,41 @@ + +// Local private includes +#include "Condition.hpp" + +// Standard includes +#include + +namespace SDMS { +namespace MockCore { + +void Promote::enforce(AuthMap &auth_map, const std::string &public_key) { + if (auth_map.hasKeyType(m_promote_from, public_key)) { + size_t access_count = auth_map.getAccessCount(m_promote_from, public_key); + if (access_count >= m_transient_to_session_count_threshold) { + // Convert transient key to session key if has been accessed more than the + // threshold + std::string uid = auth_map.getUID(m_promote_from, public_key); + auth_map.addKey(m_promote_to, public_key, uid); + } + // Remove expired short lived transient key + auth_map.removeKey(m_promote_from, public_key); + } +} + +void Reset::enforce(AuthMap &auth_map, const std::string &public_key) { + if (auth_map.hasKeyType(m_act_on_key_type, public_key)) { + size_t access_count = + auth_map.getAccessCount(m_act_on_key_type, public_key); + if (access_count >= m_access_attempts) { + // If the session key has been accessed within the threshold then reset + // the active period + auth_map.resetKey(m_act_on_key_type, public_key); + } else { + // If the key has not been used then remove it. + auth_map.removeKey(m_act_on_key_type, public_key); + } + } +} + +} // namespace MockCore +} // namespace SDMS diff --git a/repository/gridftp/globus5/authz/mock_core/Condition.hpp b/repository/gridftp/globus5/authz/mock_core/Condition.hpp new file mode 100644 index 000000000..ee4bc3a2c --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/Condition.hpp @@ -0,0 +1,64 @@ + +#ifndef CONDITION_HPP +#define CONDITION_HPP +#pragma once + +// Local includes +#include "AuthMap.hpp" +#include "PublicKeyTypes.hpp" + +// Standard includes +#include + +namespace SDMS { +namespace MockCore { + +enum class ConditionType { + PROMOTION_TO_SESSION_AND_PURGE_FROM_TRANSIENT, + RESET_IF_ACCESSED_ELSE_PURGE, +}; + +class Condition { +public: + virtual ConditionType type() const noexcept = 0; + virtual void enforce(AuthMap &auth_map, const std::string &public_key) = 0; +}; + +class Promote : public Condition { +private: + size_t m_transient_to_session_count_threshold = 0; + PublicKeyType m_promote_from; + PublicKeyType m_promote_to; + +public: + Promote(const size_t access_attempts, const PublicKeyType promote_from, + const PublicKeyType promote_to) + : m_transient_to_session_count_threshold(access_attempts), + m_promote_from(promote_from), m_promote_to(promote_to){}; + + virtual ConditionType type() const noexcept final { + return ConditionType::PROMOTION_TO_SESSION_AND_PURGE_FROM_TRANSIENT; + } + + virtual void enforce(AuthMap &auth_map, const std::string &public_key) final; +}; + +class Reset : public Condition { +private: + size_t m_access_attempts = 0; + PublicKeyType m_act_on_key_type; + +public: + Reset(const size_t access_attempts, const PublicKeyType key_type) + : m_access_attempts(access_attempts), m_act_on_key_type(key_type){}; + + virtual ConditionType type() const noexcept final { + return ConditionType::RESET_IF_ACCESSED_ELSE_PURGE; + } + + virtual void enforce(AuthMap &auth_map, const std::string &public_key) final; +}; + +} // namespace MockCore +} // namespace SDMS +#endif // CONDITION_HPP diff --git a/repository/gridftp/globus5/authz/mock_core/Config.cpp b/repository/gridftp/globus5/authz/mock_core/Config.cpp new file mode 100644 index 000000000..e1667186c --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/Config.cpp @@ -0,0 +1,47 @@ + +#define DEF_DYNALOG +// Local private includes +#include "Config.hpp" +#include "MockGlobals.hpp" + +// Local public includes +#include "common/DynaLog.hpp" + +// Standard includes +#include + +namespace SDMS { +namespace MockCore { + +// NOTE this would be better as an observer pattern using a separate object +// default public port 9998, private is assumed to be one above +// default private port = public_port + 1 +Config::Config() + : port(MockGlobals::repo_port), repo_chunk_size(100), + num_client_worker_threads(4), repo_timeout(60000) { + + RepoData r; + + r.set_id(MockGlobals::repo_id); // Required field + r.set_title(MockGlobals::repo_title); // Optional field + r.set_desc(MockGlobals::repo_desc); + r.set_capacity(MockGlobals::repo_capacity); + // The following key is a dummy key meant for testing however the public + // private key pair have to be used together for zeromq to work. Even though + // they are dummy keys for testing they are valid. + r.set_pub_key(MockGlobals::pub_repo_key); + // Address this is how the core service will communicate with the repo srevice + r.set_address(MockGlobals::repo_listen_address); + // This is just a placeholder and has no corresponding globus endpoint + // associated with it. + r.set_endpoint(MockGlobals::repo_globus_uuid); + r.set_path(MockGlobals::repo_path); + r.set_domain(""); + r.set_exp_path(""); + m_repos[r.id()] = r; +} + +std::map Config::getRepos() const { return m_repos; } + +} // namespace MockCore +} // namespace SDMS diff --git a/repository/gridftp/globus5/authz/mock_core/Config.hpp b/repository/gridftp/globus5/authz/mock_core/Config.hpp new file mode 100644 index 000000000..07523b24d --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/Config.hpp @@ -0,0 +1,52 @@ +#ifndef CONFIG_HPP +#define CONFIG_HPP +#pragma once + +// Core local private includes +#include "AuthenticationManager.hpp" + +// DataFed Common public includes +#include "common/DynaLog.hpp" +#include "common/ICredentials.hpp" +#include "common/SDMS.pb.h" + +// Standard includes +#include +#include +#include + +namespace SDMS { +namespace MockCore { + +// NOTE this would be better as an observer pattern using a separate object +// default public port 9998, private is assumed to be one above +// default private port = public_port + 1 +class Config { +public: + static Config &getInstance() { + static Config inst; + return inst; + } + +private: + Config(); + + std::map m_repos; + +public: + std::string cred_dir; + uint32_t port; + uint32_t repo_chunk_size; + uint32_t repo_timeout; + uint32_t num_client_worker_threads; + + std::map getRepos() const; + std::unique_ptr sec_ctx; + + /// Map of client key to DataFed ID +}; + +} // namespace MockCore +} // namespace SDMS + +#endif diff --git a/repository/gridftp/globus5/authz/mock_core/IMockCoreServer.hpp b/repository/gridftp/globus5/authz/mock_core/IMockCoreServer.hpp new file mode 100644 index 000000000..bb1843c81 --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/IMockCoreServer.hpp @@ -0,0 +1,25 @@ +#ifndef IMOCKCORESERVER_HPP +#define IMOCKCORESERVER_HPP +#pragma once + +// Common public libraries +#include "common/DynaLog.hpp" + +// Standard includes +#include + +namespace SDMS { +namespace MockCore { + +class IMockCoreServer { +public: + virtual void authenticateClient(const std::string &a_cert_uid, + const std::string &a_key, + const std::string &a_uid, + LogContext log_context) = 0; +}; + +} // namespace MockCore +} // namespace SDMS + +#endif diff --git a/repository/gridftp/globus5/authz/mock_core/MockCoreServer.cpp b/repository/gridftp/globus5/authz/mock_core/MockCoreServer.cpp new file mode 100644 index 000000000..3195e1676 --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/MockCoreServer.cpp @@ -0,0 +1,335 @@ +// Local private includes +#include "MockCoreServer.hpp" +#include "ClientWorker.hpp" +#include "Condition.hpp" +#include "PublicKeyTypes.hpp" + +// DataFed Common includes +#include "common/CredentialFactory.hpp" +#include "common/DynaLog.hpp" +#include "common/IServer.hpp" +#include "common/OperatorFactory.hpp" +#include "common/ServerFactory.hpp" +#include "common/SocketOptions.hpp" +#include "common/TraceException.hpp" +#include "common/Util.hpp" + +// Standard includes +#include +#include +#include +#include +#include + +#define timerDef() struct timespec _T0 = {0, 0}, _T1 = {0, 0} +#define timerStart() clock_gettime(CLOCK_REALTIME, &_T0) +#define timerStop() clock_gettime(CLOCK_REALTIME, &_T1) +#define timerElapsed() \ + ((_T1.tv_sec - _T0.tv_sec) + ((_T1.tv_nsec - _T0.tv_nsec) / 1.0e9)) + +#define MAINT_POLL_INTERVAL 5 +#define CLIENT_IDLE_TIMEOUT 3600 + +using namespace std; + +namespace SDMS { + +namespace MockCore { + +Server::Server(LogContext log_context) + : m_config(Config::getInstance()), m_log_context(log_context) { + + // Load ZMQ keys + loadKeys(m_config.cred_dir); + + // Configure ZMQ security context + CredentialFactory cred_factory; + std::unordered_map params; + params[CredentialType::PUBLIC_KEY] = m_pub_key; + params[CredentialType::PRIVATE_KEY] = m_priv_key; + m_config.sec_ctx = cred_factory.create(ProtocolType::ZQTP, params); + + std::map purge_intervals; + const time_t seconds_30 = 30; + const time_t hours_eight = 60; //*60*8; + purge_intervals[PublicKeyType::TRANSIENT] = seconds_30; + purge_intervals[PublicKeyType::SESSION] = hours_eight; + + std::map>> + purge_conditions; + + const size_t accesses_to_promote = 2; + const PublicKeyType promote_from = PublicKeyType::TRANSIENT; + const PublicKeyType promote_to = PublicKeyType::SESSION; + + purge_conditions[PublicKeyType::TRANSIENT].emplace_back( + std::make_unique(accesses_to_promote, promote_from, promote_to)); + + const size_t accesses_to_reset = 1; + const PublicKeyType key_type_to_apply_reset = PublicKeyType::SESSION; + + purge_conditions[PublicKeyType::SESSION].emplace_back( + std::make_unique(accesses_to_reset, key_type_to_apply_reset)); + + // Must occur after loading config settings + m_auth_manager = std::move( + AuthenticationManager(purge_intervals, std::move(purge_conditions))); + + for (auto &r : m_config.getRepos()) { + m_auth_manager.addKey(PublicKeyType::PERSISTENT, r.second.pub_key(), + r.second.id()); + } +} + +Server::~Server() { + // There is no way to cleanly shutdown the server, so this code really has no + // effect since the o/s cleans-up for us + + // m_zap_thread.join(); +} + +void Server::loadKeys(const std::string &a_cred_dir) { + string fname = a_cred_dir + "mock-datafed-core-key.pub"; + ifstream inf(fname.c_str()); + if (!inf.is_open() || !inf.good()) { + EXCEPT_PARAM(1, std::string("Could not open public key file: ") + fname); + } + inf >> m_pub_key; + inf.close(); + + fname = a_cred_dir + "mock-datafed-core-key.priv"; + inf.open(fname.c_str()); + if (!inf.is_open() || !inf.good()) + EXCEPT_PARAM(1, std::string("Could not open private key file: ") + fname); + inf >> m_priv_key; + inf.close(); + + std::cout << "Public key is: " << m_pub_key << std::endl; + std::cout << "Private key is: " << m_priv_key << std::endl; +} + +/** + * Start and run external interfaces. + * + * This method is no longer strictly necessary. Originally, separate + * start, run, and pause methods were implemented to allow a host program + * to control the core service, but these features were never needed or used. + * The functions performed here could be moved to the constructor; however, + * keeping them in this method allows the calling thread to run one of the + * interfaces. + */ +void Server::run() { + DL_INFO(m_log_context, "Public/private MAPI starting on ports " + << m_config.port << "/" << (m_config.port + 1)) + + m_msg_router_thread = + thread(&Server::msgRouter, this, m_log_context, getNewThreadId()); + m_io_secure_thread = + thread(&Server::ioSecure, this, m_log_context, getNewThreadId()); + + m_msg_router_thread.join(); +} + +void Server::msgRouter(LogContext log_context, int thread_count) { + log_context.thread_name += "-msgRouter"; + log_context.thread_id = thread_count; + std::unordered_map socket_options; + std::unordered_map socket_credentials; + + // Credentials are allocated on the heap, to ensure they last until the end of + // the test they must be defined outside of the scope block below + std::unique_ptr client_credentials; + + { // Proxy Client Credentials and Socket Options - these options are used + // to define the client socket that the proxy will use to communicate with + // the backend. The proxy acts like a client to the backend + SocketOptions client_socket_options; + client_socket_options.scheme = URIScheme::INPROC; + client_socket_options.class_type = SocketClassType::CLIENT; + client_socket_options.direction_type = + SocketDirectionalityType::BIDIRECTIONAL; + client_socket_options.communication_type = + SocketCommunicationType::ASYNCHRONOUS; + client_socket_options.connection_life = SocketConnectionLife::PERSISTENT; + client_socket_options.connection_security = + SocketConnectionSecurity::INSECURE; + client_socket_options.protocol_type = ProtocolType::ZQTP; + client_socket_options.host = "workers"; + client_socket_options.local_id = "core_message_routing_client"; + socket_options[SocketRole::CLIENT] = client_socket_options; + + CredentialFactory cred_factory; + std::unordered_map cred_options; + + client_credentials = cred_factory.create(ProtocolType::ZQTP, cred_options); + socket_credentials[SocketRole::CLIENT] = client_credentials.get(); + } + + // Credentials are allocated on the heap, to ensure they last until the end of + // the test they must be defined outside of the scope block below + std::unique_ptr server_credentials; + + { // Proxy Server Credentials and Socket Options - these options are used + // to define the server socket that the proxy will use to communicate with + // the frontend. The proxy acts like a server to the frontend + SocketOptions server_socket_options; + server_socket_options.scheme = URIScheme::INPROC; + server_socket_options.class_type = SocketClassType::SERVER; + server_socket_options.direction_type = + SocketDirectionalityType::BIDIRECTIONAL; + server_socket_options.communication_type = + SocketCommunicationType::ASYNCHRONOUS; + server_socket_options.connection_life = SocketConnectionLife::PERSISTENT; + server_socket_options.connection_security = + SocketConnectionSecurity::INSECURE; + server_socket_options.protocol_type = ProtocolType::ZQTP; + server_socket_options.host = "msg_proc"; + server_socket_options.local_id = "core_message_routing_server"; + socket_options[SocketRole::SERVER] = server_socket_options; + + CredentialFactory cred_factory; + + std::unordered_map cred_options; + + server_credentials = cred_factory.create(ProtocolType::ZQTP, cred_options); + socket_credentials[SocketRole::SERVER] = server_credentials.get(); + } + + ServerFactory server_factory(log_context); + auto proxy = server_factory.create(ServerType::PROXY_BASIC_ZMQ, + socket_options, socket_credentials); + + // Ceate worker threads + for (uint16_t t = 0; t < m_config.num_client_worker_threads; ++t) { + LogContext log_context_client = log_context; + log_context_client.thread_id = getNewThreadId(); + m_workers.emplace_back(new ClientWorker(*this, t + 1, log_context_client)); + } + + proxy->run(); + + // Clean-up workers + vector>::iterator iwrk; + + for (iwrk = m_workers.begin(); iwrk != m_workers.end(); ++iwrk) + (*iwrk)->stop(); +} + +int Server::getNewThreadId() { + lock_guard lock(m_thread_count_mutex); + ++m_thread_count; + return m_thread_count; +} + +void Server::ioSecure(LogContext log_context, int thread_count) { + + log_context.thread_name += "-ioSecure"; + log_context.thread_id = thread_count; + try { + + std::unordered_map socket_options; + std::unordered_map socket_credentials; + + // Credentials are allocated on the heap, to ensure they last until the end + // of the test they must be defined outside of the scope block below + std::unique_ptr client_credentials; + + { // Proxy Client Credentials and Socket Options - these options are used + // to define the client socket that the proxy will use to communicate with + // the backend. The proxy acts like a client to the backend + SocketOptions client_socket_options; + client_socket_options.scheme = URIScheme::INPROC; + client_socket_options.class_type = SocketClassType::CLIENT; + client_socket_options.direction_type = + SocketDirectionalityType::BIDIRECTIONAL; + client_socket_options.communication_type = + SocketCommunicationType::ASYNCHRONOUS; + client_socket_options.connection_life = + SocketConnectionLife::INTERMITTENT; + // Does not need to be secure, msg_proc is facing inside and is using + // INPROC + client_socket_options.connection_security = + SocketConnectionSecurity::INSECURE; + client_socket_options.protocol_type = ProtocolType::ZQTP; + client_socket_options.host = "msg_proc"; + // client_socket_options.port = 1341; + client_socket_options.local_id = "internal_facing_secure_proxy_client"; + socket_options[SocketRole::CLIENT] = client_socket_options; + + CredentialFactory cred_factory; + + std::unordered_map cred_options; + + client_credentials = + cred_factory.create(ProtocolType::ZQTP, cred_options); + socket_credentials[SocketRole::CLIENT] = client_credentials.get(); + } + + // Credentials are allocated on the heap, to ensure they last until the end + // of the test they must be defined outside of the scope block below + std::unique_ptr server_credentials; + + { // Proxy Server Credentials and Socket Options - these options are used + // to define the server socket that the proxy will use to communicate with + // the web server and repo server. The proxy acts like a server to the + // frontend + SocketOptions server_socket_options; + server_socket_options.scheme = URIScheme::TCP; + server_socket_options.class_type = SocketClassType::SERVER; + server_socket_options.direction_type = + SocketDirectionalityType::BIDIRECTIONAL; + server_socket_options.communication_type = + SocketCommunicationType::ASYNCHRONOUS; + server_socket_options.connection_life = SocketConnectionLife::PERSISTENT; + server_socket_options.connection_security = + SocketConnectionSecurity::SECURE; + server_socket_options.protocol_type = ProtocolType::ZQTP; + server_socket_options.host = "*"; + server_socket_options.port = m_config.port; + server_socket_options.local_id = "external_facing_secure_proxy_server"; + socket_options[SocketRole::SERVER] = server_socket_options; + + CredentialFactory cred_factory; + + std::unordered_map cred_options; + cred_options[CredentialType::PRIVATE_KEY] = + m_config.sec_ctx->get(CredentialType::PRIVATE_KEY); + + server_credentials = + cred_factory.create(ProtocolType::ZQTP, cred_options); + socket_credentials[SocketRole::SERVER] = server_credentials.get(); + } + + std::any argument = dynamic_cast(&m_auth_manager); + OperatorFactory operator_factory; + std::vector> operators; + operators.push_back( + operator_factory.create(OperatorType::Authenticator, argument)); + + ServerFactory server_factory(log_context); + auto proxy = + server_factory.create(ServerType::PROXY_CUSTOM, socket_options, + socket_credentials, std::move(operators)); + + proxy->run(); + + } catch (exception &e) { + DL_ERROR(log_context, "Exception in secure interface: " << e.what()) + } +} + +// Triggered by client worker +void Server::authenticateClient(const std::string &a_cert_uid, + const std::string &a_key, + const std::string &a_uid, + LogContext log_context) { + + DL_INFO(log_context, "authenticateClient a_cert_uid is " + << a_cert_uid << " a_uid is " << a_uid); + if (a_cert_uid.compare("anon") == 0) { + m_auth_manager.addKey(PublicKeyType::TRANSIENT, a_key, a_uid); + } +} + +} // namespace MockCore +} // namespace SDMS diff --git a/repository/gridftp/globus5/authz/mock_core/MockCoreServer.hpp b/repository/gridftp/globus5/authz/mock_core/MockCoreServer.hpp new file mode 100644 index 000000000..cf1f91d4b --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/MockCoreServer.hpp @@ -0,0 +1,105 @@ +#ifndef CORESERVER_HPP +#define CORESERVER_HPP +#pragma once + +// Local private includes +#include "AuthenticationManager.hpp" +#include "Config.hpp" +#include "IMockCoreServer.hpp" + +// Public common includes +#include "common/DynaLog.hpp" + +// Standard includes +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace SDMS { +namespace MockCore { + +class ClientWorker; + +/** + * The CoreServer class creates and manages all core services. + * + * The CoreServer class initializes and manages all of the worker threads of the + * core service and serves as a message router for all in-coming messages (both + * client and other distributed services). The various threads run by the + * CoreServer include client authentication, message routing, background task + * processing, and maintenance functions. + * + * Most DataFed client and server communication is based on message-passing + * using Google protobuf messages over encrypted ZeroMQ connections. The + * communication from the web client to the DataFed web service, and the + * communication between the DatabaseAPI and ArangoDB is based on JSON over + * HTTP/S. The CoreServer handles all ZeroMQ messaging and delegates the HTTP/S + * to the web server and DatabaseAPI class. + * + * There are two ZeroMQ interfaces exposed by the CoreServer at the configured + * port and port + 1. The former is a secure interface used for all non-local + * communication, and the latter is insecure for use by trusted local processes. + * Messages received from either interface are routed to the same worker threads + * for processing. + * + * The ICoreServer interface class exposes an authenticateClient method to + * client workers for manual (password) and token-based authentication. + */ +class Server : public IMockCoreServer { +public: + /// CoreServer constructor (uses Config singleton) + explicit Server(LogContext); + + /// CoreServer destructor + virtual ~Server(); + + /// Disallow instance copying + Server &operator=(const Server &) = delete; + + /// Start and run Core service interfaces. This method does not return. + void run(); + +private: + /// Used to manage purging and public auth keys + AuthenticationManager m_auth_manager; + + /** + * This method is called after a public key has been authenticated, the key is + *then made an authorized transient key. + **/ + void authenticateClient(const std::string &a_cert_uid, + const std::string &a_key, const std::string &a_uid, + LogContext log_context); + void metricsUpdateMsgCount(const std::string &a_uid, uint16_t a_msg_type); + // bool isClientAuthenticated( const std::string & a_client_key, std::string & + // a_uid ); + void loadKeys(const std::string &a_cred_dir); + void msgRouter(LogContext log_context, int thread_count); + + // Needed for communications between authz and core service + void ioSecure(LogContext log_context, int thread_count); + int getNewThreadId(); + + Config &m_config; ///< Ref to configuration singleton + std::thread m_io_secure_thread; ///< Secure I/O thread handle + std::string m_pub_key; ///< Public key for secure interface + std::string m_priv_key; ///< Private key for secure interface + std::thread m_msg_router_thread; ///< Main message router thread handle + std::mutex m_thread_count_mutex; ///< Mutex for metrics updates + std::vector> + m_workers; ///< List of ClientWorker instances + LogContext m_log_context; + int m_thread_count = 0; // Keep track of the number of threads created + int m_main_thread_id = 0; +}; + +} // namespace MockCore +} // namespace SDMS + +#endif diff --git a/repository/gridftp/globus5/authz/mock_core/MockGlobals.cpp b/repository/gridftp/globus5/authz/mock_core/MockGlobals.cpp new file mode 100644 index 000000000..89c105d9c --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/MockGlobals.cpp @@ -0,0 +1,18 @@ +#include "MockGlobals.hpp" + +namespace MockGlobals { +// These are all dummy values +const char *pub_repo_key = "Wxwm^-Cf7cJrqS)}/B?cDAq(L=@AwSA*({jhBu1]"; +// private key needed by repo is +// 1:BoDR8-#sGZuRWyP*jr+Csm-kT}zV:tn@gRDS.u +const char *repo_listen_address = "tcp://localhost:10000"; +const char *repo_id = "repo/samoas"; +const char *repo_title = "Samoas are the best girl scout cookie"; +const uint64_t repo_capacity = 100000; +const char *repo_desc = "There really is no comparison"; +const char *repo_globus_uuid = "550e8400-e29b-41d4-a716-446655440000"; +const char *repo_path = "/mnt/data/samoas"; +const uint32_t repo_port = 9998; +const char *client_uuid = "23c9067f-60e8-4741-9af1-482280faced4"; + +} // namespace MockGlobals diff --git a/repository/gridftp/globus5/authz/mock_core/MockGlobals.hpp b/repository/gridftp/globus5/authz/mock_core/MockGlobals.hpp new file mode 100644 index 000000000..e3c986f83 --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/MockGlobals.hpp @@ -0,0 +1,20 @@ +#ifndef MOCK_GLOBALS_H +#define MOCK_GLOBALS_H +#pragma once + +// Standard includes +#include + +namespace MockGlobals { +extern const char *pub_repo_key; +extern const char *repo_listen_address; +extern const char *repo_id; +extern const char *repo_title; +extern const uint64_t repo_capacity; +extern const char *repo_desc; +extern const char *repo_globus_uuid; +extern const char *client_uuid; +extern const char *repo_path; +extern const uint32_t repo_port; +} // namespace MockGlobals +#endif // MOCK_GLOBALS_H diff --git a/repository/gridftp/globus5/authz/mock_core/PublicKeyTypes.hpp b/repository/gridftp/globus5/authz/mock_core/PublicKeyTypes.hpp new file mode 100644 index 000000000..ec04326db --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/PublicKeyTypes.hpp @@ -0,0 +1,22 @@ + +#ifndef PUBLICKEYTYPES_HPP +#define PUBLICKEYTYPES_HPP +#pragma once + +// Standard includes +#include + +namespace SDMS { +namespace MockCore { + +enum class PublicKeyType { TRANSIENT, SESSION, PERSISTENT }; + +struct PublicKeyTypesClassHash { + template std::size_t operator()(T t) const { + return static_cast(t); + } +}; + +} // namespace MockCore +} // namespace SDMS +#endif // PUBLICKEYTYPES diff --git a/repository/gridftp/globus5/authz/mock_core/Version.hpp.in b/repository/gridftp/globus5/authz/mock_core/Version.hpp.in new file mode 100644 index 000000000..ccaa58d35 --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/Version.hpp.in @@ -0,0 +1,24 @@ +#ifndef CORE_VERSION_HPP +#define CORE_VERSION_HPP +#pragma once + +namespace SDMS { + namespace MockCore { + namespace version { + constexpr int MAJOR = @DATAFED_CORE_MAJOR@; + constexpr int MINOR = @DATAFED_CORE_MINOR@; + constexpr int PATCH = @DATAFED_CORE_PATCH@; + } + } + + namespace foxx_api { + namespace version { + constexpr int MAJOR = @DATAFED_FOXX_API_MAJOR@; + constexpr int MINOR = @DATAFED_FOXX_API_MINOR@; + constexpr int PATCH = @DATAFED_FOXX_API_PATCH@; + } + } +} + +#endif // CORE_VERSION_HPP + diff --git a/repository/gridftp/globus5/authz/mock_core/main.cpp b/repository/gridftp/globus5/authz/mock_core/main.cpp new file mode 100644 index 000000000..1151e7c8e --- /dev/null +++ b/repository/gridftp/globus5/authz/mock_core/main.cpp @@ -0,0 +1,187 @@ +// Local private includes +#include "MockCoreServer.hpp" + +// Local public includes +#include "common/DynaLog.hpp" +#include "common/TraceException.hpp" +#include "common/Util.hpp" + +// messaging version +#include "common/Version.pb.h" + +// Third party includes +#include + +// Standard includes +#include "Config.hpp" +#include +#include +#include +#include + +using namespace std; +using namespace SDMS; +namespace po = boost::program_options; + +void create_pid_file() { + + std::string pid_file = "./server.pid"; + std::ofstream file(pid_file); + if (!file) { + std::cerr << "Failed to create PID file: " << pid_file << std::endl; + exit(EXIT_FAILURE); + } + file << getpid(); // Write the current process ID to the file + file.close(); + std::cout << "PID file created: " << pid_file << std::endl; +} + +/** @brief Entry point for Mock Core Server + * + * Parses command line options then creates and runs a MockCoreServer instance. + */ +int main(int a_argc, char **a_argv) { + global_logger.setSysLog(false); + global_logger.addStream(std::cerr); + global_logger.setLevel(LogLevel::INFO); + LogContext log_context; + log_context.thread_name = "mock_core_server"; + log_context.thread_id = 0; + + try { + + create_pid_file(); + DL_INFO(log_context, "DataFed mock core server starting."); + + MockCore::Config &config = MockCore::Config::getInstance(); + bool gen_keys = false; + + // Note: we may want to dynamically choose type at compile time + // based on underlying type of LogLevel enum + unsigned int cfg_log_level = UINT_MAX; + + po::options_description opts("Options"); + + opts.add_options()("help,?", "Show help")( + "cred-dir,c", po::value(&config.cred_dir), + "Server credentials directory, will look for files " + "mock-datafed-core.priv and mock-datafed-core.pub.")( + "port,p", po::value(&config.port), + "Service port, this is the public port core service is listening on " + "for mock set to 9998, private by default is public_port + 1")( + "gen-keys", po::bool_switch(&gen_keys), + "Generate new server keys then exit")( + "log-level", po::value(&cfg_log_level), "Set log level"); + + try { + po::variables_map opt_map; + po::store(po::command_line_parser(a_argc, a_argv).options(opts).run(), + opt_map); + po::notify(opt_map); + + if (opt_map.count("help")) { + cout << "Usage: mock-datafed-core [options]\n"; + cout << opts << endl; + return 0; + } + + if (gen_keys) { + string pub_key, priv_key; + generateKeys(pub_key, priv_key); + + string fname = "./mock-datafed-core-key.pub"; + ofstream outf(fname.c_str()); + if (!outf.is_open() || !outf.good()) + EXCEPT_PARAM(1, "Could not open file: " << fname); + outf << pub_key; + outf.close(); + + fname = "./mock-datafed-core-key.priv"; + outf.open(fname.c_str()); + if (!outf.is_open() || !outf.good()) + EXCEPT_PARAM(1, "Could not open file: " << fname); + outf << priv_key; + outf.close(); + + return 0; + } + if (cfg_log_level != UINT_MAX) { + if (cfg_log_level >= + static_cast(LogLevel::LAST_SENTINEL)) { + DL_ERROR(log_context, + "Invalid log level provided, defaulting to INFO"); + } else { + LogLevel cast_log_level = static_cast(cfg_log_level); + std::string str_log_level = ""; + switch (cast_log_level) { + case LogLevel::CRITICAL: + str_log_level = "CRITICAL"; + break; + case LogLevel::ERROR: + str_log_level = "ERROR"; + break; + case LogLevel::WARNING: + str_log_level = "WARNING"; + break; + case LogLevel::INFO: + str_log_level = "INFO"; + break; + case LogLevel::DEBUG: + str_log_level = "DEBUG"; + break; + case LogLevel::TRACE: + str_log_level = "TRACE"; + break; + case LogLevel::LAST_SENTINEL: + str_log_level = "INVALID"; // should never be reached + EXCEPT_PARAM(1, "Unexpected state when setting log level, " + + to_string(cfg_log_level)); + break; + } + std::string log_message = "Setting log level to " + str_log_level; + DL_INFO(log_context, log_message); + global_logger.setLevel(cast_log_level); + } + } + } catch (po::unknown_option &e) { + DL_ERROR(log_context, "Options error: " << e.what()); + return 1; + } + + // Create and run CoreServer instance. Configuration is held in Config + // singleton + std::cout << std::endl; + std::cout << "Config cred_dir: " << config.cred_dir << std::endl; + std::cout << "Config port: " << std::to_string(config.port) << std::endl; + std::cout << "Config repo_chunk_size: " + << std::to_string(config.repo_chunk_size) << std::endl; + std::cout << "Config num_client_worker_threads: " + << std::to_string(config.num_client_worker_threads) << std::endl; + std::cout << std::endl; + auto repos = config.getRepos(); + std::cout << "Mocked Repos" << std::endl; + for (const auto &repo : repos) { + std::cout << "Repo Id: " << repo.second.id() << std::endl; + std::cout << "title: " << repo.second.title() << std::endl; + std::cout << "desc: " << repo.second.desc() << std::endl; + std::cout << "capacity: " << std::to_string(repo.second.capacity()) + << std::endl; + std::cout << "address: " << repo.second.address() << std::endl; + std::cout << "endpoint: " << repo.second.endpoint() << std::endl; + std::cout << "path: " << repo.second.path() << std::endl; + std::cout << "domain: " << repo.second.domain() << std::endl; + std::cout << "exp_path: " << repo.second.exp_path() << std::endl; + std::cout << std::endl; + } + + MockCore::Server server(log_context); + server.run(); + + } catch (TraceException &e) { + DL_ERROR(log_context, "Exception: " << e.toString()); + } catch (exception &e) { + DL_ERROR(log_context, "Exception: " << e.what()); + } + + return 0; +} diff --git a/repository/gridftp/globus5/authz/source/AuthzLog.c b/repository/gridftp/globus5/authz/source/AuthzLog.c new file mode 100644 index 000000000..1bf8b2dd1 --- /dev/null +++ b/repository/gridftp/globus5/authz/source/AuthzLog.c @@ -0,0 +1,7 @@ +// Standard includes +#include +#include + +// Define the global variables +FILE *log_file = NULL; +bool write_to_file = false; diff --git a/repository/gridftp/globus5/authz/source/AuthzLog.h b/repository/gridftp/globus5/authz/source/AuthzLog.h new file mode 100644 index 000000000..68d4a482a --- /dev/null +++ b/repository/gridftp/globus5/authz/source/AuthzLog.h @@ -0,0 +1,80 @@ + +#ifndef AUTHZ_LOG_H +#define AUTHZ_LOG_H + +// Private includes +#include "AuthzWorker.h" + +// Standard includes +#include +#include +#include +#include + +// Define LOG_LEVEL and USE_SYSLOG +#define LOG_LEVEL 1 + +#ifndef DONT_USE_SYSLOG +#define DONT_USE_SYSLOG +#endif + +// Define logging macros +#if defined(DONT_USE_SYSLOG) +extern FILE *log_file; +extern bool write_to_file; +#define AUTHZ_LOG_DEBUG(fmt, ...) \ + do { \ + if (LOG_LEVEL <= 1) \ + fprintf(stderr, "[DEBUG] " fmt "", ##__VA_ARGS__); \ + } while (0); \ + do { \ + if (LOG_LEVEL <= 1 && write_to_file) \ + fprintf(log_file, "[DEBUG] " fmt "", ##__VA_ARGS__); \ + } while (0) +#define AUTHZ_LOG_INFO(fmt, ...) \ + do { \ + if (LOG_LEVEL <= 2) \ + fprintf(stderr, "[INFO] " fmt "", ##__VA_ARGS__); \ + } while (0); \ + do { \ + if (LOG_LEVEL <= 2 && write_to_file) \ + fprintf(log_file, "[INFO] " fmt "", ##__VA_ARGS__); \ + } while (0) +#define AUTHZ_LOG_ERROR(fmt, ...) \ + do { \ + if (LOG_LEVEL <= 3) \ + fprintf(stderr, "[ERROR] " fmt "", ##__VA_ARGS__); \ + if (LOG_LEVEL <= 3 && write_to_file) \ + fprintf(log_file, "[ERROR] " fmt "", ##__VA_ARGS__); \ + } while (0) +#define AUTHZ_LOG_INIT(file_path) \ + log_file = fopen(file_path, "a"); \ + if (log_file != NULL) { \ + write_to_file = true; \ + } +#define AUTHZ_LOG_CLOSE() \ + if (log_file != NULL) { \ + fclose(log_file); \ + } +#else +#include +#define AUTHZ_LOG_DEBUG(fmt, ...) \ + do { \ + if (LOG_LEVEL <= 1) \ + syslog(LOG_DEBUG, "[DEBUG] " fmt, ##__VA_ARGS__); \ + } while (0) +#define AUTHZ_LOG_INFO(fmt, ...) \ + do { \ + if (LOG_LEVEL <= 2) \ + syslog(LOG_INFO, "[INFO] " fmt, ##__VA_ARGS__); \ + } while (0) +#define AUTHZ_LOG_ERROR(fmt, ...) \ + do { \ + if (LOG_LEVEL <= 3) \ + syslog(LOG_ERR, "[ERROR] " fmt, ##__VA_ARGS__); \ + } while (0) +#define AUTHZ_LOG_INIT(file_path) openlog("gsi_authz", 0, LOG_AUTH); +#define AUTHZ_LOG_CLOSE() closelog(); +#endif + +#endif // AUTHZ_LOG_H diff --git a/repository/gridftp/globus5/authz/source/AuthzWorker.cpp b/repository/gridftp/globus5/authz/source/AuthzWorker.cpp index ac3ff27ff..a51a37fc8 100644 --- a/repository/gridftp/globus5/authz/source/AuthzWorker.cpp +++ b/repository/gridftp/globus5/authz/source/AuthzWorker.cpp @@ -1,4 +1,5 @@ // Local private includes +#include "AuthzWorker.hpp" #include "Config.h" #include "Version.hpp" @@ -20,6 +21,7 @@ #include "common/Version.pb.h" // Standard includes +#include #include #include #include @@ -31,6 +33,10 @@ using namespace SDMS::Anon; using namespace SDMS::Auth; namespace { + +/** + * \brief Designed to generated a random string of characters + **/ std::string randomAlphaNumericCode() { std::string chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; @@ -48,232 +54,597 @@ std::string randomAlphaNumericCode() { namespace SDMS { -class AuthzWorker { -public: - AuthzWorker(struct Config *a_config, LogContext log_context) - : m_config(a_config), m_test_path_len(strlen(a_config->test_path)) { - - m_log_context = log_context; - m_log_context.thread_name += "-authz_worker"; - m_log_context.thread_id = 0; +static bool log_stream_added = false; + +AuthzWorker::AuthzWorker(struct Config a_config, LogContext log_context) + : m_config(a_config) { + + m_log_context = log_context; + m_log_context.thread_name += "-authz_worker"; + m_log_context.thread_id = 0; + + // Convert config item to string for easier manipulation + m_local_globus_path_root = std::string(m_config.globus_collection_path); + + m_test_path = std::string(m_config.test_path); + // NOTE the test_path MUST end with '/' this is to prevent authorization + // by accident to a subfolder i.e. + // + // /foobar + // /foo + // + // If m_test_path was meant just for the foo folder but an '/' is missing + // then both /foobar and /foo would be valid + // + // NOTE we also do not want add a '/' if the test_path is emtpy because that + // would indicate no test path is being used. + if (!m_test_path.empty() && m_test_path.back() != '/') { + m_test_path += '/'; } - ~AuthzWorker() {} + DL_DEBUG(m_log_context, "Authz init config repo_id: " << m_config.repo_id); + DL_DEBUG(m_log_context, "Authz init config server_addr: " << m_config.server_addr); + DL_DEBUG(m_log_context, "Authz init config pub_key: " << m_config.pub_key); + DL_DEBUG(m_log_context, "Authz init config priv_key: " << m_config.priv_key); + DL_DEBUG(m_log_context, "Authz init config server_key: " << m_config.server_key); + DL_DEBUG(m_log_context, "Authz init config user: " << m_config.user); + DL_DEBUG(m_log_context, "Authz init config test_path: " << m_config.test_path); + DL_DEBUG(m_log_context, "Authz init config log_path: " << m_config.log_path); + DL_DEBUG(m_log_context, "Authz init config globus_collection_path: " << m_config.globus_collection_path); + + // Add a backslash if not present + initCommunicator(); +} - AuthzWorker &operator=(const AuthzWorker &) = delete; +/** + * This method is used to initialize the communicator which will talk with + * the core services + * + * Setting up a communicator consists of several steps. + * 1. Setting up credentials that are needed to communicate securely + * 2. Creating the configuration options for how the communication should + * occur + * 3. Creating the communicator. + * + **/ +void AuthzWorker::initCommunicator() { + + m_cred_options[CredentialType::PUBLIC_KEY] = m_config.pub_key; + m_cred_options[CredentialType::PRIVATE_KEY] = m_config.priv_key; + m_cred_options[CredentialType::SERVER_KEY] = m_config.server_key; + CredentialFactory cred_factory; + m_sec_ctx = cred_factory.create(ProtocolType::ZQTP, m_cred_options); + + // Need to attach a random number to the authz_client_socket so that + // each authz client is distinct + std::string authz_thread_id; + authz_thread_id = "authz_client_socket-" + randomAlphaNumericCode(); + + m_comm = [&](const std::string &socket_id, const std::string &address, + ICredentials &credentials) { + /// Creating input parameters for constructing Communication Instance + AddressSplitter splitter(address); + + SocketOptions socket_options; + socket_options.scheme = splitter.scheme(); + socket_options.class_type = SocketClassType::CLIENT; + socket_options.direction_type = SocketDirectionalityType::BIDIRECTIONAL; + socket_options.communication_type = SocketCommunicationType::ASYNCHRONOUS; + socket_options.connection_life = SocketConnectionLife::INTERMITTENT; + socket_options.protocol_type = ProtocolType::ZQTP; + socket_options.connection_security = SocketConnectionSecurity::SECURE; + socket_options.host = splitter.host(); + socket_options.port = splitter.port(); + + DL_DEBUG(m_log_context, "Authz init socket_options host: " << socket_options.host); + DL_DEBUG(m_log_context, "Authz init socket_options port: " << socket_options.port.value()); + + if (socket_options.port.has_value()) { + if (socket_options.port.value() != 7512) { + DL_WARNING(m_log_context, + "Port number is defined for: " + << address + << " however, it is a non standard port, the standard " + "port for connecting to the core server is port " + "number 7512, whereas here you are using port: " + << socket_options.port.value()); + } + } + socket_options.local_id = socket_id; - int checkAuth(char *client_id, char *path, char *action) { - DL_DEBUG(m_log_context, "Checking auth for client: " << client_id); + uint32_t timeout_on_receive = 50000; + long timeout_on_poll = 50000; - if (m_test_path_len > 0 && - strncmp(path, m_config->test_path, m_test_path_len) == 0) { - DL_INFO(m_log_context, "Allowing request within TEST PATH: " - << m_config->test_path - << " actual path: " << path); - return 0; - } + CommunicatorFactory comm_factory(m_log_context); - // This should point to the root of the globus collection on the POSIX - // system It must be stripped from the path Expecting a path with the - // following form ftp://hostname/globus_collection_root_path + return comm_factory.create(socket_options, credentials, timeout_on_receive, + timeout_on_poll); + }(authz_thread_id, m_config.server_addr, *m_sec_ctx); +} - // Start by making sure the format is as expected +/** + * @brief Determine if the given POSIX path is within the configured test path. + * + * A test path can be set in the authorization configuration file to assist + * with debugging and setup of a DataFed-managed Globus collection. + * Any authorization associated with this path and its subpaths in the + * folder hierarchy is automatically approved. + * + * @param posix_path The POSIX-style file path to evaluate. + * @return `true` if the provided path is within the configured test path, + * `false` otherwise. + * + * @note This method uses the `m_test_path` and its length `m_test_path_len` + * to determine if the `posix_path` starts with the test path. + * If the test path is not set (`m_test_path_len == 0`), the function + * will always return `false`. + * + * @attention Use caution when setting a test path, as it bypasses normal + * authorization checks for all matching paths. + * + * Example: + * @code + * AuthzWorker authzWorker; + * std::string path = "/data/test_path/example_file"; + * if (authzWorker.isTestPath(path)) { + * std::cout << "Path is within the test path!" << std::endl; + * } else { + * std::cout << "Path is not within the test path." << std::endl; + * } + * @endcode + */ +bool AuthzWorker::isTestPath(const std::string &posix_path) const { + if (m_test_path.size() > 0 && + posix_path.compare(0, m_test_path.size(), m_test_path) == 0) { + DL_INFO(m_log_context, + "Allowing request within TEST PATH: " << m_config.test_path); + return true; + } + return false; +} - std::string scheme = "ftp://"; - // std::string local_globus_path_root = "ftp://"; - std::string local_path = path; - if (local_path.substr(0, scheme.length()).compare(scheme) != 0) { - DL_ERROR(m_log_context, "Provided path is not properly formatted, should " - "be prefixed with ftp:// but is: " - << path); - EXCEPT(1, "Format error detected in path"); - } +/** + * @brief Validates whether the provided POSIX path is properly formatted. + * + * This method checks if the given POSIX path starts with the configured + * Globus root collection path (`m_local_globus_path_root`). If the path is not + * properly formatted, an error message is logged, and the method returns + * `false`. + * + * @param posix_path The POSIX-style file path to validate. + * @return `true` if the provided path is valid (properly formatted), + * `false` otherwise. + * + * @note The validation ensures that the `posix_path` begins with the + * `m_local_globus_path_root` prefix. If the path is shorter than the + * root prefix, it is considered invalid. + * + * @attention An improperly formatted path indicates a configuration or + * user error and will result in an error log message. + * + * Example: + * @code + * AuthzWorker authzWorker; + * std::string path = "/data/globus_root/example_file"; + * if (authzWorker.isPathValid(path)) { + * std::cout << "Path is valid!" << std::endl; + * } else { + * std::cout << "Path is invalid." << std::endl; + * } + * @endcode + * + * Errors: + * - Logs an error if the path does not start with `m_local_globus_path_root`. + * - Logs an error if the path is shorter than `m_local_globus_path_root`. + */ +bool AuthzWorker::isPathValid(const std::string &posix_path) const { + if (m_local_globus_path_root.length() > posix_path.length()) { + std::string err_message = + "Provided path is not properly formatted, should be prefixed with " + "globus_root_collection_path: "; + err_message += m_local_globus_path_root + " but is: " + posix_path; + DL_ERROR(m_log_context, err_message); + return false; + } - // 2 grab substr after third backslash (and including backslash) should - // remove ftp://hostname + auto prefix = posix_path.substr(0, m_local_globus_path_root.length()); + if (prefix.compare(m_local_globus_path_root) != 0) { + std::string err_message = + "Provided path is not properly formatted, should be prefixed with " + "globus_root_collection_path: "; + err_message += m_local_globus_path_root + " but is: " + prefix; + DL_ERROR(m_log_context, err_message); + return false; + } + return true; +} - char backslash = '/'; - int count = 0; - size_t index = 0; +/** + * @brief Validates whether the provided FTP URL is properly formatted. + * + * This method checks if the given FTP URL starts with the required scheme + * (`ftp://`) and contains at least three slashes, which indicates the presence + * of a hostname after the scheme. If the URL is not properly formatted, an + * error message is logged, and the method returns `false`. + * + * @param full_ftp_url A C-style string representing the full FTP URL to + * validate. + * @return `true` if the URL is valid (properly formatted), + * `false` otherwise. + * + * @note The method performs the following checks: + * - The URL must begin with the `ftp://` scheme. + * - The URL must include at least three slashes to indicate a valid + * scheme and hostname. + * + * @attention Improperly formatted URLs result in error log messages to help + * diagnose issues. + * + * Example: + * @code + * AuthzWorker authzWorker; + * char url[] = "ftp://hostname/path/to/file"; + * if (authzWorker.isURLValid(url)) { + * std::cout << "URL is valid!" << std::endl; + * } else { + * std::cout << "URL is invalid." << std::endl; + * } + * @endcode + * + * Errors: + * - Logs an error if the URL does not start with `ftp://`. + * - Logs an error if the URL contains fewer than three slashes. + */ +bool AuthzWorker::isURLValid(char *full_ftp_url) const { + + std::string scheme = "ftp://"; + auto local_path = std::string(full_ftp_url); + if (local_path.substr(0, scheme.length()).compare(scheme) != 0) { + DL_ERROR(m_log_context, "Provided path is not properly formatted, should " + "be prefixed with ftp:// but is: " + << full_ftp_url); + return false; + } - for (size_t i = 0; i < local_path.length(); i++) { - if (local_path[i] == backslash) { - count++; - if (count == 3) { - index = i; - break; - } + int count = std::count(local_path.begin(), local_path.end(), '/'); + if (count < 3) { + DL_ERROR(m_log_context, "Provided path is not properly formatted, should " + "be prefixed with ftp://hostname but is: " + << full_ftp_url); + return false; + } + + // Make sure there are at least 8 characters + // i.e. ftp://b/ + if (local_path.length() < 8) { + DL_ERROR(m_log_context, + "Provided ftp URL is invalid, URL must have host and trailing /"); + return false; + } + + // index of character after ftp:// index 6 + size_t char_index = 6; + if (local_path.at(char_index) == '/') { + DL_ERROR(m_log_context, "Provided ftp URL is missing hostname"); + return false; + } + return true; +} + +/** + * @brief Removes the origin (ftp://hostname) from the given FTP URL. + * + * This method strips the `ftp://hostname` portion from a provided FTP URL, + * leaving only the path portion starting from the Globus collection root path. + * The URL is expected to be in the format: + * `ftp://hostname/globus_collection_root_path`. The method extracts the + * substring that follows the third occurrence of a slash (`/`), which is used + * to identify the path after the hostname. + * + * @param full_ftp_url A C-style string representing the full FTP URL, including + * the hostname and path. + * @return A string containing the remaining path after the `ftp://hostname` + * portion. + * + * @note The method assumes the URL follows the + * `ftp://hostname/globus_collection_root_path` format. If there are fewer than + * three slashes in the URL, it will return the entire string after the first + * two slashes. + * + * @attention The method does not validate the URL structure beyond checking for + * slashes, so improper formatting may result in unexpected behavior. + * + * Example: + * @code + * AuthzWorker authzWorker; + * char url[] = "ftp://hostname/globus_root_path/some/file"; + * std::string path = authzWorker.removeOrigin(url); + * std::cout << "Path after origin removed: " << path << std::endl; + * @endcode + * + * Errors: + * - Logs an error if the format does not meet the expected `ftp://hostname/` + * structure. + */ +std::string AuthzWorker::removeOrigin(char *full_ftp_url) const { + + if (isURLValid(full_ftp_url) == false) { + EXCEPT(1, "Invalid formatted ftp url."); + } + + auto local_path = std::string(full_ftp_url); + char backslash = '/'; + int count = 0; + size_t index = 0; + + for (size_t i = 0; i < local_path.length(); i++) { + if (local_path[i] == backslash) { + count++; + if (count == 3) { + index = i; + break; } } + } - if (count != 3) { - DL_ERROR(m_log_context, "Provided path is not properly formatted, should " - "be prefixed with ftp://hostname but is: " - << path); - EXCEPT(1, "Format error detected in path"); - } + // Extract the substring after the third occurrence of the character + return local_path.substr(index); +} - // extract the substring after the third occurrence of the character - local_path = local_path.substr(index); - - std::string local_globus_path_root = std::string( - m_config - ->globus_collection_path); // + - // repo_id.substr(repo_prefix.length()-1); - if (local_globus_path_root.length() > local_path.length()) { - ; - std::string err_message = - "Provided path is not properly formatted, should be prefixed with " - "globus_root_collection_path: "; - err_message += local_globus_path_root + " but is: " + path; - DL_ERROR(m_log_context, err_message); - EXCEPT(1, "Path to data item is not within the collection"); - } +/** + * @brief Retrieves the authorization path from the given FTP URL by removing + * the origin and validating the path. + * + * This method first removes the `ftp://hostname` portion from the provided FTP + * path using the `removeOrigin` method. Then, it validates the remaining path + * to ensure it is properly formatted with the expected Globus collection root + * path. If the path is invalid, an exception is thrown. Finally, it returns the + * path after the Globus collection root prefix. + * + * @param full_ftp_path A C-style string representing the full FTP URL, which + * includes the scheme, hostname, and path. + * @return A string containing the authorization path after the `ftp://hostname` + * portion and the Globus collection root path. + * + * @throws EXCEPT(1, "Invalid POSIX path.") If the path is not valid according + * to the `isPathValid` method. + * + * @note The method relies on the `removeOrigin` method to remove the + * `ftp://hostname` portion and expects the remaining path to start with a valid + * Globus collection root path. + * + * Example: + * @code + * AuthzWorker authzWorker; + * char path[] = "ftp://hostname/globus_root_path/some/file"; + * std::string authzPath = authzWorker.getAuthzPath(path); + * std::cout << "Authorization Path: " << authzPath << std::endl; + * @endcode + * + * Errors: + * - Throws an exception if the path is invalid. + */ +std::string AuthzWorker::getAuthzPath(char *full_ftp_path) { + std::string local_path = removeOrigin(full_ftp_path); + + if (isPathValid(local_path) == false) { + EXCEPT(1, "Invalid POSIX path: " + std::string(full_ftp_path) + + " local_path: " + local_path); + } - auto prefix = local_path.substr(0, local_globus_path_root.length()); - if (prefix.compare(local_globus_path_root) != 0) { - std::string err_message = - "Provided path is not properly formatted, should be prefixed with " - "globus_root_collection_path: "; - err_message += local_globus_path_root + " but is: " + path; - DL_ERROR(m_log_context, err_message); - EXCEPT(1, "Path to data item is not within the collection"); + std::string prefix = local_path.substr(0, m_local_globus_path_root.length()); + if (prefix.length() == 1) { + if (prefix.compare("/") == 0) { + return local_path; + } else { + EXCEPT(1, "Invalid POSIX path: " + std::string(full_ftp_path) + + " local_path: " + local_path + " prefix: " + prefix); } + } + return local_path.substr(prefix.length()); +} - auto sanitized_path = local_path.substr(prefix.length()); - std::unique_ptr m_sec_ctx; - - std::unordered_map cred_options; - cred_options[CredentialType::PUBLIC_KEY] = m_config->pub_key; - cred_options[CredentialType::PRIVATE_KEY] = m_config->priv_key; - cred_options[CredentialType::SERVER_KEY] = m_config->server_key; - CredentialFactory cred_factory; - m_sec_ctx = cred_factory.create(ProtocolType::ZQTP, cred_options); - - // Need to attach a random number to the authz_client_socket so that - // each authz client is distinct - std::string authz_thread_id = - "authz_client_socket-" + randomAlphaNumericCode(); - auto client = [&](const std::string &socket_id, const std::string &address, - ICredentials &credentials) { - /// Creating input parameters for constructing Communication Instance - DL_INFO(m_log_context, - "Creating client with adress to server: " << address); - AddressSplitter splitter(address); - - SocketOptions socket_options; - socket_options.scheme = splitter.scheme(); - socket_options.class_type = SocketClassType::CLIENT; - socket_options.direction_type = SocketDirectionalityType::BIDIRECTIONAL; - socket_options.communication_type = SocketCommunicationType::ASYNCHRONOUS; - socket_options.connection_life = SocketConnectionLife::INTERMITTENT; - socket_options.protocol_type = ProtocolType::ZQTP; - socket_options.connection_security = SocketConnectionSecurity::SECURE; - socket_options.host = splitter.host(); - socket_options.port = splitter.port(); - - if (socket_options.port.has_value()) { - if (socket_options.port.value() != 7512) { - DL_WARNING(m_log_context, - "Port number is defined for: " - << address - << " however, it is a non standard port, the standard " - "port for connecting to the core server is port " - "number 7512, whereas here you are using port: " - << socket_options.port.value()); - } - } - // socket_options.port = 1341; - socket_options.local_id = socket_id; - - uint32_t timeout_on_receive = 50000; - long timeout_on_poll = 50000; - - CommunicatorFactory comm_factory(m_log_context); - // When creating a communication channel with a server application we need - // to locally have a client socket. So though we have specified a client - // socket we will actually be communicating with the server. - return comm_factory.create(socket_options, credentials, - timeout_on_receive, timeout_on_poll); - }(authz_thread_id, m_config->server_addr, *m_sec_ctx); - - auto auth_req = std::make_unique(); - - auth_req->set_repo(m_config->repo_id); - auth_req->set_client(client_id); - auth_req->set_file(sanitized_path); - auth_req->set_action(action); - - MessageFactory msg_factory; - auto message = msg_factory.create(MessageType::GOOGLE_PROTOCOL_BUFFER); - message->set(MessageAttribute::KEY, - cred_options[CredentialType::PUBLIC_KEY]); - message->setPayload(std::move(auth_req)); - - client->send(*message); - LogContext log_context = m_log_context; - log_context.correlation_id = - std::get(message->get(MessageAttribute::CORRELATION_ID)); - DL_DEBUG(log_context, - "PUB KEY: " << cred_options[CredentialType::PUBLIC_KEY]); - DL_DEBUG(log_context, - "PRIV KEY: " << cred_options[CredentialType::PRIVATE_KEY]); - DL_DEBUG(log_context, - "SERV KEY: " << cred_options[CredentialType::SERVER_KEY]); - DL_DEBUG(log_context, "Sending request to core service at address." - << client->address()); - - auto response = client->receive(MessageType::GOOGLE_PROTOCOL_BUFFER); - if (response.message) { // Make sure the message exists before we try to - // access it - log_context.correlation_id = std::get( - response.message->get(MessageAttribute::CORRELATION_ID)); - } - if (response.time_out) { - std::string error_msg = - "AuthWorker.cpp Core service did not respond within timeout."; +/** + * @brief Processes the response received from the core service and handles + * different scenarios such as timeout, errors, and valid responses. + * + * This method is designed to process a response from the core service, checking + * for various conditions such as whether the response contains a message, + * whether there was a timeout, or whether an error occurred. If the response is + * valid and contains the expected payload, the method will further inspect it + * to check for a NACK reply. + * + * The method performs the following: + * - If the response contains a valid message, it extracts the correlation ID. + * - If the response has a timeout, it logs a warning with details about the + * service's address and port. + * - If an error occurs, it logs the error message. + * - If no errors or timeouts are present, it checks if the payload is a NACK + * reply. + * - If the response is a NACK, it logs a debug message. + * + * @param response A reference to an `ICommunicator::Response` object that + * contains the response data. + * @return `1` if a NACK response was received, `0` otherwise. + * + * @throws EXCEPT(1, "Core service did not respond") If the core service + * response times out. + * + * @note This method assumes that the response message and error fields are + * populated correctly before processing. + * + * Example: + * @code + * ICommunicator::Response response = communicator.getResponse(); + * int result = authzWorker.processResponse(response); + * if (result == 1) { + * std::cout << "Received NACK reply" << std::endl; + * } else { + * std::cout << "Response processed successfully" << std::endl; + * } + * @endcode + */ +int AuthzWorker::processResponse(ICommunicator::Response &response) { + if (response.message) { // Make sure the message exists before we try to + // access it + + // Prefer the correlation id of the received message than the one that + // was originally sent + m_log_context.correlation_id = std::get( + response.message->get(MessageAttribute::CORRELATION_ID)); + } + if (response.time_out) { + std::string error_msg = "AuthWorker.cpp Core service at address: "; + error_msg += m_comm->address(); + error_msg += " did not respond within timeout. "; - AddressSplitter splitter(client->address()); + AddressSplitter splitter(m_comm->address()); - if (splitter.port().value() != 7512) { + if (splitter.port().value() != 7512) { - error_msg += "Port number is defined for: " + client->address() + - " however, it is a non standard port, the standard port " - "for connecting to the core server is port number 7512, " - "whereas here you are using port: " + - std::to_string(splitter.port().value()); - } + error_msg += "Port number is defined for: " + m_comm->address() + + " however, it is a non standard port, the standard port " + "for connecting to the core server is port number 7512, " + "whereas here you are using port: " + + std::to_string(splitter.port().value()); + } - DL_WARNING(log_context, error_msg); - EXCEPT(1, "Core service did not respond"); - } else if (response.error) { - DL_ERROR(log_context, "AuthWorker.cpp there was an error when " + DL_WARNING(m_log_context, error_msg); + EXCEPT(1, error_msg); + } else if (response.error) { + // This will just log the output without throwing. + DL_ERROR(m_log_context, "AuthWorker.cpp there was an error when " "communicating with the core service: " << response.error_msg); - } else { + } else { - if (not response.message) { - DL_ERROR(log_context, "No error was reported and no time out occured " + if (not response.message) { + DL_ERROR(m_log_context, "No error was reported and no time out occured " "but message is not defined."); - } + EXCEPT(1, "This exception indicates that something is very wrong."); + } - auto payload = - std::get(response.message->getPayload()); - Anon::NackReply *nack = dynamic_cast(payload); - if (!nack) { - return 0; - } else { - DL_DEBUG(log_context, "Received NACK reply"); - } + auto payload = + std::get(response.message->getPayload()); + Anon::NackReply *nack = dynamic_cast(payload); + if (!nack) { + return 0; + } else { + DL_DEBUG(m_log_context, "Received NACK reply"); } - return 1; } + return 1; +} -private: - struct Config *m_config; - size_t m_test_path_len; - LogContext m_log_context; -}; +/** + * @brief Checks the authorization for a given client and action on a specific + * path. + * + * This method performs the following steps to check authorization: + * - Logs the client ID being checked. + * - Sanitizes the provided path using the `getAuthzPath` method. If the path is + * invalid, an exception is raised. + * - If the path is determined to be a test path, the method returns early with + * a `0`, allowing access without further checks. + * - Constructs an authorization request (`AuthzRequest`) and sets the + * repository ID, client ID, path, and action to be validated. + * - Creates a message using `MessageFactory` and sets the public key from the + * credentials options. + * - Sends the message through the communicator and waits for a response. + * - Processes the response using the `processResponse` method and returns the + * result. + * + * This method is used to ensure that the client has proper authorization to + * perform a specific action on a file or resource. It validates the action + * against the provided path and client ID, contacting the core service for + * verification. + * + * @param client_id The client ID requesting the action. + * @param path The path to the file or resource to be accessed. + * @param action The action (e.g., read, write) that the client wants to + * perform. + * @return An integer result based on the response: + * - `0` if the path is a test path or authorization is granted. + * - Non-zero value indicating the result of the authorization process (such as + * the result of the NACK check). + * + * @throws EXCEPT(1, "Invalid POSIX path.") If the path cannot be sanitized or + * is invalid. + * + * @note This method relies on the communication layer to send and receive + * messages to validate authorization and requires a configured communicator and + * credentials options. + * + * Example: + * @code + * char client_id[] = "client123"; + * char path[] = "/some/path/to/resource"; + * char action[] = "read"; + * AuthzWorker auth_worker; + * int result = auth_worker.checkAuth(client_id, path, action); + * if (result == 0) { + * std::cout << "Authorization granted or path is a test path" << std::endl; + * } else { + * std::cout << "Authorization failed or additional checks required" << + * std::endl; + * } + * @endcode + */ +int AuthzWorker::checkAuth(char *client_id, char *path, char *action) { + DL_DEBUG(m_log_context, "Checking auth for client: " << client_id); + + // An exception will be raised here if the path is invalid + std::string sanitized_path = getAuthzPath(path); + + if (isTestPath(sanitized_path)) { + return 0; + } + + auto auth_req = std::make_unique(); + + auto cpp_repo_id = std::string(m_config.repo_id); + auto cpp_client_id = std::string(client_id); + auto cpp_action = std::string(action); + + auth_req->set_repo(cpp_repo_id); + auth_req->set_client(cpp_client_id); + auth_req->set_file(sanitized_path); + auth_req->set_action(cpp_action); + + + DL_INFO(m_log_context, "Sending RepoAuthzRequest std::string client_id: " + << cpp_client_id << " path: " << sanitized_path << " action: " + << cpp_action << " repo id: " << cpp_repo_id); + + MessageFactory msg_factory; + auto message = msg_factory.create(MessageType::GOOGLE_PROTOCOL_BUFFER); + + // This needs to point to the public key of the repo not the core server. The + // core server will use this key to figure out if the repo is authorized. + message->set(MessageAttribute::KEY, + m_cred_options[CredentialType::PUBLIC_KEY]); + message->setPayload(std::move(auth_req)); + + m_log_context.correlation_id = + std::get(message->get(MessageAttribute::CORRELATION_ID)); + + ICommunicator::Response response; + + int attempt = 0; + // TODO - this needs to be configurable + int retries = 3; + do { + DL_INFO(m_log_context, "Sending RepoAuthzRequest client_id: " + << client_id << " path: " << path << " action: " + << action << " attempt: " << attempt + << " address: " << m_comm->address()); + m_comm->send(*message); + response = m_comm->receive(MessageType::GOOGLE_PROTOCOL_BUFFER); + ++attempt; + } while (response.time_out && attempt < retries); + + return processResponse(response); +} } // End namespace SDMS @@ -309,26 +680,40 @@ const char *getReleaseVersion() { // The same int checkAuthorization(char *client_id, char *object, char *action, - struct Config *config) { + struct Config config, int thread_id) { #if defined(DONT_USE_SYSLOG) SDMS::global_logger.setSysLog(false); #else SDMS::global_logger.setSysLog(true); #endif - SDMS::global_logger.setLevel(SDMS::LogLevel::INFO); + SDMS::LogContext log_context; + log_context.thread_name = "authz_check"; + log_context.thread_id = thread_id; + + SDMS::global_logger.setLevel(SDMS::LogLevel::TRACE); SDMS::global_logger.addStream(std::cerr); - auto log_path_authz = std::string(config->log_path); + // The ofstream must exist for the duration of the lifetime + std::list::iterator it; + std::ofstream log_file_worker; + auto log_path_authz = std::string(config.log_path); + bool added = false; if (log_path_authz.length() > 0) { // Append to the existing path because we don't want the C++ and C code // trying to write to the same file log_path_authz.append("_authz"); - std::ofstream log_file_worker(log_path_authz); - SDMS::global_logger.addStream(log_file_worker); + if (SDMS::log_stream_added == false) { + log_file_worker.open(log_path_authz, std::ios::app); + if (!log_file_worker.is_open()) { + DL_ERROR(log_context, "AuthzWorker open log file path failed, path: " + << log_path_authz); + } else { + it = SDMS::global_logger.addStream(log_file_worker); + SDMS::log_stream_added = true; + added = true; + } + } } - SDMS::LogContext log_context; - log_context.thread_name = "authz_check"; - log_context.thread_id = 0; DL_DEBUG(log_context, "AuthzWorker checkAuthorization " << client_id << ", " << object << ", " << action); @@ -343,6 +728,15 @@ int checkAuthorization(char *client_id, char *object, char *action, DL_ERROR(log_context, "AuthzWorker exception: " << e.what()); } + // We don't want to close it unless we can also remove it, and we want to + // leave it open until we are completely done. But because it is only defined + // in this scope we have to close and remove it. + // + if (log_file_worker.is_open() && added) { + log_file_worker.close(); + SDMS::global_logger.removeStream(it); + SDMS::log_stream_added = false; + } return result; } } diff --git a/repository/gridftp/globus5/authz/source/AuthzWorker.h b/repository/gridftp/globus5/authz/source/AuthzWorker.h index b9a8525d9..c1640c184 100644 --- a/repository/gridftp/globus5/authz/source/AuthzWorker.h +++ b/repository/gridftp/globus5/authz/source/AuthzWorker.h @@ -7,6 +7,6 @@ const char *getVersion(); const char *getAPIVersion(); const char *getReleaseVersion(); int checkAuthorization(char *client_id, char *object, char *action, - struct Config *config); + struct Config config, int thread_id); #endif diff --git a/repository/gridftp/globus5/authz/source/AuthzWorker.hpp b/repository/gridftp/globus5/authz/source/AuthzWorker.hpp new file mode 100644 index 000000000..6639eca45 --- /dev/null +++ b/repository/gridftp/globus5/authz/source/AuthzWorker.hpp @@ -0,0 +1,72 @@ +#ifndef AUTHZWORKER_HPP +#define AUTHZWORKER_HPP +#pragma once + +// Private includes +#include "Config.h" + +// Common public includes +#include "common/DynaLog.hpp" +#include "common/ICommunicator.hpp" +#include "common/ICredentials.hpp" + +// Standard includes +#include +#include + +namespace SDMS { + +/** + * @class AuthzWorker + * @brief Handles authorization checking, path validation, and FTP URL + * processing. + * + * The `AuthzWorker` class is responsible for handling authorization requests, + * validating paths, processing FTP URLs, and interacting with a core service to + * perform authorization checks. It utilizes a communicator for sending and + * receiving messages and manages security credentials to perform its + * operations. + * + * The class provides various methods for: + * - Checking the validity of paths and URLs. + * - Verifying authorization for a client on a given path with a specified + * action. + * - Removing the origin portion of an FTP URL to extract the path. + * - Processing responses from the core service to determine authorization + * success or failure. + * + * The class requires configuration and logging context for proper + * initialization. + */ +class AuthzWorker { +public: + AuthzWorker(struct Config a_config, LogContext log_context); + + ~AuthzWorker() {} + + AuthzWorker &operator=(const AuthzWorker &) = delete; + + int checkAuth(char *client_id, char *path, char *action); + + bool isTestPath(const std::string &) const; + bool isURLValid(char *full_ftp_url) const; + bool isPathValid(const std::string &posix_path) const; + std::string getAuthzPath(char *full_ftp_url); + std::string removeOrigin(char *full_ftp_url) const; + + int processResponse(ICommunicator::Response &response); + +private: + void initCommunicator(); + struct Config m_config; + std::string m_test_path; + std::string m_local_globus_path_root; + LogContext m_log_context; + + std::unique_ptr m_sec_ctx; + std::unique_ptr m_comm; + std::unordered_map m_cred_options; +}; + +} // namespace SDMS +#endif // AUTHZWORKER_HPP diff --git a/repository/gridftp/globus5/authz/source/Config.c b/repository/gridftp/globus5/authz/source/Config.c new file mode 100644 index 000000000..cc4c0ba98 --- /dev/null +++ b/repository/gridftp/globus5/authz/source/Config.c @@ -0,0 +1,543 @@ + +// Local private includes +#include "Config.h" +#include "AuthzLog.h" + +// Standard includes +#include +#include +#include +#include +#include +#include + +// IMPORTANT: The DATAFED_AUTHZ_CFG_FILE env variable must be set in the gridFTP +// service script (usually /etc/init.d/globus-gridftp-server). This variable +// points to the configuration file used for DataFed comm settings + +/****************************************************************************** + * Global Vars + ******************************************************************************/ +// Define the global configuration object +static struct Config g_config; +// Boolean value is used to control initialization of the global config +// structure false means it has not yet been initialized and true means it has +// already been initialized +static bool config_loaded = false; + +// Used to control the output of log messages and prevent initialization +// messaged from reappearing +static bool first_run = true; + +// Initialize the read-write lock for the configuration object +pthread_rwlock_t config_rwlock = PTHREAD_RWLOCK_INITIALIZER; +/****************************************************************************** + * File Scoped Vars + ******************************************************************************/ +// Config file has the following format +// +// key=value +// +// i.e. +// fruit=banana +// +// This three constants define the max char limit for key and the value +#define CONFIG_FILE_MAX_KEY_CHAR_SIZE 256 +#define CONFIG_FILE_MAX_VALUE_CHAR_SIZE 768 +// 256 + 768 = 1024 +#define CONFIG_FILE_MAX_LINE_LEN 1024 + +/****************************************************************************** + * File Scoped Functions + ******************************************************************************/ + +/** + * @brief Sets a value to a destination buffer with length checks. + * + * This function copies a source string (`a_src`) to a destination buffer + * (`a_dest`) while ensuring the length of the source string does not exceed the + * maximum allowed length + * (`a_max_len`). If the source string is empty or too long, an error is logged, + * and the function returns `true`. Otherwise, the source string is copied to + * the destination. + * + * @param a_label The label associated with the configuration value, used in + * error logs. + * @param a_dest A pointer to the destination buffer where the source string + * will be copied. + * @param a_src A pointer to the source string to be copied to the destination + * buffer. + * @param a_max_len The maximum allowable length for the destination buffer. + * + * @return `true` if an error occurred (e.g., empty source or source too long), + * `false` otherwise. + * + * @note The function uses `strncpy` to copy the source string into the + * destination buffer, ensuring that no more than `a_max_len` characters are + * copied. If the source string is longer than the allowed maximum length, an + * error is logged, and the value is not copied. + */ +bool setConfigValInternal(const char *a_label, char *a_dest, const char *a_src, + size_t a_max_len) { + + // 1 added to account for null char + size_t len = strlen(a_src) + 1; + if (len == 1) { + AUTHZ_LOG_ERROR("DataFed - '%s' value not set.\n", a_label); + return true; + } + + if (len > a_max_len) { + AUTHZ_LOG_ERROR("DataFed - '%s' value too long (max %zu).\n", a_label, + a_max_len); + return true; + } + + strncpy(a_dest, a_src, a_max_len); + + return false; +} + +/** + * @brief Loads a key from a file into a destination buffer. + * + * This function attempts to open a file specified by `a_filename` and reads the + * first line into the provided destination buffer (`a_dest`). It checks for + * errors when opening the file and reading the key. If successful, the key is + * stored in `a_dest` with any trailing carriage return or newline characters + * stripped. + * + * @param a_dest A pointer to the buffer where the key will be loaded. + * @param a_filename The name of the file from which the key is to be loaded. + * + * @return `true` if an error occurred (e.g., file couldn't be opened or read), + * `false` otherwise. + * + * @note The function removes any trailing carriage return or newline characters + * from the key string after it is read from the file. The destination buffer + * (`a_dest`) is assumed to be large enough to hold the key (up to `MAX_KEY_LEN` + * characters). + */ +bool loadKeyFile(char *a_dest, char *a_filename) { + FILE *inf = fopen(a_filename, "r"); + + if (!inf) { + AUTHZ_LOG_ERROR("DataFed - Could not open key file: %s\n", a_filename); + return true; + } + + if (!fgets(a_dest, MAX_KEY_LEN, inf)) { + AUTHZ_LOG_ERROR("DataFed - Error reading key from file: %s\n", a_filename); + fclose(inf); + return true; + } + + fclose(inf); + + // Strip trailing CR / LF + a_dest[strcspn(a_dest, "\r\n")] = 0; + + return false; +} + +// Assume write read lock is already in place +void initializeDefaults() { + g_config.timeout = 10000; + g_config.log_path[0] = '\0'; + g_config.repo_id[0] = '\0'; + g_config.server_addr[0] = '\0'; + g_config.user[0] = '\0'; + g_config.test_path[0] = '\0'; + g_config.globus_collection_path[0] = '\0'; + g_config.pub_key[0] = '\0'; + g_config.priv_key[0] = '\0'; + g_config.server_key[0] = '\0'; +} + +/** + * @brief Opens a configuration file based on an environment variable or a + * default path. + * + * This function first checks if the environment variable specified by `env_var` + * is set. If the environment variable is set, its value is used as the path to + * the configuration file. If the environment variable is not set, the function + * falls back to using the `default_path` provided. It then attempts to open the + * configuration file in read mode. If the file cannot be opened, an error is + * logged. + * + * @param env_var The name of the environment variable that holds the path to + * the configuration file. + * @param default_path The default path to the configuration file to use if the + * environment variable is not set. + * + * @return A pointer to the opened configuration file, or `NULL` if the file + * could not be opened. + * + * @note The function logs information when it decides to use the default path + * if the environment variable is not set, and logs an error if the file cannot + * be opened. + */ +FILE *openConfigFile(const char *env_var, const char *default_path) { + const char *config_path = getenv(env_var); + if (!config_path) { + config_path = default_path; + AUTHZ_LOG_INFO("Environment variable %s not set. Using default path: %s", + env_var, default_path); + } else { + AUTHZ_LOG_INFO("Loading configuration file from: %s", config_path); + } + + FILE *file = fopen(config_path, "r"); + if (!file) { + AUTHZ_LOG_ERROR("Failed to open configuration file: %s", config_path); + } + return file; +} + +/** + * @brief Validates and parses a configuration line. + * + * This function processes a single line from a configuration file. It trims any + * leading whitespace, skips empty lines or lines that are comments (starting + * with `#`), and attempts to parse a valid key-value pair in the format + * `key=value`. If the line contains a syntax error, an error message is logged + * with the line number. The key and value are extracted into the provided `key` + * and `value` buffers. + * + * @param line The configuration line to be validated and parsed. + * @param line_number The line number in the configuration file (used for error + * reporting). + * @param key A pointer to a buffer where the parsed key will be stored. + * @param value A pointer to a buffer where the parsed value will be stored. + * + * @return `true` if the line is valid or ignored (empty/comment line), `false` + * if there is a syntax error. + * + * @note The function uses `sscanf` to extract the key and value, and it ensures + * that the key is no longer than 255 characters and the value no longer than + * 767 characters. If the line is valid, the `key` and `value` buffers will be + * filled accordingly. + */ +bool validConfigLine(const char *line, int line_number, char *key, + char *value) { + // Trim leading whitespace + while (isspace(*line)) { + line++; + } + + // Skip empty lines or comments + if (*line == '\0' || *line == '#') { + return true; // Not an error; simply ignore + } + + // Parse the line for key=value + // %255[^=] → Reads up to 255 characters into key, stopping at =. + // = Matches the literal = character in the input. + // %767s Reads up to 767 non-whitespace characters into value. + if (sscanf(line, "%255[^=]=%767s", key, value) != 2) { + AUTHZ_LOG_ERROR("Syntax error in config file at line %d: %s", line_number, + line); + return false; + } + + return true; +} + +/** + * @brief Parses and processes a configuration line, setting the appropriate + * values in the global config. + * + * This function validates and parses a single line from a configuration file. + * It checks if the line is valid and contains a key-value pair, then assigns + * the value to the corresponding field in the global `g_config` structure based + * on the key. Supported keys include `repo_id`, `server_address`, `user`, + * `log_path`, `test_path`, `globus_collection_path`, `pub_key`, `priv_key`, + * `server_key`, and `timeout`. If the line is empty or a comment, it is + * ignored. If an unknown key is encountered or there is an error processing a + * key-value pair, an error message is logged. + * + * @param line The configuration line to be parsed. + * @param line_number The line number in the configuration file, used for error + * reporting. + * + * @return `false` if the line was parsed and processed successfully, `true` if + * there was an error. + * + * @note This function utilizes the `validConfigLine` function to validate and + * parse the configuration line. It uses `setConfigValInternal` to set values + * for various configuration fields, and `loadKeyFile` for loading + * public/private keys from files. If the configuration key is `timeout`, the + * value is converted from a string to an integer using `atoi`. Any unrecognized + * configuration keys will result in an error message. + * + * @note Assumes read write thread lock is in place. + */ +bool parseConfigLine(const char *line, int line_number) { + char key[CONFIG_FILE_MAX_KEY_CHAR_SIZE]; + char value[CONFIG_FILE_MAX_VALUE_CHAR_SIZE]; + if (validConfigLine(line, line_number, key, value) == false) { + return false; + } + + bool err = false; + if (strcmp(key, "repo_id") == 0) { + err = setConfigValInternal("repo_id", g_config.repo_id, value, MAX_ID_LEN); + } else if (strcmp(key, "server_address") == 0) { + err = setConfigValInternal("server_address", g_config.server_addr, value, + MAX_ADDR_LEN); + } else if (strcmp(key, "user") == 0) { + err = setConfigValInternal("user", g_config.user, value, MAX_ID_LEN); + } else if (strcmp(key, "log_path") == 0) { + err = setConfigValInternal("log_path", g_config.log_path, value, + MAX_PATH_LEN); + AUTHZ_LOG_INIT(g_config.log_path); + } else if (strcmp(key, "test_path") == 0) { + err = setConfigValInternal("test_path", g_config.test_path, value, + MAX_PATH_LEN); + } else if (strcmp(key, "globus_collection_path") == 0) { + err = setConfigValInternal("globus_collection_path", + g_config.globus_collection_path, value, + MAX_PATH_LEN); + } else if (strcmp(key, "pub_key") == 0) { + err = loadKeyFile(g_config.pub_key, value); + } else if (strcmp(key, "priv_key") == 0) { + err = loadKeyFile(g_config.priv_key, value); + } else if (strcmp(key, "server_key") == 0) { + err = loadKeyFile(g_config.server_key, value); + } else if (strcmp(key, "timeout") == 0) { + g_config.timeout = atoi(value); + } else if (*line == '\0' || *line == '#') { + // Ignore line + return false; + } else { + AUTHZ_LOG_ERROR("Unknown configuration key: %s", key); + return true; + } + + if (err) { + AUTHZ_LOG_ERROR("Error processing key: %s at line %d", key, line_number); + return err; + } + + return err; +} + +/** + * @brief Validates that all required configuration fields are set. + * + * This function checks if all the necessary fields in the global `g_config` + * structure are populated. The required fields are `repo_id`, `server_addr`, + * `user`, `pub_key`, `priv_key`, and `server_key`. If any of these fields are + * missing (i.e., contain empty strings), an error message is logged listing the + * missing keys. If all required fields are present, the function returns + * `true`. + * + * @return `true` if all required configuration fields are present and valid, + * `false` otherwise. + * + * @note The missing configuration keys, if any, are logged in an error message. + * The check is performed by looking at the first character of each key in the + * `g_config` structure, and if it is a null character (`\0`), the field is + * considered missing. + * + * @note Assumes read write thread lock is in place. + */ +bool validateConfig() { + char missing[CONFIG_FILE_MAX_LINE_LEN]; + missing[0] = '\0'; + + if (g_config.repo_id[0] == '\0') { + strcat(missing, " repo_id"); + } + if (g_config.server_addr[0] == '\0') { + strcat(missing, " server_address"); + } + if (g_config.user[0] == '\0') { + strcat(missing, " user"); + } + if (g_config.pub_key[0] == '\0') { + strcat(missing, " pub_key"); + } + if (g_config.priv_key[0] == '\0') { + strcat(missing, " priv_key"); + } + if (g_config.server_key[0] == '\0') { + strcat(missing, " server_key"); + } + + if (missing[0] != '\0') { + AUTHZ_LOG_ERROR("Missing required configuration keys:%s", missing); + return false; + } + + return true; +} + +/** + * Will print the version information first go around.. + * + * @note Assumes you have a thread lock in play + **/ +void logRelease() { + if (first_run) { + AUTHZ_LOG_INFO("DataFed Authz module started, version %s\n", getVersion()); + AUTHZ_LOG_INFO(" API, version %s\n", + getAPIVersion()); + AUTHZ_LOG_INFO(" Release, version %s\n", + getReleaseVersion()); + first_run = false; + } +} + +/****************************************************************************** + * Public Facing Functions + ******************************************************************************/ + +void allowConfigReinitialization() { + pthread_rwlock_wrlock(&config_rwlock); + config_loaded = false; + pthread_rwlock_unlock(&config_rwlock); +} + +struct Config createLocalConfigCopy() { + pthread_rwlock_rdlock(&config_rwlock); + struct Config temp = g_config; + pthread_rwlock_unlock(&config_rwlock); + return temp; +} + +// Function to safely get a configuration value +bool getConfigVal(const char *a_label, char *a_dest, size_t a_max_len) { + + // Acquire a read lock (allow concurrent reads) + pthread_rwlock_rdlock(&config_rwlock); + + bool err = false; + // Logic to get specific configuration value + if (strcmp(a_label, "repo_id") == 0) { + strncpy(a_dest, g_config.repo_id, a_max_len); + } else if (strcmp(a_label, "server_addr") == 0) { + strncpy(a_dest, g_config.server_addr, a_max_len); + } else if (strcmp(a_label, "pub_key") == 0) { + strncpy(a_dest, g_config.pub_key, a_max_len); + } else if (strcmp(a_label, "priv_key") == 0) { + strncpy(a_dest, g_config.priv_key, a_max_len); + } else if (strcmp(a_label, "server_key") == 0) { + strncpy(a_dest, g_config.server_key, a_max_len); + } else if (strcmp(a_label, "user") == 0) { + strncpy(a_dest, g_config.user, a_max_len); + } else if (strcmp(a_label, "test_path") == 0) { + strncpy(a_dest, g_config.test_path, a_max_len); + } else if (strcmp(a_label, "log_path") == 0) { + strncpy(a_dest, g_config.log_path, a_max_len); + } else if (strcmp(a_label, "globus_collection_path") == 0) { + strncpy(a_dest, g_config.globus_collection_path, a_max_len); + } else { + err = true; + // Make it clear nothing was found + a_dest[0] = '\0'; + } + + // Release the read lock + pthread_rwlock_unlock(&config_rwlock); + return err; +} + +// Function to safely set a configuration value +bool setConfigVal(const char *a_label, const char *a_src) { + + // Acquire a write lock (only one writer, no concurrent readers) + pthread_rwlock_wrlock(&config_rwlock); + + bool err = false; + // Logic to set specific configuration value + if (strcmp(a_label, "repo_id") == 0) { + err = setConfigValInternal(a_label, g_config.repo_id, a_src, MAX_ID_LEN); + } else if (strcmp(a_label, "server_addr") == 0) { + err = setConfigValInternal(a_label, g_config.server_addr, a_src, + MAX_ADDR_LEN); + } else if (strcmp(a_label, "pub_key") == 0) { + err = setConfigValInternal(a_label, g_config.pub_key, a_src, MAX_KEY_LEN); + } else if (strcmp(a_label, "priv_key") == 0) { + err = setConfigValInternal(a_label, g_config.priv_key, a_src, MAX_KEY_LEN); + } else if (strcmp(a_label, "server_key") == 0) { + err = + setConfigValInternal(a_label, g_config.server_key, a_src, MAX_KEY_LEN); + } else if (strcmp(a_label, "user") == 0) { + err = setConfigValInternal(a_label, g_config.user, a_src, MAX_ID_LEN); + } else if (strcmp(a_label, "test_path") == 0) { + err = + setConfigValInternal(a_label, g_config.test_path, a_src, MAX_PATH_LEN); + } else if (strcmp(a_label, "log_path") == 0) { + err = setConfigValInternal(a_label, g_config.log_path, a_src, MAX_PATH_LEN); + } else if (strcmp(a_label, "globus_collection_path") == 0) { + err = setConfigValInternal(a_label, g_config.globus_collection_path, a_src, + MAX_PATH_LEN); + } else { + err = true; + } + + // Release the write lock + pthread_rwlock_unlock(&config_rwlock); + return err; +} + +bool parseConfigFile(FILE *config_file) { + char line[CONFIG_FILE_MAX_LINE_LEN]; + line[0] = '\0'; + int line_number = 0; + bool parse_success = true; + while (fgets(line, sizeof(line), config_file)) { + line_number++; + line[strcspn(line, "\r\n")] = '\0'; // Remove newlines + if (strlen(line) == 0 || line[0] == '#') + continue; // Skip comments/empty lines + + if (parseConfigLine(line, line_number)) { + AUTHZ_LOG_ERROR("Configuration file parsing failed line: %s.", line); + parse_success = false; + break; + } + } + return parse_success; +} + +bool initializeGlobalConfig() { + bool error_found = true; + // Acquire a write lock to modify configuration values + pthread_rwlock_wrlock(&config_rwlock); + + // Initialized only at start + if (config_loaded) { + AUTHZ_LOG_INFO("Config file already loaded. Skipping reload.\n"); + error_found = false; + logRelease(); + } else { + + // Moving default initialization outside of the while loop prevents + // overwriting + initializeDefaults(); + + FILE *config_file = openConfigFile("DATAFED_AUTHZ_CFG_FILE", + "/opt/datafed/authz/datafed-authz.cfg"); + if (config_file) { + + bool parse_success = parseConfigFile(config_file); + + fclose(config_file); + + if (parse_success && validateConfig()) { + AUTHZ_LOG_INFO("Configuration loaded successfully."); + error_found = false; + } else { + AUTHZ_LOG_ERROR("Configuration validation failed."); + } + + // Avoid trying to reload + config_loaded = true; + } + logRelease(); + } + pthread_rwlock_unlock(&config_rwlock); + return error_found; +} diff --git a/repository/gridftp/globus5/authz/source/Config.h b/repository/gridftp/globus5/authz/source/Config.h index 3fae04617..80a94d08b 100644 --- a/repository/gridftp/globus5/authz/source/Config.h +++ b/repository/gridftp/globus5/authz/source/Config.h @@ -7,6 +7,7 @@ #define MAX_KEY_LEN 100 // Standard includes +#include #include struct Config { @@ -22,4 +23,111 @@ struct Config { size_t timeout; }; +/** + * @brief Initializes the global configuration by loading settings from a + * configuration file. + * + * This function acquires a write lock to safely initialize the global + * configuration. It first checks if the configuration has already been loaded, + * skipping the reload if it has. If not, it proceeds to load default values and + * then attempts to load values from the configuration file. The function + * validates the configuration after loading the file and logs the results. + * + * @return `false` if the configuration was successfully loaded and validated, + * or `true` if an error occurred (e.g., file read failure, parsing error, + * validation failure). + * + * @note The function uses a write lock (`config_rwlock`) to ensure exclusive + * access to the global configuration during the initialization process. It + * ensures that the configuration is only loaded once, even if multiple threads + * attempt to initialize it. + * + * @note The DATAFED_AUTHZ_CFG_FILE env variable must be set in the gridFTP + * service script (usually /etc/init.d/globus-gridftp-server). This variable + * points to the configuration file used for DataFed communcation settings + */ +bool initializeGlobalConfig(); + +/** + * @brief Allows reinitialization of the global configuration by resetting the + * `config_loaded` flag. + * + * This function acquires a write lock to ensure exclusive access to the global + * configuration state. It resets the `config_loaded` flag to `false`, which + * indicates that the configuration can be reloaded. After resetting the flag, + * the write lock is released. This function is useful when you need to reload + * the configuration after it has already been loaded once. + * + * @note The function uses a write lock (`config_rwlock`) to ensure exclusive + * access to the global configuration while modifying the `config_loaded` flag. + * This prevents any readers or writers from accessing the configuration while + * it is being updated. + */ +void allowConfigReinitialization(); + +/** + * @brief Retrieves a configuration value based on the provided label. + * + * This function acquires a read lock to safely access the global configuration + * and retrieve the value associated with the specified label. If the label + * matches one of the known configuration keys (e.g., `repo_id`, `server_addr`, + * `user`, etc.), the corresponding value is copied into the `a_dest` buffer, + * ensuring that it does not exceed the provided maximum length (`a_max_len`). + * The lock is then released after the operation. + * + * @param a_label The configuration key (label) for which the value is + * requested. + * @param a_dest A buffer where the configuration value will be copied. + * @param a_max_len The maximum length of the buffer `a_dest`. + * + * @return `true` if the configuration value was successfully retrieved, or + * `false` if the label does not match any known configuration keys. + * + * @note The function uses a read-write lock (`config_rwlock`) to ensure + * thread-safety when reading the global configuration. If the requested label + * does not match any known keys, the destination buffer is cleared and `true` + * is returned to indicate no value was found. + */ +bool getConfigVal(const char *a_label, char *a_dest, size_t a_max_len); + +/** + * @brief Sets a configuration value based on the provided label. + * + * This function acquires a write lock to safely modify the global + * configuration. It checks the provided label against known configuration keys + * and updates the corresponding value if a match is found. The new value is + * copied from the `a_src` argument into the appropriate configuration field, + * ensuring that the length does not exceed the maximum size for that field. + * + * @param a_label The configuration key (label) for which the value is being + * set. + * @param a_src The new value to set for the specified configuration key. + * + * @return `true` if the configuration value was successfully set, or `false` if + * the label does not match any known configuration keys or an error occurred + * during the process. + * + * @note The function uses a write lock (`config_rwlock`) to ensure exclusive + * access to the global configuration while the update is being made. Only one + * writer can modify the configuration at a time, and no readers are allowed + * during this operation. + */ +bool setConfigVal(const char *a_label, const char *a_src); + +/** + * @brief Creates a local copy of the global configuration. + * + * This function acquires a read lock to safely access the global `g_config` + * structure, copies its contents into a temporary `Config` structure, and then + * releases the lock. The local copy of the configuration is returned to the + * caller. This ensures thread-safety when accessing the global configuration. + * + * @return A copy of the current global configuration stored in a `Config` + * structure. + * + * @note The function uses a read-write lock (`config_rwlock`) to ensure that + * the global configuration is not modified while it is being copied. + */ +struct Config createLocalConfigCopy(); + #endif diff --git a/repository/gridftp/globus5/authz/source/Util.c b/repository/gridftp/globus5/authz/source/Util.c new file mode 100644 index 000000000..cfa89b19f --- /dev/null +++ b/repository/gridftp/globus5/authz/source/Util.c @@ -0,0 +1,88 @@ +// Private local includes +#include "Util.h" + +// Standard includes +#include +#include +#include +#include +#include +#include + +void uuidToStr(unsigned char *a_uuid, char *a_out) { + static const char *hex = + "0123456789abcdef"; ///< Lookup table for hexadecimal digits. + static const char *form = + "xxxx-xx-xx-xx-xxxxxx"; ///< Format template for UUID sections. + + unsigned char *pend = + a_uuid + 16; ///< Pointer to the end of the input UUID array. + char *pout = a_out; ///< Pointer to the current position in the output string. + const char *f = + form + 1; ///< Pointer to the current position in the format template. + + for (unsigned char *pin = a_uuid; pin != pend; pout += 2, pin++, f++) { + // Convert the high and low nibbles of the current byte to hexadecimal + // characters. + pout[0] = hex[(*pin >> 4) & 0xF]; + pout[1] = hex[*pin & 0xF]; + + // If the format template specifies a hyphen, add it to the output. + if (*f == '-') { + pout[2] = '-'; + pout++; + f++; + } + } + + // Append a null terminator to the output string. + pout[0] = 0; +} + +bool decodeUUID(const char *a_input, char *a_uuid) { + static char vocab[33] = "abcdefghijklmnopqrstuvwxyz234567"; + uint64_t word; + const char *iter; + const char *end = vocab + 32; + size_t len = strlen(a_input); + char c; + unsigned long v; + unsigned char out[16]; + unsigned char *outp = out; + size_t out_len = 0; + size_t i, j; + if (len == 0) { + return false; + } + + for (i = 0; i < len; i += 8) { + word = 0; + for (j = 0; j < 8; ++j) { + if (i + j < len) { + c = a_input[i + j]; + for (iter = vocab; iter != end; ++iter) { + if (*iter == c) { + v = (iter - vocab); + break; + } + } + + if (iter == end) + return false; + + word <<= 5; + word |= v; + } else { + word <<= 5 * (8 - j); + break; + } + } + + for (j = 0; j < 5 && out_len < 16; ++j, ++out_len) + *outp++ = ((word >> ((4 - j) * 8)) & 0xFF); + } + + uuidToStr(out, a_uuid); + + return true; +} diff --git a/repository/gridftp/globus5/authz/source/Util.h b/repository/gridftp/globus5/authz/source/Util.h new file mode 100644 index 000000000..4a4642aa6 --- /dev/null +++ b/repository/gridftp/globus5/authz/source/Util.h @@ -0,0 +1,57 @@ + +#ifndef UTIL_H +#define UTIL_H +// Standard includes +#include + +/** + * @brief Converts a 16-byte UUID into a canonical string representation. + * + * This function takes a 16-byte binary UUID and converts it into a standard + * UUID string format (e.g., "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"), where + * each 'x' represents a hexadecimal digit and the hyphens separate the UUID + * sections as per the canonical format. + * + * @param[in] a_uuid Pointer to an array containing 16 bytes of the UUID in + * binary format. + * @param[out] a_out Pointer to a pre-allocated character array to hold the + * resulting string. This array must have at least 37 bytes of space to store + * the 36-character UUID string plus the null terminator. + * + * The function processes the input UUID byte by byte, converting each byte into + * its hexadecimal representation and placing it into the output string. It + * inserts hyphens at specific positions to separate the UUID sections. Finally, + * it appends a null terminator to ensure the output is a valid C string. + */ +void uuidToStr(unsigned char *a_uuid, char *a_out); + +/** + * @brief Decodes a Base32-encoded string into a UUID string. + * + * This function decodes a Base32-like encoded string using a custom vocabulary + * and converts it into a 16-byte binary UUID format. The result is then + * converted to the canonical UUID string format. + * + * @param[in] a_input The Base32-encoded input string to decode. + * @param[out] a_uuid A pre-allocated buffer for the decoded UUID string in + * canonical format (36 characters + null terminator). + * The buffer must have a size of at least 37 bytes. + * @return true if the input string is valid and decoding succeeds; false + * otherwise. + * + * @note The input string must be a multiple of 8 characters for proper + * decoding. + * + * Example usage: + * @code + * char uuid[37]; + * if (decodeUUID("abcd1234efgh5678ijklmnopqrstu345", uuid)) { + * printf("Decoded UUID: %s\n", uuid); + * } else { + * printf("Invalid input.\n"); + * } + * @endcode + */ +bool decodeUUID(const char *a_input, char *a_uuid); + +#endif // UTIL_H diff --git a/repository/gridftp/globus5/authz/source/libauthz.c b/repository/gridftp/globus5/authz/source/libauthz.c index 629d64178..4fd74579e 100644 --- a/repository/gridftp/globus5/authz/source/libauthz.c +++ b/repository/gridftp/globus5/authz/source/libauthz.c @@ -1,10 +1,13 @@ // Local private includes +#include "AuthzLog.h" #include "AuthzWorker.h" #include "Config.h" +#include "Util.h" // Globus third party includes #include +#include #include #include @@ -15,72 +18,6 @@ #include #include -// Define LOG_LEVEL and USE_SYSLOG -#define LOG_LEVEL 1 - -#ifndef DONT_USE_SYSLOG -#define DONT_USE_SYSLOG -#endif - -// Define logging macros -#if defined(DONT_USE_SYSLOG) -FILE *log_file = NULL; -bool write_to_file = false; -#define AUTHZ_LOG_DEBUG(fmt, ...) \ - do { \ - if (LOG_LEVEL <= 1) \ - fprintf(stderr, "[DEBUG] " fmt "", ##__VA_ARGS__); \ - } while (0); \ - do { \ - if (LOG_LEVEL <= 1 && write_to_file) \ - fprintf(log_file, "[DEBUG] " fmt "", ##__VA_ARGS__); \ - } while (0) -#define AUTHZ_LOG_INFO(fmt, ...) \ - do { \ - if (LOG_LEVEL <= 2) \ - fprintf(stderr, "[INFO] " fmt "", ##__VA_ARGS__); \ - } while (0); \ - do { \ - if (LOG_LEVEL <= 2 && write_to_file) \ - fprintf(log_file, "[INFO] " fmt "", ##__VA_ARGS__); \ - } while (0) -#define AUTHZ_LOG_ERROR(fmt, ...) \ - do { \ - if (LOG_LEVEL <= 3) \ - fprintf(stderr, "[ERROR] " fmt "", ##__VA_ARGS__); \ - if (LOG_LEVEL <= 3 && write_to_file) \ - fprintf(log_file, "[ERROR] " fmt "", ##__VA_ARGS__); \ - } while (0) -#define AUTHZ_LOG_INIT(file_path) \ - log_file = fopen(file_path, "a"); \ - if (log_file != NULL) { \ - write_to_file = true; \ - } -#define AUTHZ_LOG_CLOSE() \ - if (log_file != NULL) { \ - fclose(log_file); \ - } -#else -#include -#define AUTHZ_LOG_DEBUG(fmt, ...) \ - do { \ - if (LOG_LEVEL <= 1) \ - syslog(LOG_DEBUG, "[DEBUG] " fmt, ##__VA_ARGS__); \ - } while (0) -#define AUTHZ_LOG_INFO(fmt, ...) \ - do { \ - if (LOG_LEVEL <= 2) \ - syslog(LOG_INFO, "[INFO] " fmt, ##__VA_ARGS__); \ - } while (0) -#define AUTHZ_LOG_ERROR(fmt, ...) \ - do { \ - if (LOG_LEVEL <= 3) \ - syslog(LOG_ERR, "[ERROR] " fmt, ##__VA_ARGS__); \ - } while (0) -#define AUTHZ_LOG_INIT(file_path) openlog("gsi_authz", 0, LOG_AUTH); -#define AUTHZ_LOG_CLOSE() closelog(); -#endif - typedef void *globus_gsi_authz_handle_t; typedef void (*globus_gsi_authz_cb_t)(void *callback_arg, globus_gsi_authz_handle_t handle, @@ -93,9 +30,6 @@ bool clearContext(globus_gsi_authz_handle_t a_handle); // TODO This value must be pulled from server config (max concurrency) #define MAX_ACTIVE_CTX 25 -void uuidToStr(unsigned char *a_uuid, char *a_out); -bool decodeUUID(const char *a_input, char *a_uuid); - struct ContextHandleEntry { globus_gsi_authz_handle_t handle; gss_ctx_id_t context; @@ -103,71 +37,6 @@ struct ContextHandleEntry { static struct ContextHandleEntry g_active_contexts[MAX_ACTIVE_CTX]; -void uuidToStr(unsigned char *a_uuid, char *a_out) { - static const char *hex = "0123456789abcdef"; - static const char *form = "xxxx-xx-xx-xx-xxxxxx"; - unsigned char *pend = a_uuid + 16; - char *pout = a_out; - const char *f = form + 1; - - for (unsigned char *pin = a_uuid; pin != pend; pout += 2, pin++, f++) { - pout[0] = hex[(*pin >> 4) & 0xF]; - pout[1] = hex[*pin & 0xF]; - if (*f == '-') { - pout[2] = '-'; - pout++; - f++; - } - } - - pout[0] = 0; -} - -bool decodeUUID(const char *a_input, char *a_uuid) { - static char vocab[33] = "abcdefghijklmnopqrstuvwxyz234567"; - uint64_t word; - const char *iter; - const char *end = vocab + 32; - size_t len = strlen(a_input); - char c; - unsigned long v; - unsigned char out[16]; - unsigned char *outp = out; - size_t out_len = 0; - size_t i, j; - - for (i = 0; i < len; i += 8) { - word = 0; - for (j = 0; j < 8; ++j) { - if (i + j < len) { - c = a_input[i + j]; - for (iter = vocab; iter != end; ++iter) { - if (*iter == c) { - v = (iter - vocab); - break; - } - } - - if (iter == end) - return false; - - word <<= 5; - word |= v; - } else { - word <<= 5 * (8 - j); - break; - } - } - - for (j = 0; j < 5 && out_len < 16; ++j, ++out_len) - *outp++ = ((word >> ((4 - j) * 8)) & 0xFF); - } - - uuidToStr(out, a_uuid); - - return true; -} - gss_ctx_id_t findContext(globus_gsi_authz_handle_t a_handle) { struct ContextHandleEntry *c = &g_active_contexts[0]; struct ContextHandleEntry *e = c + MAX_ACTIVE_CTX; @@ -206,203 +75,15 @@ bool clearContext(globus_gsi_authz_handle_t a_handle) { return true; } -// IMPORTANT: The DATAFED_AUTHZ_CFG_FILE env variable must be set in the gridFTP -// service script (usually /etc/init.d/globus-gridftp-server). This variable -// points to the configuration file used for DataFed comm settings -static struct Config g_config; - -bool setConfigVal(const char *a_label, char *a_dest, char *a_src, - size_t a_max_len) { - size_t len = strlen(a_src); - - if (len == 0) { - AUTHZ_LOG_ERROR("DataFed - '%s' value not set.\n", a_label); - return true; - } - - if (len > a_max_len) { - AUTHZ_LOG_ERROR( - "DataFed - '%s' value too long in authz config file (max %zu).\n", - a_label, a_max_len); - return true; - } - - strcpy(a_dest, a_src); - - return false; -} - -bool loadKeyFile(char *a_dest, char *a_filename) { - FILE *inf = fopen(a_filename, "r"); - - if (!inf) { - AUTHZ_LOG_ERROR("DataFed - Could not open key file: %s\n", a_filename); - return true; - } - - if (!fgets(a_dest, MAX_KEY_LEN, inf)) { - AUTHZ_LOG_ERROR("DataFed - Error reading key from file: %s\n", a_filename); - fclose(inf); - return true; - } - - fclose(inf); - - // Strip trailing CR / LF - a_dest[strcspn(a_dest, "\r\n")] = 0; - - return false; -} - -bool loadConfig() { - memset(&g_config, 0, sizeof(struct Config)); - - const char *cfg_file = getenv("DATAFED_AUTHZ_CFG_FILE"); - - FILE *inf; - if (!cfg_file) { - // If env variable is not set check default location - inf = fopen("/opt/datafed/authz/datafed-authz.cfg", "r"); - if (!inf) { - AUTHZ_LOG_ERROR("DataFed - DATAFED_AUTHZ_CFG_FILE env variable not set, " - "and datafed-authz.cfg is not located in default " - "location /opt/datafed/authz\n"); - return true; - } - } else { - AUTHZ_LOG_INFO("DataFed - Loading authz config file: %s\n", cfg_file); - inf = fopen(cfg_file, "r"); - } - if (inf) { - size_t MAX_BUF = 1024; - char buf[MAX_BUF]; - int lc = -1; - char *val; - bool err; - - while (1) { - lc++; - - // Stop at EOF - if (!fgets(buf, MAX_BUF, inf)) - break; - - buf[strcspn(buf, "\r\n")] = 0; - - // Skip comments and blank lines - if (strlen(buf) == 0 || buf[0] == '#') - continue; - - // Content is formatted as "key=value" (no spaces) - val = strchr(buf, '='); - if (!val) { - AUTHZ_LOG_ERROR( - "DataFed - Syntax error in authz config file at line %i.\n", lc); - return true; - } else { - *val = 0; - val++; - } - - // Default values - g_config.timeout = 10000; - g_config.log_path[0] = '\0'; - - if (strcmp(buf, "repo_id") == 0) - err = setConfigVal("repo_id", g_config.repo_id, val, MAX_ID_LEN); - else if (strcmp(buf, "server_address") == 0) - err = setConfigVal("server_address", g_config.server_addr, val, - MAX_ADDR_LEN); - else if (strcmp(buf, "user") == 0) - err = setConfigVal("user", g_config.user, val, MAX_ID_LEN); - else if (strcmp(buf, "log_path") == 0) { - err = setConfigVal("log_path", g_config.log_path, val, MAX_PATH_LEN); - AUTHZ_LOG_INIT(g_config.log_path); - } else if (strcmp(buf, "test_path") == 0) - err = setConfigVal("test_path", g_config.test_path, val, MAX_PATH_LEN); - else if (strcmp(buf, "globus-collection-path") == 0) - err = setConfigVal("globus-collection-path", - g_config.globus_collection_path, val, MAX_PATH_LEN); - else if (strcmp(buf, "pub_key") == 0) - err = loadKeyFile(g_config.pub_key, val); - else if (strcmp(buf, "priv_key") == 0) - err = loadKeyFile(g_config.priv_key, val); - else if (strcmp(buf, "server_key") == 0) - err = loadKeyFile(g_config.server_key, val); - else if (strcmp(buf, "timeout") == 0) - g_config.timeout = atoi(val); - else { - err = true; - AUTHZ_LOG_ERROR( - "DataFed - Invalid key, '%s', in authz config file at line %i.\n", - buf, lc); - } - - if (err) { - fclose(inf); - return true; - } - } - - fclose(inf); - - char miss[1024]; - miss[0] = 0; - - if (g_config.user[0] == 0) - strcat(miss, " user"); - if (g_config.repo_id[0] == 0) - strcat(miss, " repo_id"); - if (g_config.server_addr[0] == 0) - strcat(miss, " server_address"); - if (g_config.pub_key[0] == 0) - strcat(miss, " pub_key"); - if (g_config.globus_collection_path[0] == 0) - strcat(miss, " globus-collection-path"); - if (g_config.priv_key[0] == 0) - strcat(miss, " priv_key"); - if (g_config.server_key[0] == 0) - strcat(miss, " server_key"); - - AUTHZ_LOG_INFO("DataFed Authz module started, version %s\n", getVersion()); - AUTHZ_LOG_INFO(" API, version %s\n", - getAPIVersion()); - AUTHZ_LOG_INFO(" Release, version %s\n", - getReleaseVersion()); - - if (miss[0] != 0) { - AUTHZ_LOG_ERROR("DataFed - Missing required authz config items:%s\n", - miss); - return true; - } - } else { - - AUTHZ_LOG_INFO("DataFed Authz module started, version %s\n", getVersion()); - AUTHZ_LOG_INFO(" API, version %s\n", - getAPIVersion()); - AUTHZ_LOG_INFO(" Release, version %s\n", - getReleaseVersion()); - AUTHZ_LOG_ERROR("DataFed - Could not open authz config file.\n"); - - return true; - } - - AUTHZ_LOG_INFO("DataFed Authz module started, version %s\n", getVersion()); - AUTHZ_LOG_INFO(" API, version %s\n", getAPIVersion()); - AUTHZ_LOG_INFO(" Release, version %s\n", - getReleaseVersion()); - - return false; -} - // The same globus_result_t gsi_authz_init() { - // openlog("gsi_authz", 0, LOG_AUTH); + AUTHZ_LOG_DEBUG("gsi_authz_init\n"); memset(g_active_contexts, 0, sizeof(g_active_contexts)); // This line is different - if (loadConfig()) + if (initializeGlobalConfig()) { return GLOBUS_FAILURE; + } return GLOBUS_SUCCESS; } @@ -476,27 +157,23 @@ globus_result_t gsi_authz_authorize_async(va_list ap) { globus_gsi_authz_cb_t callback = va_arg(ap, globus_gsi_authz_cb_t); void *callback_arg = va_arg(ap, void *); // void * authz_system_state = va_arg(ap, void *); - char *callout_ids1 = getenv("GLOBUS_GRIDFTP_GUEST_IDENTITY_IDS"); char *callout_username_mapped1 = getenv("GLOBUS_GRIDFTP_MAPPED_USERNAME"); char *callout_id_mapped1 = getenv("GLOBUS_GRIDFTP_MAPPED_IDENTITY_ID"); - AUTHZ_LOG_DEBUG("libauthz.c GLOBUS_GRIDFTP_GUEST_IDENTITY_IDS: %s\n", + AUTHZ_LOG_DEBUG("gsi_authz_authorize_async GLOBUS_GRIDFTP_GUEST_IDENTITY_IDS: %s\n", callout_ids1); - AUTHZ_LOG_DEBUG("libauthz.c GLOBUS_GRIDFTP_MAPPED_USERNAME: %s\n", + AUTHZ_LOG_DEBUG("gsi_authz_authorize_async GLOBUS_GRIDFTP_MAPPED_USERNAME: %s\n", callout_username_mapped1); - AUTHZ_LOG_DEBUG("libauthz.c GLOBUS_GRIDFTP_MAPPED_IDENTITY_ID: %s\n", + AUTHZ_LOG_DEBUG("gsi_authz_authorize_async GLOBUS_GRIDFTP_MAPPED_IDENTITY_ID: %s\n", callout_id_mapped1); - AUTHZ_LOG_INFO("Allowed collection path: %s, action: %s, object is %s\n", - g_config.globus_collection_path, action, object); - if (strcmp(action, "lookup") == 0 || strcmp(action, "chdir") == 0) { - AUTHZ_LOG_INFO("Allowed collection path: %s, action: %s, object is %s\n", - g_config.globus_collection_path, action, object); - result = GLOBUS_SUCCESS; - callback(callback_arg, handle, result); - return result; - } + char globus_collection_path[MAX_PATH_LEN]; + getConfigVal("globus_collection_path", globus_collection_path, MAX_PATH_LEN); + AUTHZ_LOG_INFO("Allowed collection path: %s, action: %s, object is %s\n", + globus_collection_path, action, object); + globus_thread_t thread_id = globus_thread_self(); + AUTHZ_LOG_INFO("Thread id is: %p\n", (void *)thread_id.dummy); AUTHZ_LOG_ERROR("gsi_authz_authorize_async, handle: %p, act: %s, obj: %s\n", handle, action, object); @@ -579,31 +256,38 @@ globus_result_t gsi_authz_authorize_async(va_list ap) { if (callout_ids != NULL) { AUTHZ_LOG_DEBUG( - "libauthz.c GLOBUS_GRIDFTP_GUEST_IDENTITY_IDS: %s\n", + "gsi_authz_authorize_async GLOBUS_GRIDFTP_GUEST_IDENTITY_IDS: %s\n", callout_ids); client_id = strdup(callout_ids); AUTHZ_LOG_INFO("libauthz.c client_id(s): %s\n", client_id); } else if (callout_id_mapped != NULL) { AUTHZ_LOG_DEBUG( - "libauthz.c GLOBUS_GRIDFTP_MAPPED_IDENTITY_ID: %s\n", + "gsi_authz_authorize_async GLOBUS_GRIDFTP_MAPPED_IDENTITY_ID: %s\n", callout_id_mapped); client_id = strdup(callout_id_mapped); } else { AUTHZ_LOG_ERROR( - "libauthz.c GLOBUS_GRIDFTP_GUEST_IDENTITY_IDS.\n"); + "gsi_authz_authorize_async GLOBUS_GRIDFTP_GUEST_IDENTITY_IDS.\n"); } } if (client_id) { - if (checkAuthorization(client_id, object, action, &g_config) == - 0) { + struct Config config = createLocalConfigCopy(); + AUTHZ_LOG_INFO("gsi_authz_authorize_async client_id: %s, file: %s, action: " + "%s log_file path: %s\n", + client_id, object, action, config.log_path); + + // NOTE - Globus stores thread ids as a pointer, using an int to + // represent this is non ideal because it will be truncated on + // conversion. + if (checkAuthorization(client_id, object, action, config, + (int)thread_id.dummy) == 0) { result = GLOBUS_SUCCESS; } else { AUTHZ_LOG_INFO( - "libauthz.c Auth client_id: %s, file: %s, action: %s\n", + "gsi_authz_authorize_async client_id: %s, file: %s, action: %s, status: FALIED, msg: checkAuthorization command failed\n", client_id, object, action); - AUTHZ_LOG_INFO("libauthz.c checkAuthorization FAIL.\n"); } free(client_id); @@ -612,34 +296,33 @@ globus_result_t gsi_authz_authorize_async(va_list ap) { gss_release_buffer(&min_stat, &target_buf); } else { - AUTHZ_LOG_ERROR("gss_display_name target FAILED, maj: %d, min: %d\n", + AUTHZ_LOG_ERROR("gsi_authz_authorize_async path: %s, action: %s, object: %s, status: FAILED, msg: gss_display_name target FAILED, maj: %d, min: %d\n", globus_collection_path, action, object, maj_stat, min_stat); } gss_release_buffer(&min_stat, &client_buf); } else { - AUTHZ_LOG_ERROR("gss_display_name source FAILED, maj: %d, min: %d\n", + AUTHZ_LOG_ERROR("gsi_authz_authorize_async path: %s, action: %s, object: %s, status: FAILED, msg: gss_display_name source FAILED, maj: %d, min: %d\n", globus_collection_path, action, object, maj_stat, min_stat); } } else { - AUTHZ_LOG_ERROR("gss_inquire_context FAILED, maj: %d, min: %d\n", + AUTHZ_LOG_ERROR("gsi_authz_authorize_async path: %s, action: %s, object: %s, status: FAILED, msg: gss_inquire_context FAILED, maj: %d, min: %d\n", globus_collection_path, action, object, maj_stat, min_stat); } } else { - AUTHZ_LOG_ERROR("context handle lookup FAILED\n"); + AUTHZ_LOG_ERROR("gsi_authz_authorize_async path: %s, action: %s, object: %s, status: FAILED, msg: context handle\n", globus_collection_path, action, object); } if (result != GLOBUS_SUCCESS) { globus_object_t *error = globus_error_construct_no_authentication(0, 0); - AUTHZ_LOG_INFO("Authz: FAILED\n"); + + AUTHZ_LOG_INFO("gsi_authz_authorize_async path: %s, action: %s, object: %s, status: FAILED\n", globus_collection_path, action, object); result = globus_error_put(error); } else { - AUTHZ_LOG_DEBUG("Authz: PASSED\n"); + AUTHZ_LOG_INFO("gsi_authz_authorize_async path: %s, action: %s, object: %s, status: PASSED\n", globus_collection_path, action, object); callback(callback_arg, handle, result); } - AUTHZ_LOG_ERROR("Authz returning\n"); - return result; } @@ -675,8 +358,11 @@ globus_result_t gsi_map_user(va_list Ap) { (void)service; memset(identity_buffer, 0, buffer_length); - strcat(identity_buffer, g_config.user); - buffer_length = strlen(g_config.user); + + char user[MAX_ID_LEN]; + getConfigVal("user", user, MAX_ID_LEN); + strcat(identity_buffer, user); + buffer_length = strlen(user); return GLOBUS_SUCCESS; } diff --git a/repository/gridftp/globus5/authz/tests/CMakeLists.txt b/repository/gridftp/globus5/authz/tests/CMakeLists.txt new file mode 100644 index 000000000..c32ba16b5 --- /dev/null +++ b/repository/gridftp/globus5/authz/tests/CMakeLists.txt @@ -0,0 +1,28 @@ +if( ENABLE_UNIT_TESTS ) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_start.sh + ${CMAKE_CURRENT_BINARY_DIR}/mock/mock_start.sh + COPYONLY) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_stop.sh + ${CMAKE_CURRENT_BINARY_DIR}/mock/mock_stop.sh + COPYONLY) + + add_test(NAME start_mock + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/mock/mock_start.sh + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/repository/gridftp/globus5/authz/mock_core + ) + + # Add a custom target to stop the server + add_test(NAME stop_mock + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/mock/mock_stop.sh + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/repository/gridftp/globus5/authz/mock_core + ) + + set_tests_properties(start_mock PROPERTIES FIXTURES_SETUP FIX_MOCK) + set_tests_properties(stop_mock PROPERTIES FIXTURES_CLEANUP FIX_MOCK) + + add_subdirectory(unit) + add_subdirectory(integration) + add_subdirectory(mock) +endif() diff --git a/repository/gridftp/globus5/authz/tests/integration/CMakeLists.txt b/repository/gridftp/globus5/authz/tests/integration/CMakeLists.txt new file mode 100644 index 000000000..0f4d6f2df --- /dev/null +++ b/repository/gridftp/globus5/authz/tests/integration/CMakeLists.txt @@ -0,0 +1,20 @@ +# Each test listed in Alphabetical order +foreach(PROG + test_gsi_authz_init +) + + #test_AuthzWorker + file(GLOB ${PROG}_SOURCES ${PROG}*.cpp) + add_executable(integration_${PROG} ${${PROG}_SOURCES}) + + target_link_libraries(integration_${PROG} PUBLIC datafed-authz ${DATAFED_BOOST_LIBRARIES} ${DATAFED_GSSAPI_LIBRARIES} ${DATAFED_GLOBUS_COMMON_LIBRARIES}) + target_include_directories(integration_${PROG} PRIVATE ${DataFed_SOURCE_DIR}/repository/gridftp/globus5/authz/source) + if(BUILD_SHARED_LIBS) + target_compile_definitions(integration_${PROG} PRIVATE BOOST_TEST_DYN_LINK) + endif() + + add_test(integration_${PROG} integration_${PROG}) + + set_tests_properties(integration_${PROG} PROPERTIES FIXTURES_REQUIRED FIX_MOCK) + +endforeach(PROG) diff --git a/repository/gridftp/globus5/authz/tests/integration/test_AuthzWorker.cpp b/repository/gridftp/globus5/authz/tests/integration/test_AuthzWorker.cpp new file mode 100644 index 000000000..b7ec51e50 --- /dev/null +++ b/repository/gridftp/globus5/authz/tests/integration/test_AuthzWorker.cpp @@ -0,0 +1,174 @@ +#define BOOST_TEST_MAIN + +#define BOOST_TEST_MODULE getVersion +#include +#include + +// Local private includes +#include "AuthzWorker.hpp" + +// Standard includes +#include // For std::setenv +#include // For checking and removing files (C++17) +#include +#include + +extern "C" { +// Globus third party includes +#include +#include +#include + +// Local private includes +#include "Config.h" + +// Globus third party includes +#include +#include +#include + +// Declare functions +globus_result_t gsi_authz_init(); +void initializeDefaults(); +} + +const std::string repo_id = "repo/samoas"; +const std::string server_key_path = "../../mock_core/mock-datafed-core-key.pub"; +const std::string server_address = "tcp://localhost:9998"; +const std::string pub_key_path = "./datafed-repo-key.pub"; +const std::string pub_key = "Wxwm^-Cf7cJrqS)}/B?cDAq(L=@AwSA*({jhBu1]"; +const std::string priv_key_path = "./datafed-repo-key.priv"; +const std::string priv_key = "1:BoDR8-#sGZuRWyP*jr+Csm-kT}zV:tn@gRDS.u"; +const std::string log_path = "./datafed-gsi-authz.log"; +const std::string user = "TheRock"; +const std::string globus_collection_path = "/mnt/datafed"; + +BOOST_AUTO_TEST_SUITE(test_gsi) + +BOOST_AUTO_TEST_CASE(test_gsi_authz_init) { + + std::string file_path = "./datafed-authz-test.conf"; + // Check if the file exists + if (std::filesystem::exists(file_path)) { + // Remove the existing file + std::filesystem::remove(file_path); + } + + // Create and write to the new file + std::ofstream config_file(file_path); + if (!config_file) { + throw std::ios_base::failure("Failed to create the configuration file. " + + file_path); + } + + config_file << "server_address=" << server_address << std::endl; + config_file << "server_key=" << server_key_path << std::endl; + config_file << "repo_id=" << repo_id << std::endl; + config_file << "pub_key=" << pub_key_path << std::endl; + config_file << "priv_key=" << priv_key_path << std::endl; + config_file << "log_path=" << log_path << std::endl; + config_file << "user=" << user << std::endl; + config_file << "globus_collection_path=" << globus_collection_path + << std::endl; + + config_file.close(); + + // Check if the file exists + if (std::filesystem::exists(pub_key_path)) { + // Remove the existing file + std::filesystem::remove(pub_key_path); + } + + // Create and write to the new file + std::ofstream repo_pub(pub_key_path); + if (!repo_pub) { + throw std::ios_base::failure("Failed to create the configuration file. " + + pub_key_path); + } + + repo_pub << pub_key << std::endl; + repo_pub.close(); + + // Check if the file exists + if (std::filesystem::exists(priv_key_path)) { + // Remove the existing file + std::filesystem::remove(priv_key_path); + } + + // Create and write to the new file + std::ofstream repo_priv(priv_key_path); + if (!repo_priv) { + throw std::ios_base::failure("Failed to create the configuration file. " + + priv_key_path); + } + + repo_priv << priv_key << std::endl; + repo_priv.close(); + + // Read in contents of core public key which should be generated on the spot + // Open the file in input mode + std::ifstream server_file(server_key_path); + if (!server_file.is_open()) { + std::cerr << "Failed to open file: " << server_key_path << std::endl; + } + + // Use a string stream to read the entire file into a string + std::ostringstream ss; + ss << server_file.rdbuf(); // Read the file into the stream buffer + std::string server_key = ss.str(); // Convert stream buffer to string + + // Output the contents, these keys are test keys + std::cout << "File contents:\n" << server_key << std::endl; + + server_file.close(); // Close the file + + std::string conf_env_name = "DATAFED_AUTHZ_CFG_FILE"; + if (setenv(conf_env_name.c_str(), file_path.c_str(), 1) != 0) { + throw std::runtime_error("Failed to set environment variable: " + + conf_env_name); + } + + // Create a dummy config file to be loaded + // server_address=tcp://${local_DATAFED_DOMAIN}:${local_DATAFED_SERVER_PORT} + + initializeDefaults(); + + struct Config conf = createLocalConfigCopy(); + conf.repo_id[0] = '\0'; + conf.server_addr[0] = '\0'; + conf.pub_key[0] = '\0'; + conf.priv_key[0] = '\0'; + conf.server_key[0] = '\0'; + conf.user[0] = '\0'; + conf.log_path[0] = '\0'; + conf.globus_collection_path[0] = '\0'; + + BOOST_CHECK_EQUAL(std::string(conf.repo_id), ""); + BOOST_CHECK_EQUAL(std::string(conf.server_addr), ""); + BOOST_CHECK_EQUAL(std::string(conf.pub_key), ""); + BOOST_CHECK_EQUAL(std::string(conf.priv_key), ""); + BOOST_CHECK_EQUAL(std::string(conf.server_key), ""); + BOOST_CHECK_EQUAL(std::string(conf.user), ""); + BOOST_CHECK_EQUAL(std::string(conf.log_path), ""); + BOOST_CHECK_EQUAL(std::string(conf.globus_collection_path), ""); + + globus_result_t result = gsi_authz_init(); + + auto config = createLocalConfigCopy(); + + // Test a valid full FTP path when the globus_collection_path is / + SDMS::LogContext log_context; + + strcpy(config.globus_collection_path, "/mnt/datafed"); + SDMS::AuthzWorker worker(config, log_context); + + char client_id[] = "23c9067f-60e8-4741-9af1-482280faced4"; + char path[] = "ftp://ci-datafed-globus2/mnt/datafed/datafedci-home"; + char action[] = "lookup"; + + int rv = worker.checkAuth(client_id, path, action); + + BOOST_CHECK_EQUAL(rv, 0); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/repository/gridftp/globus5/authz/tests/integration/test_gsi_authz_init.cpp b/repository/gridftp/globus5/authz/tests/integration/test_gsi_authz_init.cpp new file mode 100644 index 000000000..b76f2a83d --- /dev/null +++ b/repository/gridftp/globus5/authz/tests/integration/test_gsi_authz_init.cpp @@ -0,0 +1,169 @@ +#define BOOST_TEST_MAIN + +#define BOOST_TEST_MODULE getVersion +#include +#include + +// Standard includes +#include // For std::setenv +#include // For checking and removing files (C++17) +#include +#include + +extern "C" { +// Globus third party includes +#include +#include +#include + +// Local private includes +#include "Config.h" + +// Globus third party includes +#include +#include +#include + +// Declare functions +globus_result_t gsi_authz_init(); +void initializeDefaults(); +} + +const std::string repo_id = "repo/samoas"; +const std::string server_key_path = "../../mock_core/mock-datafed-core-key.pub"; +const std::string server_address = "tcp://localhost:9998"; +const std::string pub_key_path = "./datafed-repo-key.pub"; +const std::string pub_key = "Wxwm^-Cf7cJrqS)}/B?cDAq(L=@AwSA*({jhBu1]"; +const std::string priv_key_path = "./datafed-repo-key.priv"; +const std::string priv_key = "1:BoDR8-#sGZuRWyP*jr+Csm-kT}zV:tn@gRDS.u"; +const std::string log_path = "./datafed-gsi-authz.log"; +const std::string user = "TheRock"; +const std::string globus_collection_path = "/mnt/datafed"; + +BOOST_AUTO_TEST_SUITE(test_gsi) + +BOOST_AUTO_TEST_CASE(test_gsi_authz_init) { + + std::string file_path = "./datafed-authz-test.conf"; + // Check if the file exists + if (std::filesystem::exists(file_path)) { + // Remove the existing file + std::filesystem::remove(file_path); + } + + // Create and write to the new file + std::ofstream config_file(file_path); + if (!config_file) { + throw std::ios_base::failure("Failed to create the configuration file. " + + file_path); + } + + config_file << "server_address=" << server_address << std::endl; + config_file << "server_key=" << server_key_path << std::endl; + config_file << "repo_id=" << repo_id << std::endl; + config_file << "pub_key=" << pub_key_path << std::endl; + config_file << "priv_key=" << priv_key_path << std::endl; + config_file << "log_path=" << log_path << std::endl; + config_file << "user=" << user << std::endl; + config_file << "globus_collection_path=" << globus_collection_path + << std::endl; + + config_file.close(); + + // Check if the file exists + if (std::filesystem::exists(pub_key_path)) { + // Remove the existing file + std::filesystem::remove(pub_key_path); + } + + // Create and write to the new file + std::ofstream repo_pub(pub_key_path); + if (!repo_pub) { + throw std::ios_base::failure("Failed to create the configuration file. " + + pub_key_path); + } + + repo_pub << pub_key << std::endl; + repo_pub.close(); + + // Check if the file exists + if (std::filesystem::exists(priv_key_path)) { + // Remove the existing file + std::filesystem::remove(priv_key_path); + } + + // Create and write to the new file + std::ofstream repo_priv(priv_key_path); + if (!repo_priv) { + throw std::ios_base::failure("Failed to create the configuration file. " + + priv_key_path); + } + + repo_priv << priv_key << std::endl; + repo_priv.close(); + + // Read in contents of core public key which should be generated on the spot + // Open the file in input mode + std::ifstream server_file(server_key_path); + if (!server_file.is_open()) { + std::cerr << "Failed to open file: " << server_key_path << std::endl; + } + + // Use a string stream to read the entire file into a string + std::ostringstream ss; + ss << server_file.rdbuf(); // Read the file into the stream buffer + std::string server_key = ss.str(); // Convert stream buffer to string + + // Output the contents, these keys are test keys + std::cout << "File contents:\n" << server_key << std::endl; + + server_file.close(); // Close the file + + std::string conf_env_name = "DATAFED_AUTHZ_CFG_FILE"; + if (setenv(conf_env_name.c_str(), file_path.c_str(), 1) != 0) { + throw std::runtime_error("Failed to set environment variable: " + + conf_env_name); + } + + // Create a dummy config file to be loaded + // server_address=tcp://${local_DATAFED_DOMAIN}:${local_DATAFED_SERVER_PORT} + + initializeDefaults(); + struct Config conf = createLocalConfigCopy(); + conf.repo_id[0] = '\0'; + conf.server_addr[0] = '\0'; + conf.pub_key[0] = '\0'; + conf.priv_key[0] = '\0'; + conf.server_key[0] = '\0'; + conf.user[0] = '\0'; + conf.log_path[0] = '\0'; + conf.globus_collection_path[0] = '\0'; + + BOOST_CHECK_EQUAL(std::string(conf.repo_id), ""); + BOOST_CHECK_EQUAL(std::string(conf.server_addr), ""); + BOOST_CHECK_EQUAL(std::string(conf.pub_key), ""); + BOOST_CHECK_EQUAL(std::string(conf.priv_key), ""); + BOOST_CHECK_EQUAL(std::string(conf.server_key), ""); + BOOST_CHECK_EQUAL(std::string(conf.user), ""); + BOOST_CHECK_EQUAL(std::string(conf.log_path), ""); + BOOST_CHECK_EQUAL(std::string(conf.globus_collection_path), ""); + + globus_result_t result = gsi_authz_init(); + + conf = createLocalConfigCopy(); + BOOST_CHECK_EQUAL(std::string(conf.repo_id), repo_id); + BOOST_CHECK_EQUAL(std::string(conf.server_addr), server_address); + BOOST_CHECK_EQUAL(std::string(conf.pub_key), pub_key); + BOOST_CHECK_EQUAL(std::string(conf.priv_key), priv_key); + BOOST_CHECK_EQUAL(std::string(conf.server_key), server_key); + BOOST_CHECK_EQUAL(std::string(conf.user), user); + BOOST_CHECK_EQUAL(std::string(conf.log_path), log_path); + BOOST_CHECK_EQUAL(std::string(conf.globus_collection_path), + globus_collection_path); + + BOOST_CHECK_EQUAL(result, GLOBUS_SUCCESS); + + +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/repository/gridftp/globus5/authz/tests/mock/CMakeLists.txt b/repository/gridftp/globus5/authz/tests/mock/CMakeLists.txt new file mode 100644 index 000000000..0492f8b0c --- /dev/null +++ b/repository/gridftp/globus5/authz/tests/mock/CMakeLists.txt @@ -0,0 +1,20 @@ + + +# Each test listed in Alphabetical order +foreach(PROG + test_getVersion +) + + file(GLOB ${PROG}_SOURCES ${PROG}*.cpp) + add_executable(mock_liveness_${PROG} ${${PROG}_SOURCES}) + + target_link_libraries(mock_liveness_${PROG} PUBLIC datafed-authz ${DATAFED_BOOST_LIBRARIES} ${DATAFED_GSSAPI_LIBRARIES} ${DATAFED_GLOBUS_COMMON_LIBRARIES}) + target_include_directories(mock_liveness_${PROG} PRIVATE ${DataFed_SOURCE_DIR}/repository/gridftp/globus5/authz/source) + if(BUILD_SHARED_LIBS) + target_compile_definitions(mock_liveness_${PROG} PRIVATE BOOST_TEST_DYN_LINK) + endif() + + add_test(mock_liveness_${PROG} mock_liveness_${PROG}) + set_tests_properties(mock_liveness_${PROG} PROPERTIES FIXTURES_REQUIRED FIX_MOCK) + +endforeach(PROG) diff --git a/repository/gridftp/globus5/authz/tests/mock/mock_start.sh b/repository/gridftp/globus5/authz/tests/mock/mock_start.sh new file mode 100755 index 000000000..acadcd11a --- /dev/null +++ b/repository/gridftp/globus5/authz/tests/mock/mock_start.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +if [ -f ./mock.log ] +then + rm ./mock.log +fi +./datafed-mock-core --gen-keys +./datafed-mock-core > mock.log 2>&1 & +sleep 2 diff --git a/repository/gridftp/globus5/authz/tests/mock/mock_stop.sh b/repository/gridftp/globus5/authz/tests/mock/mock_stop.sh new file mode 100755 index 000000000..109b3061e --- /dev/null +++ b/repository/gridftp/globus5/authz/tests/mock/mock_stop.sh @@ -0,0 +1,4 @@ +#!/bin/bash +echo "Stopping Mock Server" +kill $(cat ./server.pid ) && rm -f ./server.pid +cat ./mock.log diff --git a/repository/gridftp/globus5/authz/tests/mock/test_getVersion.cpp b/repository/gridftp/globus5/authz/tests/mock/test_getVersion.cpp new file mode 100644 index 000000000..f407c97c1 --- /dev/null +++ b/repository/gridftp/globus5/authz/tests/mock/test_getVersion.cpp @@ -0,0 +1,200 @@ +#define BOOST_TEST_MAIN + +#define BOOST_TEST_MODULE getVersion +#include +#include + +#include "Version.hpp" + +// Public includes +#include "common/CommunicatorFactory.hpp" +#include "common/CredentialFactory.hpp" +#include "common/DynaLog.hpp" +#include "common/ICredentials.hpp" +#include "common/MessageFactory.hpp" +#include "common/ProtocolTypes.hpp" +#include "common/TraceException.hpp" + +// Proto file includes +#include "common/SDMS.pb.h" +#include "common/SDMS_Anon.pb.h" + +// Standard includes +#include + +using namespace SDMS; + +extern "C" { +#include "AuthzWorker.h" +} + +BOOST_AUTO_TEST_SUITE(mock_liveness_get_version) + +BOOST_AUTO_TEST_CASE(mock_liveness_test_get_version) { + + std::string fname = "../../mock_core/mock-datafed-core-key.pub"; + std::string mock_core_server_address = "tcp://localhost:9998"; + std::ifstream inf(fname.c_str()); + if (!inf.is_open() || !inf.good()) { + EXCEPT_PARAM(1, std::string("Could not open server key file: ") + fname); + } + std::string server_key; + inf >> server_key; + inf.close(); + + std::unordered_map cred_options; + // Public and private keys are consistent with what is in the mock for the + // repo + cred_options[CredentialType::PUBLIC_KEY] = + "Wxwm^-Cf7cJrqS)}/B?cDAq(L=@AwSA*({jhBu1]"; + cred_options[CredentialType::PRIVATE_KEY] = + "1:BoDR8-#sGZuRWyP*jr+Csm-kT}zV:tn@gRDS.u"; + // Server key can be generated by the mock + cred_options[CredentialType::SERVER_KEY] = server_key; + + std::cout << "cred public key: " << cred_options[CredentialType::PUBLIC_KEY] + << std::endl; + std::cout << "cred private key: " << cred_options[CredentialType::PRIVATE_KEY] + << std::endl; + // Server key should be the public key of the mock-datafed-core.pub + std::cout << "cred server key: " << cred_options[CredentialType::SERVER_KEY] + << std::endl; + + CredentialFactory cred_factory; + std::unique_ptr sec_ctx = + cred_factory.create(ProtocolType::ZQTP, cred_options); + + // Need to attach a random number to the authz_client_socket so that + // each authz client is distinct + std::string authz_thread_id; + authz_thread_id = "authz_client_socket_test_mock"; + + auto client_comm = [&](const std::string &socket_id, + const std::string &address, + ICredentials &credentials) { + /// Creating input parameters for constructing Communication Instance + AddressSplitter splitter(address); + + SocketOptions socket_options; + socket_options.scheme = splitter.scheme(); + socket_options.class_type = SocketClassType::CLIENT; + socket_options.direction_type = SocketDirectionalityType::BIDIRECTIONAL; + socket_options.communication_type = SocketCommunicationType::ASYNCHRONOUS; + socket_options.connection_life = SocketConnectionLife::INTERMITTENT; + socket_options.protocol_type = ProtocolType::ZQTP; + socket_options.connection_security = SocketConnectionSecurity::SECURE; + socket_options.host = splitter.host(); + socket_options.port = splitter.port(); + + std::cout << "Host: " << socket_options.host << std::endl; + std::cout << "Port: " << std::to_string(socket_options.port.value()) + << std::endl; + + LogContext log_context; + log_context.thread_name = "mock_core_server_test_client"; + log_context.thread_id = 0; + if (socket_options.port.has_value()) { + if (socket_options.port.value() != 9998) { + + DL_WARNING(log_context, + "Port number is defined for: " + << address + << " however, it is a non standard port, the standard " + "port for connecting to the mock core server is port " + "number 9998, whereas here you are using port: " + << socket_options.port.value()); + } + } + socket_options.local_id = socket_id; + + // Shortened for testing speed + uint32_t timeout_on_receive = 2000; + long timeout_on_poll = 2000; + + CommunicatorFactory comm_factory(log_context); + + return comm_factory.create(socket_options, credentials, timeout_on_receive, + timeout_on_poll); + }(authz_thread_id, mock_core_server_address, *sec_ctx); + + // Correlation id should be created when message is created + std::string corr_id; + const std::string id = "MyClientId"; + MessageFactory msg_factory; + + { // Client send an empty payload i.e. an ack + auto msg_from_client = + msg_factory.create(MessageType::GOOGLE_PROTOCOL_BUFFER); + + corr_id = std::get( + msg_from_client->get(MessageAttribute::CORRELATION_ID)); + + std::cout << "Message correlation id: " << corr_id << std::endl; + std::cout << "Message id: " << id << std::endl; + msg_from_client->set(MessageAttribute::ID, id); + msg_from_client->set(MessageAttribute::KEY, + cred_options[CredentialType::PUBLIC_KEY]); + + auto version_req = std::make_unique(); + + msg_from_client->setPayload(std::move(version_req)); + + client_comm->send(*msg_from_client); + } + + { // Receive a version response payload + ICommunicator::Response response = + client_comm->receive(MessageType::GOOGLE_PROTOCOL_BUFFER); + + std::cout << "Checking message response" << std::endl; + + BOOST_CHECK(response.time_out == false); + BOOST_CHECK(response.error == false); + + // Only run the following if the unique pointer is valid and a message + // exists + if (response.message) { + std::cout << "Checking matching correlation ids." << std::endl; + BOOST_CHECK_EQUAL(corr_id, std::get(response.message->get( + MessageAttribute::CORRELATION_ID))); + + std::cout << "Key is " + << std::get( + response.message->get(MessageAttribute::KEY)) + << std::endl; + std::cout << "ID is " + << std::get( + response.message->get(MessageAttribute::ID)) + << std::endl; + // BOOST_CHECK( + // std::get(response.message->get(MessageAttribute::KEY)) + // .compare(key) == 0); + // BOOST_CHECK(std::get(response.message->get(MessageAttribute::ID)).compare(id) + // == 0); + + // const auto &routes = response.message->getRoutes(); + // std::cout << "Routes are " << std::endl; + // for (const auto &route : routes) { + // std::cout << route << std::endl; + //} + // BOOST_CHECK(routes.size() == 1); + // BOOST_CHECK(routes.front().compare(client_id) == 0); + + auto google_msg_ptr = std::get<::google::protobuf::Message *>( + response.message->getPayload()); + + Anon::VersionReply *version_response = + dynamic_cast(google_msg_ptr); + + BOOST_CHECK(version_response->has_release_year()); + BOOST_CHECK(version_response->has_release_month()); + BOOST_CHECK(version_response->has_release_day()); + BOOST_CHECK(version_response->has_release_hour()); + BOOST_CHECK(version_response->has_release_minute()); + } else { + std::cout << "No message was received." << std::endl; + } + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/repository/gridftp/globus5/authz/tests/unit/CMakeLists.txt b/repository/gridftp/globus5/authz/tests/unit/CMakeLists.txt new file mode 100644 index 000000000..b25d8c419 --- /dev/null +++ b/repository/gridftp/globus5/authz/tests/unit/CMakeLists.txt @@ -0,0 +1,19 @@ +# Each test listed in Alphabetical order +foreach(PROG + test_AuthzWorker + test_Config + test_getVersion + test_Util +) + + file(GLOB ${PROG}_SOURCES ${PROG}*.cpp) + add_executable(unit_${PROG} ${${PROG}_SOURCES}) + + target_link_libraries(unit_${PROG} PUBLIC datafed-authz ${DATAFED_BOOST_LIBRARIES} ${DATAFED_GSSAPI_LIBRARIES} ${DATAFED_GLOBUS_COMMON_LIBRARIES}) + target_include_directories(unit_${PROG} PRIVATE ${DataFed_SOURCE_DIR}/repository/gridftp/globus5/authz/source) + if(BUILD_SHARED_LIBS) + target_compile_definitions(unit_${PROG} PRIVATE BOOST_TEST_DYN_LINK) + endif() + add_test(unit_${PROG} unit_${PROG}) + +endforeach(PROG) diff --git a/repository/gridftp/globus5/authz/tests/unit/test_AuthzWorker.cpp b/repository/gridftp/globus5/authz/tests/unit/test_AuthzWorker.cpp new file mode 100644 index 000000000..05beb591b --- /dev/null +++ b/repository/gridftp/globus5/authz/tests/unit/test_AuthzWorker.cpp @@ -0,0 +1,458 @@ +#define BOOST_TEST_MAIN + +#define BOOST_TEST_MODULE AuthzWorker +#include +#include + +// Private includes +#include "AuthzWorker.hpp" + +// Third party includes +#include + +// Public includes +#include "common/DynaLog.hpp" +#include "common/ICommunicator.hpp" +#include "common/IMessage.hpp" +#include "common/MessageFactory.hpp" +#include "common/SDMS_Anon.pb.h" +#include "common/TraceException.hpp" + +extern "C" { +#include "Config.h" +} + +class ConfigFixture { +public: + // Setup: create the object before each test case + // The below settings are simply for testing and are not + // used in anyway in a production environment. + ConfigFixture() { + std::string repo_id = "datafed-one-repo-to-rule-them-all"; + std::string server_addr = "tcp://ruler:7513"; + std::string pub_key = "=+r^&Qc&}fset(SDMS::MessageAttribute::ID, user_id); + response.message->set(SDMS::MessageAttribute::KEY, key); + response.message->set(SDMS::MessageAttribute::STATE, + SDMS::MessageState::REQUEST); + response.message->set(SDMS::constants::message::google::CONTEXT, context); + auto auth_by_token_req = + std::make_unique(); + std::string token = "golden_chest"; + auth_by_token_req->set_token(token); + + response.message->setPayload(std::move(auth_by_token_req)); + + std::string route = "MtOlympia"; + response.message->addRoute(route); + + SDMS::LogContext log_context; + SDMS::AuthzWorker worker(config, log_context); + + BOOST_CHECK_EQUAL(worker.processResponse(response), 0); +} + +BOOST_AUTO_TEST_CASE(ProcessResponseWithNackReply) { + + SDMS::MessageFactory msg_factory; + + SDMS::ICommunicator::Response response; + response.message = + msg_factory.create(SDMS::MessageType::GOOGLE_PROTOCOL_BUFFER); + + std::string user_id = "hermes"; + std::string key = "skeleton"; + const uint16_t context = 1; + + response.message->set(SDMS::MessageAttribute::ID, user_id); + response.message->set(SDMS::MessageAttribute::KEY, key); + response.message->set(SDMS::MessageAttribute::STATE, + SDMS::MessageState::REQUEST); + response.message->set(SDMS::constants::message::google::CONTEXT, context); + auto nack = std::make_unique(); + + response.message->setPayload(std::move(nack)); + + std::string route = "MtOlympia"; + response.message->addRoute(route); + + SDMS::LogContext log_context; + SDMS::AuthzWorker worker(config, log_context); + // Verify that DL_DEBUG was called with "Received NACK reply" for NACK case + BOOST_CHECK_EQUAL(worker.processResponse(response), 1); + // Verify error occurs +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/repository/gridftp/globus5/authz/tests/unit/test_Config.cpp b/repository/gridftp/globus5/authz/tests/unit/test_Config.cpp new file mode 100644 index 000000000..f04cb97ec --- /dev/null +++ b/repository/gridftp/globus5/authz/tests/unit/test_Config.cpp @@ -0,0 +1,212 @@ +#define BOOST_TEST_MAIN + +#define BOOST_TEST_MODULE getVersion +#include +#include + +extern "C" { +#include "Config.h" +} + +#include // For std::filesystem::exists and std::filesystem::remove +#include + +void setEnvVar() { + const char *config_file_path_key = "DATAFED_AUTHZ_CFG_FILE"; + const char *config_file_path_value = "./datafed-authz.cfg"; + + if (setenv(config_file_path_key, config_file_path_value, 1) == 0) { + std::cout << config_file_path_key << " is set to " << config_file_path_value + << std::endl; + } else { + std::cerr << "Failed to set environment variable." << std::endl; + } +} + +void removeLocalCfgFile() { + std::string cfg_file_path = "./datafed-authz.cfg"; + if (std::filesystem::exists(cfg_file_path)) { + std::cout << "File exists. Removing: " << cfg_file_path << std::endl; + std::filesystem::remove(cfg_file_path); + std::cout << "File removed successfully." << std::endl; + } else { + std::cout << "File does not exist: " << cfg_file_path << std::endl; + } +} + +void createKeyFile(std::string file_path, std::string content) { + std::ofstream file_stream(file_path); + // Check if the file is open + if (!file_stream.is_open()) { + std::cerr << "Failed to open or create the file: " << file_path + << std::endl; + return; + } + + file_stream << content; + file_stream.close(); +} + +static const std::string pub_key = "s@!#0N^FPml<]O +#include + +extern "C" { +#include "Util.h" +} + +BOOST_AUTO_TEST_SUITE(util) + +// uuidToStr Valid UUID Conversion +BOOST_AUTO_TEST_CASE(ValidUuidConversion) { + unsigned char uuid[16] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, + 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef}; + char output[37]; // UUID string length + null terminator + uuidToStr(uuid, output); + + BOOST_CHECK_EQUAL(std::string(output), + "12345678-90ab-cdef-1234-567890abcdef"); +} + +// uuidToStr Empty UUID +BOOST_AUTO_TEST_CASE(EmptyUuid) { + unsigned char uuid[16] = {0}; + char output[37]; + uuidToStr(uuid, output); + + BOOST_CHECK_EQUAL(std::string(output), + "00000000-0000-0000-0000-000000000000"); +} + +// uuidToStr Max UUID +BOOST_AUTO_TEST_CASE(MaxUuid) { + unsigned char uuid[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + char output[37]; + uuidToStr(uuid, output); + + BOOST_CHECK_EQUAL(std::string(output), + "ffffffff-ffff-ffff-ffff-ffffffffffff"); +} + +// uuidToStr Random UUID +BOOST_AUTO_TEST_CASE(RandomUuid) { + unsigned char uuid[16] = {0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe, + 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe}; + char output[37]; + uuidToStr(uuid, output); + + BOOST_CHECK_EQUAL(std::string(output), + "deadbeef-cafe-babe-dead-beefcafebabe"); +} + +BOOST_AUTO_TEST_CASE(TestValidInput) { + char output[37]; + output[0] = '\0'; + + // decodeUUID Test with valid Base32 encoded input + BOOST_CHECK(decodeUUID("mzxw6ytbpiqgsxu6zt4jq5diiy", output)); + BOOST_CHECK_EQUAL(strlen(output), 36); + BOOST_CHECK_EQUAL(output[8], '-'); // Check canonical UUID format + BOOST_CHECK_EQUAL(output[13], '-'); + BOOST_CHECK_EQUAL(output[18], '-'); + BOOST_CHECK_EQUAL(output[23], '-'); +} + +BOOST_AUTO_TEST_CASE(TestInvalidCharacter) { + char output[37]; + + // decodeUUID Test with invalid character in input + BOOST_CHECK(!decodeUUID("mzxw6ytbpiqg8xu6zt4jq5diiy", output)); +} + +BOOST_AUTO_TEST_CASE(TestEmptyInput) { + char output[37]; + + // decodeUUID Test with empty input string + BOOST_CHECK(!decodeUUID("", output)); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/repository/gridftp/globus5/authz/tests/unit/test_getVersion.cpp b/repository/gridftp/globus5/authz/tests/unit/test_getVersion.cpp new file mode 100644 index 000000000..8b0d94a4a --- /dev/null +++ b/repository/gridftp/globus5/authz/tests/unit/test_getVersion.cpp @@ -0,0 +1,43 @@ +#define BOOST_TEST_MAIN + +#define BOOST_TEST_MODULE getVersion +#include +#include + +#include "Version.hpp" + +// Third party includes +#include + +extern "C" { +#include "AuthzWorker.h" +} + +struct GlobalProtobufTeardown { + ~GlobalProtobufTeardown() { + // This is the teardown function that runs once at the end + google::protobuf::ShutdownProtobufLibrary(); + } +}; + +// Declare a global fixture instance +BOOST_GLOBAL_FIXTURE(GlobalProtobufTeardown); + +BOOST_AUTO_TEST_SUITE(get_version) + +BOOST_AUTO_TEST_CASE(test_get_version) { + // Simulate expected version from SDMS::authz::version + const int expected_major = SDMS::authz::version::MAJOR; + const int expected_minor = SDMS::authz::version::MINOR; + const int expected_patch = SDMS::authz::version::PATCH; + + // Construct the expected version string + std::string expected_version = std::to_string(expected_major) + "." + + std::to_string(expected_minor) + "." + + std::to_string(expected_patch); + + // Call the function and verify the result + BOOST_CHECK_EQUAL(std::string(getVersion()), expected_version); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/scripts/ci_harbor_artifact_count.sh b/scripts/ci_harbor_artifact_count.sh index b08e6c79d..2c2ea5501 100755 --- a/scripts/ci_harbor_artifact_count.sh +++ b/scripts/ci_harbor_artifact_count.sh @@ -2,12 +2,55 @@ set -euf +Help() +{ + echo "$(basename ${BASH_SOURCE[0]}) Will check to make sure that the selected" + echo " docker image has been uploaded to the registry." + echo + echo "Syntax: $(basename ${BASH_SOURCE[0]}) [-h|r]" + echo "options:" + echo "-h, --help Print this help message" + echo "-r, --repository The container image repository." +} + +# Define an array with variable names +vars=("DATAFED_HARBOR_REGISTRY" "DATAFED_HARBOR_REPOSITORY" "DATAFED_HARBOR_USERNAME" "DATAFED_HARBOR_PASSWORD") + +# Loop through the array and set local variables +for var in "${vars[@]}"; do + eval "local_${var}=\${${var}:-\"\"}" +done + + +VALID_ARGS=$(getopt -o hr: --long 'help',repository: -- "$@") +if [[ $? -ne 0 ]]; then + exit 2; +fi +eval set -- "$VALID_ARGS" +while [ : ]; do + case "$1" in + -h | --help) + Help + exit 0 + ;; + -r | --repository) + local_DATAFED_HARBOR_REPOSITORY=$2 + shift 2 + ;; + --) shift; + break + ;; + \?) # incorrect option + echo "Error: Invalid option" + exit;; + esac +done + # This script is created to determine if a harbor image exists in the repository # It will print the number of artifacts that exist for a particualar image. LOG_FILE="harbor_check.log" echo "CI Harbor Check Log File" > "$LOG_FILE" - if [ -z "${DATAFED_HARBOR_PROJECT:-}" ] then local_DATAFED_HARBOR_PROJECT="datafed" @@ -22,14 +65,6 @@ else local_DATAFED_HARBOR_IMAGE_TAG=$(printenv DATAFED_HARBOR_IMAGE_TAG) fi -# Define an array with variable names -vars=("DATAFED_HARBOR_REGISTRY" "DATAFED_HARBOR_REPOSITORY" "DATAFED_HARBOR_USERNAME" "DATAFED_HARBOR_PASSWORD") - -# Loop through the array and set local variables -for var in "${vars[@]}"; do - eval "local_${var}=\${${var}:-\"\"}" -done - # Check for required variables for var in "${vars[@]}"; do local_var="local_${var}" @@ -41,9 +76,53 @@ done local_DATAFED_HARBOR_URL="https://$local_DATAFED_HARBOR_REGISTRY" +# Note HARBOR_REPOSITORY should not include the project path that is kept in the +# variable DATAFED_HARBOR_PROJECT +# +# i.e. the below is correct +# +# local_DATAFED_HARBOR_PROJECT="datafed" +# local_DATAFED_HARBOR_REPOSITORY="core-devel" URL="$local_DATAFED_HARBOR_URL/api/v2.0/projects/$local_DATAFED_HARBOR_PROJECT/repositories/$local_DATAFED_HARBOR_REPOSITORY/artifacts" -echo "$URL" >> "$LOG_FILE" -data=$(curl -u $local_DATAFED_HARBOR_USERNAME:$local_DATAFED_HARBOR_PASSWORD -s "${URL}?with_tag=$local_DATAFED_HARBOR_IMAGE_TAG" ) +echo "${URL}?with_tag=$local_DATAFED_HARBOR_IMAGE_TAG" >> "$LOG_FILE" +# This requires artifact permissions for the token +data=$(curl -u "$local_DATAFED_HARBOR_USERNAME:$local_DATAFED_HARBOR_PASSWORD" -s "${URL}?with_tag=$local_DATAFED_HARBOR_IMAGE_TAG" ) + +echo "$data" >> "$LOG_FILE" +# In the case that an image has not yet been uploaded the server will return +# a json object of the following format +# +# { +# "errors": [ +# { +# "code": "NOT_FOUND", +# "message": "path /api/v2.0/projects/datafed/repositories/gcs-1086-bug-python-client-pypi-version/artifacts was not found" +# } +# ] +# } +# +# If credentials are wrong. +# +# { +# "errors": [ +# { +# "code": "UNAUTHORIZED", +# "message": "unauthorized" +# } +# ] +# } +# +# If authorization scope is wrong (needs artifact access) +# +# { +# "errors": [ +# { +# "code": "FORBIDDEN", +# "message": "forbidden" +# } +# ] +# } + error_code=$(echo $?) if [ "$error_code" != "0" ] then @@ -67,6 +146,31 @@ then echo "$data" | jq >> "$LOG_FILE" fi number_of_artifacts=$(echo "$data" | jq ' . | length') + +# Make sure the response doesn't contain an error code before assumptions are made +if [ "$number_of_artifacts" != "0" ] +then + # Can only check for errors with .errors if it is an object not if it is an + # array + if [ "$is_obj" == "true" ] + then + ERROR_FOUND=$(echo "$data" | jq -r 'if .errors and (.errors | length > 0) then "TRUE" else "FALSE" end') + if [ "$ERROR_FOUND" == "TRUE" ] + then + ERROR_CODE=$(echo "$data" | jq -r '.errors[0].code') + if [ "$ERROR_CODE" == "NOT_FOUND" ] + then + echo "0" + exit 0 + else + echo "Aborting unhandled error $ERROR_CODE" >> "$LOG_FILE" + exit 1 + fi + fi + fi +fi + echo "Number of artifacts found: $number_of_artifacts" >> "$LOG_FILE" +# Otherwise we assume the object contains the list of objects echo "$number_of_artifacts" diff --git a/scripts/ci_pipeline_setup.sh b/scripts/ci_pipeline_setup.sh index 8621f1046..94ffd3be9 100755 --- a/scripts/ci_pipeline_setup.sh +++ b/scripts/ci_pipeline_setup.sh @@ -26,7 +26,6 @@ Help() echo "-a, --gitlab-api-token The GitLab API token for checking the" echo " status of a pipeline." } - GITLAB_PROJECT_ID="10830" OS_APP_ID=$(printenv OS_APP_ID || true) @@ -145,7 +144,7 @@ data=$(curl -s --retry 5 -i -X POST \ } }" \ https://orc-open.ornl.gov:13000/v3/auth/tokens) -error_code=$? +error_code="$?" if [ "$error_code" == "6" ] then echo "Unable to connect to Open Stack API endpoints, make sure you are" @@ -226,17 +225,20 @@ find_orc_instance_by_name() { found_vm_id="TRUE" fi } +body=$(echo "$data" | sed -n 's/^\({\".*\)/\1/p') -body=$(echo $data | sed 's/^.*{\"token/{\"token/' ) +if jq -e 'has("error")' <<< "$body" > /dev/null; then + echo "Error Detected!" + echo "$body" | jq + exit 2 +fi compute_url=$(echo "$body" | jq '.token.catalog[] | select(.name=="nova") |.endpoints[] | select(.interface=="public") | .url ') sanitize_compute_url=$(echo $compute_url | sed 's/\"//g') header=$(echo "$data" | sed 's/{\"token.*//') subject_token=$(echo "$data" | grep "X-Subject-Token" | awk '{print $2}' ) - sanitize_subject_token=${subject_token:0:268} - ################################################################################ # Check 1 - Are there running pipelines ################################################################################ diff --git a/scripts/ci_purge_images.sh b/scripts/ci_purge_images.sh index 84548dc09..5a7ae0d41 100755 --- a/scripts/ci_purge_images.sh +++ b/scripts/ci_purge_images.sh @@ -1,45 +1,81 @@ #!/bin/bash +set -euf # The purpose of this script is to prevent the number of images built on a # VM from taking over to much storage, here we can set the number of GB, that # we will allow to be stored on the VM, after which we will start deleting # the oldest one # Max allowed size of all images in GB -if [ -z "${DATAFED_CI_PURGE_THRESHOLD}" ] +if [ -z "${DATAFED_CI_PURGE_THRESHOLD:-}" ] then local_DATAFED_CI_PURGE_THRESHOLD="15" else local_DATAFED_CI_PURGE_THRESHOLD=$(printenv DATAFED_CI_PURGE_THRESHOLD) fi +echo "Docker Purge Threshold set to: $local_DATAFED_CI_PURGE_THRESHOLD" get_size_of_all_images_in_GB() { - declare -g total_image_size_number="0" - docker_size_stats=$(docker system df --format "{{.Type}} {{.Size}}") - echo "docker_size_stats" - total_image_size=$(echo "${docker_size_stats}" | head -1 | awk '{print $2}' ) - echo "Image size is $total_image_size" - if [ ! -z "${total_image_size}" ] - then - if [ "${total_image_size: -2}" = "GB" ] - then - total_image_size_number="${total_image_size%??}" - total_image_size_number="${total_image_size%%.*}" - fi - fi + declare -g total_image_size_number="0" + docker_size_stats=$(docker system df --format "{{.Type}} {{.Size}}") + total_image_size=$(echo "${docker_size_stats}" | head -1 | awk '{print $2}' ) + echo "Image size is $total_image_size" + if [ ! -z "${total_image_size}" ] + then + if [ "${total_image_size: -2}" = "GB" ] + then + # Removes GB postfix + total_image_size_number="${total_image_size%??}" + # Removes any floating point pieces i.e. 2.4 = 2 so that it is interpreted + # as an integer + total_image_size_number="${total_image_size_number%%.*}" + elif [ "${total_image_size: -2}" = "MB" ] + then + # Removes MB postfix + total_image_size_number="${total_image_size%??}" + # Removes any floating point pieces i.e. 2.4 = 2 so that it is interpreted + # as an integer + total_image_size_number="${total_image_size_number%%.*}" + # Convert to GB + total_image_size_number=$(( "$total_image_size_number" / 1024)) + elif [ "${total_image_size: -2}" = "kB" ] + then + # Removes kB postfix + total_image_size_number="${total_image_size%??}" + # Removes any floating point pieces i.e. 2.4 = 2 so that it is interpreted + # as an integer + total_image_size_number="${total_image_size_number%%.*}" + # Convert to GB + total_image_size_number=$(( "$total_image_size_number" / 1048576)) + elif [ "${total_image_size: -1}" = "B" ] + then + # Removes B postfix + total_image_size_number="${total_image_size%?}" + # Removes any floating point pieces i.e. 2.4 = 2 so that it is interpreted + # as an integer + total_image_size_number="${total_image_size_number%%.*}" + # Convert to GB + total_image_size_number=$(( "$total_image_size_number" / 1073741824)) + else + echo "Size reported by 'docker system df --format {{.Type}} {{.Size}}' is" + echo "given in unsupported format $docker_size_stats" + echo "Purge script expects format 'X.X' or 'X' i.e. '4.5GB', '8MB', '0B'" + exit 1 + fi + fi } purge_oldest_image() { - oldest_image_id=$(docker image list --format "{{.ID}}" | tail -n1) - docker image rm "$oldest_image_id" -f + oldest_image_id=$(docker image list --format "{{.ID}}" | tail -n1) + docker image rm "$oldest_image_id" -f } get_size_of_all_images_in_GB while [ "$total_image_size_number" -gt "$local_DATAFED_CI_PURGE_THRESHOLD" ] do - purge_oldest_image - get_size_of_all_images_in_GB + purge_oldest_image + get_size_of_all_images_in_GB done diff --git a/scripts/compose_build_images.sh b/scripts/compose_build_images.sh index 302edb399..2d5eb5d5d 100755 --- a/scripts/compose_build_images.sh +++ b/scripts/compose_build_images.sh @@ -42,7 +42,6 @@ while [ : ]; do shift 1 ;; -b | --base-image) - echo "BASE" BASE_IMAGE="$2" shift 2 ;; @@ -55,6 +54,10 @@ while [ : ]; do esac done +echo "BASE_IMAGE: $BASE_IMAGE" +echo "BUILD_METADATA: $BUILD_METADATA" +echo "BUILD_REPO: $BUILD_REPO" + if [[ "$BUILD_METADATA" == "TRUE" ]] then if [ "$BASE_IMAGE" == "" ] @@ -81,19 +84,26 @@ then fi docker build -f \ "${PROJECT_ROOT}/core/docker/Dockerfile" \ - --build-arg DEPENDENCIES="datafed-dependencies" \ - --build-arg RUNTIME="datafed-runtime" \ + --build-arg DEPENDENCIES="datafed-dependencies:latest" \ + --build-arg RUNTIME="datafed-runtime:latest" \ "${PROJECT_ROOT}" \ -t datafed-core:latest docker build -f \ "${PROJECT_ROOT}/web/docker/Dockerfile" \ - --build-arg DEPENDENCIES="datafed-dependencies" \ + --build-arg DEPENDENCIES="datafed-dependencies:latest" \ + --build-arg RUNTIME="datafed-runtime" \ + --target ws-build \ + "${PROJECT_ROOT}" \ + -t datafed-web-build:latest + docker build -f \ + "${PROJECT_ROOT}/web/docker/Dockerfile" \ + --build-arg DEPENDENCIES="datafed-dependencies:latest" \ --build-arg RUNTIME="datafed-runtime" \ "${PROJECT_ROOT}" \ -t datafed-web:latest docker build -f \ "${PROJECT_ROOT}/docker/Dockerfile.foxx" \ - --build-arg DEPENDENCIES="datafed-dependencies" \ + --build-arg DEPENDENCIES="datafed-dependencies:latest" \ --build-arg RUNTIME="datafed-runtime" \ "${PROJECT_ROOT}" \ -t datafed-foxx:latest diff --git a/scripts/compose_cleanup_globus_files.sh b/scripts/compose_cleanup_globus_files.sh index 4bffefb10..b01cf592f 100755 --- a/scripts/compose_cleanup_globus_files.sh +++ b/scripts/compose_cleanup_globus_files.sh @@ -3,6 +3,8 @@ SCRIPT=$(realpath "$0") SOURCE=$(dirname "$SCRIPT") PROJECT_ROOT=$(realpath "${SOURCE}/..") +source "${SOURCE}/dependency_versions.sh" + # This script should be run after generating the .env file as it will pull # values from the .env file Help() @@ -70,4 +72,4 @@ fi sudo globus-connect-server node cleanup DATAFED_GCS_ROOT_NAME="$DATAFED_GCS_ROOT_NAME" \ -python3 "${PROJECT_ROOT}/scripts/globus/globus_cleanup.py" +"python${DATAFED_PYTHON_VERSION}" "${PROJECT_ROOT}/scripts/globus/globus_cleanup.py" diff --git a/scripts/compose_generate_env.sh b/scripts/compose_generate_env.sh index 575094476..93d99ee5a 100755 --- a/scripts/compose_generate_env.sh +++ b/scripts/compose_generate_env.sh @@ -113,9 +113,16 @@ fi if [ -z "${DATAFED_COMPOSE_REPO_DOMAIN}" ] then - # Make the repo domain equivalent to the COMPOSE DOMAIN unless it is specified - # explicitly - local_DATAFED_COMPOSE_REPO_DOMAIN="${local_DATAFED_COMPOSE_DOMAIN}" + + # Make the repo domain equivalent to the COMPOSE DOMAIN unless REPO_DOMAIN is + # specified explicitly, and it is not localhost, communication between the + # core container and the repo container will not resolve using localhost. + if [ "${local_DATAFED_COMPOSE_DOMAIN}" = "localhost" ] + then + local_DATAFED_COMPOSE_REPO_DOMAIN="" + else + local_DATAFED_COMPOSE_REPO_DOMAIN="${local_DATAFED_COMPOSE_DOMAIN}" + fi else local_DATAFED_COMPOSE_REPO_DOMAIN=$(printenv DATAFED_COMPOSE_REPO_DOMAIN) fi @@ -183,6 +190,13 @@ else local_DATAFED_COMPOSE_DATABASE_IP_ADDRESS=$(printenv DATAFED_COMPOSE_DATABASE_IP_ADDRESS) fi +if [ -z "${DATAFED_ENABLE_FOXX_TESTS}" ] +then + local_DATAFED_ENABLE_FOXX_TESTS="FALSE" +else + local_DATAFED_ENABLE_FOXX_TESTS=$(printenv DATAFED_ENABLE_FOXX_TESTS) +fi + if [ -z "${DATAFED_COMPOSE_DATABASE_PORT}" ] then local_DATAFED_COMPOSE_DATABASE_PORT="8529" @@ -250,6 +264,12 @@ else local_DATAFED_GLOBUS_SUBSCRIPTION=$(printenv DATAFED_GLOBUS_SUBSCRIPTION) fi +if [ -z "${DATAFED_CORE_LOG_LEVEL}" ] +then + local_DATAFED_CORE_LOG_LEVEL=3 +else + local_DATAFED_CORE_LOG_LEVEL=$(printenv DATAFED_CORE_LOG_LEVEL) +fi # Make the logs folder if it doesn't exist mkdir -p "${COMPOSE_ENV_DIR}/logs" @@ -270,6 +290,7 @@ DATAFED_HTTPS_SERVER_PORT=${local_DATAFED_COMPOSE_HTTPS_SERVER_PORT} DATAFED_DOMAIN=${local_DATAFED_COMPOSE_DOMAIN} DATAFED_UID=$(id -u) DATAFED_CONTAINER_LOG_PATH=${local_DATAFED_COMPOSE_CONTAINER_LOG_PATH} +DATAFED_CORE_LOG_LEVEL=${local_DATAFED_CORE_LOG_LEVEL} EOF fi @@ -285,6 +306,7 @@ DATAFED_WEB_KEY_PATH=/opt/datafed/keys/${local_DATAFED_WEB_KEY_NAME} DATAFED_DATABASE_PASSWORD=${local_DATAFED_COMPOSE_DATABASE_PASSWORD} DATAFED_DATABASE_IP_ADDRESS=${local_DATAFED_COMPOSE_DATABASE_IP_ADDRESS} DATAFED_DATABASE_PORT=${local_DATAFED_COMPOSE_DATABASE_PORT} +DATAFED_ENABLE_FOXX_TESTS=${local_DATAFED_ENABLE_FOXX_TESTS} EOF fi diff --git a/scripts/compose_generate_globus_files.sh b/scripts/compose_generate_globus_files.sh index 9afe99b4c..17f2e8f3b 100755 --- a/scripts/compose_generate_globus_files.sh +++ b/scripts/compose_generate_globus_files.sh @@ -3,6 +3,8 @@ SCRIPT=$(realpath "$0") SOURCE=$(dirname "$SCRIPT") PROJECT_ROOT=$(realpath "${SOURCE}/..") +source "${SOURCE}/dependency_versions.sh" + # This script should be run after generating the .env file as it will pull # values from the .env file Help() @@ -89,4 +91,4 @@ DATAFED_GLOBUS_CRED_FILE_PATH="$DATAFED_HOST_CRED_FILE_PATH" \ DATAFED_GLOBUS_CONTROL_PORT="$DATAFED_GLOBUS_CONTROL_PORT" \ DATAFED_GLOBUS_SUBSCRIPTION="$DATAFED_GLOBUS_SUBSCRIPTION" \ DATAFED_GCS_ROOT_NAME="$DATAFED_GCS_ROOT_NAME" \ - python3 "${PROJECT_ROOT}/scripts/globus/initialize_globus_endpoint.py" + "python${DATAFED_PYTHON_VERSION}" "${PROJECT_ROOT}/scripts/globus/initialize_globus_endpoint.py" diff --git a/scripts/dependency_install_functions.sh b/scripts/dependency_install_functions.sh index e16eacea0..1c00b9637 100644 --- a/scripts/dependency_install_functions.sh +++ b/scripts/dependency_install_functions.sh @@ -1,5 +1,5 @@ #!/bin/bash -SCRIPT=$(realpath "$0") +SCRIPT=$(realpath "$BASH_SOURCE[0]") SOURCE=$(dirname "$SCRIPT") source "${SOURCE}/dependency_versions.sh" PROJECT_ROOT=$(realpath "${SOURCE}/..") @@ -49,6 +49,11 @@ else fi fi +# WARNING: overwriting PATH can be very dangerous +# In Docker builds this must follow the pattern: +# PATH=":$PATH" +# Curly braces around PATH, like ${PATH} may pull from the host's PATH +# Please see StackOverflow answer: https://stackoverflow.com/a/38742545 if [[ ! -v PATH ]]; then PATH="$DATAFED_DEPENDENCIES_INSTALL_PATH/bin" else @@ -59,32 +64,98 @@ else fi fi +# Function to clean up multiple installation flag files with a given prefix +clean_install_flags() { + local install_path="${DATAFED_DEPENDENCIES_INSTALL_PATH}" + local prefix="$1" # The first argument is now the prefix + + # Validate that a prefix was provided + if [ -z "$prefix" ]; then + echo "Error: No prefix provided for clean_install_flags." >&2 + return 1 # Indicate an error + fi + + # Count files matching the pattern + local count=$(find "${install_path}" -maxdepth 1 -type f -name "${prefix}*" 2>/dev/null | wc -l) + + if [ "${count}" -gt 1 ]; then + echo "Warning: Found ${count} installation flag files with prefix '${prefix}'. Cleaning up..." + # Remove all files matching the pattern + find "${install_path}" -maxdepth 1 -type f -name "${prefix}*" -delete + echo "Removed all existing installation flag files with prefix '${prefix}'." + fi +} + +install_python() { + + local PYTHON_FLAG_PREFIX=".python_installed-" + clean_install_flags "$PYTHON_FLAG_PREFIX" + if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${PYTHON_FLAG_PREFIX}${DATAFED_PYTHON_VERSION}" ]; then + # Check if the deadsnakes repository has already been added to avoid issues with gpg + if ! grep -qr '^deb .\+deadsnakes' /etc/apt/sources.list.d/; then + "$SUDO_CMD" apt update + "$SUDO_CMD" apt install -y software-properties-common + "$SUDO_CMD" add-apt-repository -y ppa:deadsnakes/ppa + "$SUDO_CMD" apt update + fi + + "$SUDO_CMD" apt install -y "python${DATAFED_PYTHON_VERSION}" "python${DATAFED_PYTHON_VERSION}-dev" "python${DATAFED_PYTHON_VERSION}-venv" "python${DATAFED_PYTHON_VERSION}-distutils" + + touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${PYTHON_FLAG_PREFIX}${DATAFED_PYTHON_VERSION}" + fi +} + init_python() { + + if [[ ! -v DATAFED_PYTHON_DEPENDENCIES_DIR ]]; then + echo "DATAFED_PYTHON_DEPENDENCIES_DIR is not defined please make sure it is defined in the ${PROJECT_ROOT}/config/datafed.sh file." + exit 1 + else + if [[ -z "$DATAFED_PYTHON_DEPENDENCIES_DIR" ]]; then + echo "DATAFED_PYTHON_DEPENDENCIES_DIR is defined but is empty please make sure it is defined in ${PROJECT_ROOT}/config/datafed.sh file." + exit 1 + fi + fi + if [ ! -e "$DATAFED_DEPENDENCIES_INSTALL_PATH" ] || [ ! -d "$DATAFED_PYTHON_DEPENDENCIES_DIR" ]; then mkdir -p "$DATAFED_PYTHON_DEPENDENCIES_DIR" fi - python3 -m venv "${DATAFED_PYTHON_ENV}" + "python${DATAFED_PYTHON_VERSION}" -m venv "${DATAFED_PYTHON_ENV}" + # Make sure that pip is installed and upgraded + "python${DATAFED_PYTHON_VERSION}" -m ensurepip --upgrade } install_cmake() { - if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.cmake_installed-${DATAFED_CMAKE_VERSION}" ]; then - wget https://github.com/Kitware/CMake/releases/download/v${DATAFED_CMAKE_VERSION}/cmake-${DATAFED_CMAKE_VERSION}-Linux-x86_64.tar.gz - tar -xzvf "cmake-${DATAFED_CMAKE_VERSION}-Linux-x86_64.tar.gz" >/dev/null 2>&1 - cp -r "cmake-${DATAFED_CMAKE_VERSION}-Linux-x86_64/bin" "${DATAFED_DEPENDENCIES_INSTALL_PATH}" - cp -r "cmake-${DATAFED_CMAKE_VERSION}-Linux-x86_64/share" "${DATAFED_DEPENDENCIES_INSTALL_PATH}" + + local CMAKE_FLAG_PREFIX=".cmake_installed-" + clean_install_flags "$CMAKE_FLAG_PREFIX" + if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${CMAKE_FLAG_PREFIX}${DATAFED_CMAKE_VERSION}" ]; then + # Version 3.20 of cmake and onwards starting using all lower case in the package names, previos versions use a + # a capital L in the name. + wget https://github.com/Kitware/CMake/releases/download/v${DATAFED_CMAKE_VERSION}/cmake-${DATAFED_CMAKE_VERSION}-linux-x86_64.tar.gz + tar -xzvf "cmake-${DATAFED_CMAKE_VERSION}-linux-x86_64.tar.gz" >/dev/null 2>&1 + cp -r "cmake-${DATAFED_CMAKE_VERSION}-linux-x86_64/bin" "${DATAFED_DEPENDENCIES_INSTALL_PATH}" + cp -r "cmake-${DATAFED_CMAKE_VERSION}-linux-x86_64/share" "${DATAFED_DEPENDENCIES_INSTALL_PATH}" # Cleanup - rm -rf "cmake-${DATAFED_CMAKE_VERSION}-Linux-x86_64" - rm -rf "cmake-${DATAFED_CMAKE_VERSION}-Linux-x86_64.tar.gz" + rm -rf "cmake-${DATAFED_CMAKE_VERSION}-linux-x86_64" + rm -rf "cmake-${DATAFED_CMAKE_VERSION}-linux-x86_64.tar.gz" # Mark cmake as installed - touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.cmake_installed-${DATAFED_CMAKE_VERSION}" + touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${CMAKE_FLAG_PREFIX}${DATAFED_CMAKE_VERSION}" fi - export PATH="${DATAFED_DEPENDENCIES_INSTALL_PATH}/bin:${PATH}" + # WARNING: overwriting PATH can be very dangerous + # In Docker builds this must follow the pattern: + # PATH=":$PATH" + # Curly braces around PATH, like ${PATH} may pull from the host's PATH + # Please see StackOverflow answer: https://stackoverflow.com/a/38742545 + export PATH="${DATAFED_DEPENDENCIES_INSTALL_PATH}/bin:$PATH" } install_protobuf() { - if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.protobuf_installed-${DATAFED_PROTOBUF_VERSION}" ]; then + local PROTOBUF_FLAG_PREFIX=".protobuf_installed-" + clean_install_flags "$PROTOBUF_FLAG_PREFIX" + if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${PROTOBUF_FLAG_PREFIX}${DATAFED_PROTOBUF_VERSION}" ]; then local original_dir=$(pwd) cd "${PROJECT_ROOT}" if [ -d "${PROJECT_ROOT}/external/protobuf" ] @@ -128,12 +199,12 @@ install_protobuf() { cd python init_python source "${DATAFED_PYTHON_ENV}/bin/activate" - LD_LIBRARY_PATH="$LD_LIBRARY_PATH" PATH="$PATH" python3 -m pip install numpy - LD_LIBRARY_PATH="$LD_LIBRARY_PATH" PATH="$PATH" python3 setup.py build - LD_LIBRARY_PATH="$LD_LIBRARY_PATH" PATH="$PATH" python3 setup.py test + LD_LIBRARY_PATH="$LD_LIBRARY_PATH" PATH="$PATH" python${DATAFED_PYTHON_VERSION} -m pip install numpy tzdata + LD_LIBRARY_PATH="$LD_LIBRARY_PATH" PATH="$PATH" python${DATAFED_PYTHON_VERSION} setup.py build + LD_LIBRARY_PATH="$LD_LIBRARY_PATH" PATH="$PATH" python${DATAFED_PYTHON_VERSION} setup.py test # Because we have activaited a venv we don't want to use the --user flag # with the install command - LD_LIBRARY_PATH="$LD_LIBRARY_PATH" PATH="$PATH" python3 setup.py install + LD_LIBRARY_PATH="$LD_LIBRARY_PATH" PATH="$PATH" "python${DATAFED_PYTHON_VERSION}" setup.py install cd ../ # Cleanup build file with root ownership if [ -f build/install_manifest.txt ] @@ -143,27 +214,27 @@ install_protobuf() { cd "${PROJECT_ROOT}" # Mark protobuf as installed - touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.protobuf_installed-${DATAFED_PROTOBUF_VERSION}" + touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${PROTOBUF_FLAG_PREFIX}${DATAFED_PROTOBUF_VERSION}" cd "$original_dir" fi } install_libsodium() { - if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.libsodium_installed-${DATAFED_LIBSODIUM_VERSION}" ]; then + local LIBSODIUM_FLAG_PREFIX=".libsodium_installed-" + clean_install_flags "$LIBSODIUM_FLAG_PREFIX" + if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${LIBSODIUM_FLAG_PREFIX}${DATAFED_LIBSODIUM_VERSION}" ]; then local original_dir=$(pwd) if [ -d "${PROJECT_ROOT}/external/libsodium" ] then # sudo required because of egg file "$SUDO_CMD" rm -rf "${PROJECT_ROOT}/external/libsodium" fi - # Here we are using clone instead of submodule update, because submodule - # requires the .git folder exist and the current folder be considered a repo - # this creates problems in docker because each time a commit is made the - # .git folder contents are changed causing a fresh rebuild of all containers - git clone https://github.com/jedisct1/libsodium.git "${PROJECT_ROOT}/external/libsodium" - cd "${PROJECT_ROOT}/external/libsodium" - git checkout "$DATAFED_LIBSODIUM_VERSION" - ./autogen.sh + # Official documentation for libsodium indicates this is the preferred way to build libsodium. + # Using the git repo directly results in build instability because of additional network calls when running + # autogen.sh. + wget "https://download.libsodium.org/libsodium/releases/libsodium-${DATAFED_LIBSODIUM_VERSION}.tar.gz" -P "${PROJECT_ROOT}/external" + tar -xvzf "${PROJECT_ROOT}/external/libsodium-${DATAFED_LIBSODIUM_VERSION}.tar.gz" -C "${PROJECT_ROOT}/external/" + cd "${PROJECT_ROOT}/external/libsodium-${DATAFED_LIBSODIUM_VERSION}" # Build static ONLY!!!! # Note if zmq detects a shared sodium library it will grab it no matter what # --enable-shared=no must be set here @@ -175,15 +246,17 @@ install_libsodium() { else "$SUDO_CMD" make install fi - + # Mark libsodium as installed - touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.libsodium_installed-${DATAFED_LIBSODIUM_VERSION}" + touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${LIBSODIUM_FLAG_PREFIX}${DATAFED_LIBSODIUM_VERSION}" cd "$original_dir" fi } install_libzmq() { - if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.libzmq_installed-${DATAFED_LIBZMQ_VERSION}" ]; then + local LIBZMQ_FLAG_PREFIX=".libzmq_installed-" + clean_install_flags "$LIBZMQ_FLAG_PREFIX" + if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${LIBZMQ_FLAG_PREFIX}${DATAFED_LIBZMQ_VERSION}" ]; then local original_dir=$(pwd) if [ -d "${PROJECT_ROOT}/external/libzmq" ] then @@ -242,12 +315,14 @@ install_libzmq() { cd "$original_dir" # Mark libzmq as installed - touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.libzmq_installed-${DATAFED_LIBZMQ_VERSION}" + touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${LIBZMQ_FLAG_PREFIX}${DATAFED_LIBZMQ_VERSION}" fi } install_nlohmann_json() { - if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.nlohmann_json_installed-${DATAFED_NLOHMANN_JSON_VERSION}" ]; then + local NLOHMANN_FLAG_PREFIX=".nlohmann_json_installed-" + clean_install_flags "$NLOHMANN_FLAG_PREFIX" + if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${NLOHMANN_FLAG_PREFIX}${DATAFED_NLOHMANN_JSON_VERSION}" ]; then local original_dir=$(pwd) if [ -d "${PROJECT_ROOT}/external/json" ] then @@ -281,13 +356,15 @@ install_nlohmann_json() { fi # Mark nlohmann_json as installed - touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.nlohmann_json_installed-${DATAFED_NLOHMANN_JSON_VERSION}" + touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${NLOHMANN_FLAG_PREFIX}${DATAFED_NLOHMANN_JSON_VERSION}" cd "$original_dir" fi } install_json_schema_validator() { - if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.json_schema_validator_installed-${DATAFED_JSON_SCHEMA_VALIDATOR_VERSION}" ]; then + local NLOHMANN_SCHEMA_FLAG_PREFIX=".nlohmann_schema_validator_installed-" + clean_install_flags "$NLOHMANN_SCHEMA_FLAG_PREFIX" + if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${NLOHMANN_SCHEMA_FLAG_PREFIX}${DATAFED_JSON_SCHEMA_VALIDATOR_VERSION}" ]; then local original_dir=$(pwd) if [ -d "${PROJECT_ROOT}/external/json-schema-validator" ] then @@ -311,13 +388,15 @@ install_json_schema_validator() { # library, does not appear to support both targets at the same time, similar # to protobuf # Mark json-schema-validator as installed - touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.json_schema_validator_installed-${DATAFED_JSON_SCHEMA_VALIDATOR_VERSION}" + touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${NLOHMANN_SCHEMA_FLAG_PREFIX}${DATAFED_JSON_SCHEMA_VALIDATOR_VERSION}" cd "$original_dir" fi } install_gcs() { - if [ ! -e ".gcs_installed-${DATAFED_GLOBUS_VERSION}" ]; then + local GCS_FLAG_PREFIX=".gcs_installed-" + clean_install_flags "$GCS_FLAG_PREFIX" + if [ ! -e "${GCS_FLAG_PREFIX}${DATAFED_GLOBUS_VERSION}" ]; then "$SUDO_CMD" apt update "$SUDO_CMD" apt install -y curl git gnupg curl -LOs \ @@ -329,20 +408,22 @@ install_gcs() { "$SUDO_CMD" apt-get install globus-connect-server54 -y # Mark gcs as installed - touch ".gcs_installed-${DATAFED_GLOBUS_VERSION}" + touch "${GCS_FLAG_PREFIX}${DATAFED_GLOBUS_VERSION}" fi } install_nvm() { + local NVM_FLAG_PREFIX=".nvm_installed-" + clean_install_flags "$NVM_FLAG_PREFIX" # By default this will place NVM in $HOME/.nvm - if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.nvm_installed-${DATAFED_NVM_VERSION}" ]; then + if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${NVM_FLAG_PREFIX}${DATAFED_NVM_VERSION}" ]; then # By setting NVM_DIR beforehand when the scirpt is run it # will use it to set the install path export NVM_DIR="${DATAFED_DEPENDENCIES_INSTALL_PATH}/nvm" mkdir -p "${NVM_DIR}" curl -o- "https://raw.githubusercontent.com/nvm-sh/nvm/${DATAFED_NVM_VERSION}/install.sh" | bash # Mark nvm as installed - touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.nvm_installed-${DATAFED_NVM_VERSION}" + touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${NVM_FLAG_PREFIX}${DATAFED_NVM_VERSION}" else export NVM_DIR="${DATAFED_DEPENDENCIES_INSTALL_PATH}/nvm" fi @@ -372,8 +453,10 @@ install_ws_node_packages() { install_node() { + local NODE_FLAG_PREFIX=".node_installed-" + clean_install_flags "$NODE_FLAG_PREFIX" # By default this will place NVM in $HOME/.nvm - if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.node_installed-${DATAFED_NODE_VERSION}" ]; then + if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${NODE_FLAG_PREFIX}${DATAFED_NODE_VERSION}" ]; then local original_dir=$(pwd) if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.nvm_installed-${DATAFED_NVM_VERSION}" ]; then echo "You must first install nvm before installing node." @@ -384,12 +467,16 @@ install_node() { [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm nvm install "$DATAFED_NODE_VERSION" + nvm use "$DATAFED_NODE_VERSION" # Mark node as installed - touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.node_installed-${DATAFED_NODE_VERSION}" + touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${NODE_FLAG_PREFIX}${DATAFED_NODE_VERSION}" cd "$original_dir" else export NVM_DIR="${DATAFED_DEPENDENCIES_INSTALL_PATH}/nvm" + # Used by nvm + export NODE_VERSION="$DATAFED_NODE_VERSION" [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm + nvm use "$DATAFED_NODE_VERSION" fi } @@ -402,15 +489,17 @@ install_foxx_cli() { echo "You must first install node before installing foxx_cli" exit 1 fi + local FOXX_FLAG_PREFIX=".foxx_cli_installed-" + clean_install_flags "$FOXX_FLAG_PREFIX" # By default this will place NVM in $HOME/.nvm - if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.foxx_cli_installed" ]; then + if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${FOXX_FLAG_PREFIX}" ]; then local original_dir=$(pwd) export NVM_DIR="${DATAFED_DEPENDENCIES_INSTALL_PATH}/nvm" [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm export NODE_VERSION="$DATAFED_NODE_VERSION" "$NVM_DIR/nvm-exec" npm install --global foxx-cli --prefix "${DATAFED_DEPENDENCIES_INSTALL_PATH}/npm" # Mark foxx_cli as installed - touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.foxx_cli_installed" + touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${FOXX_FLAG_PREFIX}" cd "$original_dir" else export NVM_DIR="${DATAFED_DEPENDENCIES_INSTALL_PATH}/nvm" @@ -436,16 +525,18 @@ install_foxx_cli() { } install_arangodb() { - curl -OL https://download.arangodb.com/arangodb311/DEBIAN/Release.key + curl -OL https://download.arangodb.com/arangodb312/DEBIAN/Release.key "$SUDO_CMD" apt-key add - < Release.key - echo 'deb https://download.arangodb.com/arangodb311/DEBIAN/ /' | "$SUDO_CMD" tee /etc/apt/sources.list.d/arangodb.list + echo 'deb https://download.arangodb.com/arangodb312/DEBIAN/ /' | "$SUDO_CMD" tee /etc/apt/sources.list.d/arangodb.list "$SUDO_CMD" apt-get install apt-transport-https "$SUDO_CMD" apt-get update "$SUDO_CMD" apt-get install arangodb3 } install_openssl() { - if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.openssl_installed-${DATAFED_OPENSSL}" ]; then + local OPENSSL_FLAG_PREFIX=".openssl_installed-" + clean_install_flags "$OPENSSL_FLAG_PREFIX" + if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${OPENSSL_FLAG_PREFIX}${DATAFED_OPENSSL}" ]; then local original_dir=$(pwd) if [ -d "${PROJECT_ROOT}/external/openssl" ] then @@ -463,13 +554,15 @@ install_openssl() { "$SUDO_CMD" make install fi # Mark openssl as installed - touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.openssl_installed-${DATAFED_OPENSSL}" + touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${OPENSSL_FLAG_PREFIX}${DATAFED_OPENSSL}" cd "$original_dir" fi } install_libcurl() { - if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.libcurl_installed-${DATAFED_LIBCURL}" ]; then + local CURL_FLAG_PREFIX=".libcurl_installed-" + clean_install_flags "$CURL_FLAG_PREFIX" + if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${CURL_FLAG_PREFIX}${DATAFED_LIBCURL}" ]; then local original_dir=$(pwd) if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.zlib_installed-${DATAFED_ZLIB_VERSION}" ]; then echo "You must first install zlib before installing libcurl packages" @@ -514,13 +607,15 @@ install_libcurl() { fi # Mark libcurl as installed - touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.libcurl_installed-${DATAFED_LIBCURL}" + touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${CURL_FLAG_PREFIX}${DATAFED_LIBCURL}" cd "$original_dir" fi } install_zlib() { - if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.zlib_installed-${DATAFED_ZLIB_VERSION}" ]; then + local ZLIB_FLAG_PREFIX=".zlib_installed-" + clean_install_flags "$ZLIB_FLAG_PREFIX" + if [ ! -e "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${ZLIB_FLAG_PREFIX}${DATAFED_ZLIB_VERSION}" ]; then local original_dir=$(pwd) if [ -d "${PROJECT_ROOT}/external/zlib" ] then @@ -540,7 +635,7 @@ install_zlib() { fi # Mark libcurl as installed - touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/.zlib_installed-${DATAFED_ZLIB_VERSION}" + touch "${DATAFED_DEPENDENCIES_INSTALL_PATH}/${ZLIB_FLAG_PREFIX}${DATAFED_ZLIB_VERSION}" cd "$original_dir" fi } diff --git a/scripts/dependency_versions.sh b/scripts/dependency_versions.sh index 2ada763da..0ed936fa5 100644 --- a/scripts/dependency_versions.sh +++ b/scripts/dependency_versions.sh @@ -1,9 +1,9 @@ # Versions -DATAFED_CMAKE_VERSION="3.17.5" +DATAFED_CMAKE_VERSION="3.31.6" DATAFED_GLOBUS_VERSION="6.0.31-1" -DATAFED_JSON_SCHEMA_VALIDATOR_VERSION="2.1.0" -DATAFED_NLOHMANN_JSON_VERSION="3.10.2" +DATAFED_JSON_SCHEMA_VALIDATOR_VERSION="2.3.0" +DATAFED_NLOHMANN_JSON_VERSION="3.12.0" DATAFED_LIBSODIUM_VERSION="1.0.18" # this version is different from above due to the fact libsodium names its shared library diffrently than the actual api version DATAFED_LIB_LIBSODIUM_VERSION="23.3.0" @@ -14,14 +14,15 @@ DATAFED_LIB_ZMQCPP_VERSION="4.10.0" DATAFED_NVM_VERSION="v0.39.7" DATAFED_NODE_VERSION="v14.21.3" DATAFED_NVM_VERSION="v0.39.7" +DATAFED_PYTHON_VERSION="3.9" # Git tag -DATAFED_PROTOBUF_VERSION="25.2" +DATAFED_PROTOBUF_VERSION="25.7" # Dynamic library extension .so.{DATAFED_FULL_PROTOBUF_VERSION} -DATAFED_DYNAMIC_LIBRARY_PROTOBUF_VERSION="25.2.0" +DATAFED_DYNAMIC_LIBRARY_PROTOBUF_VERSION="25.7.0" # Full version -DATAFED_FULL_PROTOBUF_VERSION="4.25.2" -DATAFED_LIBCURL="7.88.1" -DATAFED_LIBCURL_URL="https://github.com/curl/curl/releases/download/curl-7_88_1/curl-7.88.1.tar.gz" +DATAFED_FULL_PROTOBUF_VERSION="4.25.7" +DATAFED_LIBCURL="8.11.0" +DATAFED_LIBCURL_URL="https://github.com/curl/curl/releases/download/curl-8_11_0/curl-8.11.0.tar.gz" DATAFED_OPENSSL="1.1.1" DATAFED_OPENSSL_COMMIT="e04bd34" DATAFED_BOOST="1.71.0" diff --git a/scripts/generate_authz_config.sh b/scripts/generate_authz_config.sh index f8018a59e..c945a3f14 100755 --- a/scripts/generate_authz_config.sh +++ b/scripts/generate_authz_config.sh @@ -124,7 +124,7 @@ pub_key=${DATAFED_INSTALL_PATH}/keys/datafed-repo-key.pub priv_key=${DATAFED_INSTALL_PATH}/keys/datafed-repo-key.priv log_path=${local_DATAFED_LOG_PATH}/datafed-gsi-authz.log user=$local_DATAFED_AUTHZ_USER -globus-collection-path=$local_DATAFED_GCS_COLLECTION_BASE_PATH +globus_collection_path=$local_DATAFED_GCS_COLLECTION_BASE_PATH EOF echo diff --git a/scripts/generate_core_config.sh b/scripts/generate_core_config.sh index 59fac623a..3c20305fe 100755 --- a/scripts/generate_core_config.sh +++ b/scripts/generate_core_config.sh @@ -47,8 +47,19 @@ Help() } # Set defaults use environment variables by default -local_DATAFED_CORE_CLIENT_THREADS=2 -local_DATAFED_CORE_TASK_THREADS=2 +if [ -z "${DATAFED_CORE_CLIENT_THREADS}" ] +then + local_DATAFED_CORE_CLIENT_THREADS="2" +else + local_DATAFED_CORE_CLIENT_THREADS=$(printenv DATAFED_CORE_CLIENT_THREADS) +fi + +if [ -z "${DATAFED_CORE_TASK_THREADS}" ] +then + local_DATAFED_CORE_TASK_THREADS="2" +else + local_DATAFED_CORE_TASK_THREADS=$(printenv DATAFED_CORE_TASK_THREADS) +fi if [ -z "${DATAFED_CRED_DIR}" ] then @@ -86,6 +97,13 @@ else local_DATAFED_DATABASE_PASSWORD=$(printenv DATAFED_DATABASE_PASSWORD) fi +if [ -z "${DATAFED_CORE_LOG_LEVEL}" ] +then + local_DATAFED_CORE_LOG_LEVEL=3 +else + local_DATAFED_CORE_LOG_LEVEL=$(printenv DATAFED_CORE_LOG_LEVEL) +fi + VALID_ARGS=$(getopt -o ht:c:f:a:s:i:u:p --long 'help',threads-task:,cred-dir:,threads-client:,database-ip-address:,globus-secret:,globus-id:,database-user:,database-password: -- "$@") if [[ $? -ne 0 ]]; then exit 1; @@ -208,6 +226,14 @@ db-pass=$local_DATAFED_DATABASE_PASSWORD # with what is in the datafed-ws.cfg file client-id=$local_DATAFED_GLOBUS_APP_ID client-secret=$local_DATAFED_GLOBUS_APP_SECRET +# Below sets the log level of the application +# 0 - Critical +# 1 - Error +# 2 - Warning +# 3 - Info (Default) +# 4 - Debug +# 5 - Trace +log-level=$local_DATAFED_CORE_LOG_LEVEL EOF echo diff --git a/scripts/generate_repo_config.sh b/scripts/generate_repo_config.sh index e10ce7c42..d99c7d12d 100755 --- a/scripts/generate_repo_config.sh +++ b/scripts/generate_repo_config.sh @@ -30,7 +30,6 @@ Help() echo "-g, --globus-collection-base-path The Globus (POSIX) Base path to the Guest Collection." } -local_DATAFED_PORT="7512" if [ -z "${DATAFED_DOMAIN}" ] then local_DATAFED_DOMAIN="datafed.ornl.gov" @@ -54,6 +53,14 @@ else local_DATAFED_LOG_PATH=$(printenv DATAFED_DEFAULT_LOG_PATH) fi +local_DATAFED_SERVER_PORT="" +if [ -z "${DATAFED_SERVER_PORT}" ] +then + local_DATAFED_SERVER_PORT="7512" +else + local_DATAFED_SERVER_PORT=$(printenv DATAFED_SERVER_PORT) +fi + local_DATAFED_CRED_DIR="${DATAFED_INSTALL_PATH}/keys/" local_DATAFED_REPO_PORT="9000" local_DATAFED_REPO_THREADS=2 @@ -113,7 +120,7 @@ CONFIG_FILE_NAME="datafed-repo.cfg" # same port listed in the datafed-repo.cfg file. cat << EOF > "$PATH_TO_CONFIG_DIR/$CONFIG_FILE_NAME" cred-dir=$local_DATAFED_CRED_DIR -server=tcp://$local_DATAFED_DOMAIN:${local_DATAFED_PORT} +server=tcp://$local_DATAFED_DOMAIN:${local_DATAFED_SERVER_PORT} port=$local_DATAFED_REPO_PORT threads=$local_DATAFED_REPO_THREADS globus-collection-path=$local_DATAFED_GCS_COLLECTION_BASE_PATH diff --git a/scripts/globus/setup_collection_directory.sh b/scripts/globus/setup_collection_directory.sh new file mode 100755 index 000000000..2527072e5 --- /dev/null +++ b/scripts/globus/setup_collection_directory.sh @@ -0,0 +1,148 @@ +#!/bin/bash +# Description +# +# This script sets up a collection directory for DataFed. +# It checks for necessary permissions and environment variables, +# creates the directory if it doesn't exist, and sets the correct ownership. +set -euf -o pipefail + +readonly SCRIPT=$(realpath "${BASH_SOURCE}") +readonly SOURCE=$(dirname "$SCRIPT") +readonly PROJECT_ROOT=$(realpath "${SOURCE}"/../../) +readonly FILENAME=$(basename "${BASH_SOURCE}") + +log_error() { echo "ERROR: $*" >&2; } +log_info() { echo "INFO: $*"; } +log_success() { echo "SUCCESS: $*"; } + +############################################################ +# Functions # +############################################################ +Help() { + echo "${FILENAME} sets up a collection directory for DataFed." + echo + echo "Syntax: ${FILENAME} [-h|c]" + echo "options:" + echo "-h, --help Print this help message." + echo "-c, --compose-directory-name The name of the compose directory your .env file is in." +} + +list_compose_directories() { + echo "Available compose directories:" + if composes=$(ls -l "${PROJECT_ROOT}/compose/" | grep "^d"); then + echo "$composes" + else + echo "No compose directories found." + fi +} + +parse_arguments() { + local VALID_ARGS + VALID_ARGS=$(getopt -o hc: --long help,compose-directory-name: -- "$@") + if [[ $# -eq 0 ]]; then + Help + exit 1 + fi + eval set -- "$VALID_ARGS" + + while true; do + case "$1" in + -h | --help) + Help + exit 0 + ;; + -c | --compose-directory-name) + COMPOSE_DIR="$2" + shift 2 + ;; + --) + shift + break + ;; + *) + log_error "Invalid option" + exit 1 + ;; + esac + done + + if [ -z "${COMPOSE_DIR:-}" ]; then + log_error "-c|--compose-directory-name is required" + exit 1 + fi +} + +validate_environment() { + local env_file="${PROJECT_ROOT}/compose/${COMPOSE_DIR}/.env" + + if [ ! -d "${PROJECT_ROOT}/compose/${COMPOSE_DIR}" ]; then + log_error "Compose directory ${COMPOSE_DIR} does not exist" + list_compose_directories + exit 1 + fi + + if [ -f "${env_file}" ]; then + source <(grep -v '^#' "${env_file}") + log_info "Loaded environment variables from ${env_file}" + else + log_error ".env file not found in ${COMPOSE_DIR}" + exit 1 + fi + + local required_vars=("DATAFED_UID" "DATAFED_HOST_COLLECTION_MOUNT" "DATAFED_REPO_ID_AND_DIR") + for var in "${required_vars[@]}"; do + if [ -z "${!var:-}" ]; then + log_error "${var} is not set" + exit 1 + fi + done + + if ! [[ "${DATAFED_UID}" =~ ^[0-9]+$ ]]; then + log_error "DATAFED_UID must be a valid numeric user ID" + exit 1 + fi +} + +check_permissions() { + local host_collection_dir="${DATAFED_HOST_COLLECTION_MOUNT}/${DATAFED_REPO_ID_AND_DIR}" + + if [ ! -w "$(dirname "${DATAFED_HOST_COLLECTION_MOUNT}")" ]; then + log_error "Insufficient permissions to create ${host_collection_dir}" + exit 1 + fi + + if [ -d "${DATAFED_HOST_COLLECTION_MOUNT}" ]; then + log_info "Directory ${DATAFED_HOST_COLLECTION_MOUNT} exists, validating UID ownership" + local dir_uid + dir_uid=$(stat -c %u "${DATAFED_HOST_COLLECTION_MOUNT}") + + if [ "${dir_uid}" -ne "${DATAFED_UID}" ]; then + log_error "Directory UID doesn't match expected UID ${DATAFED_UID}" + echo "Please see an administrator to chown the directory, or choose another directory" + exit 1 + fi + fi +} + +setup_directory() { + local host_collection_dir="${DATAFED_HOST_COLLECTION_MOUNT}/${DATAFED_REPO_ID_AND_DIR}" + + if [ -d "${host_collection_dir}" ]; then + log_info "Directory ${host_collection_dir} already exists, skipping creation" + else + mkdir -p "${host_collection_dir}" + log_success "Created new collection directory ${host_collection_dir}" + fi +} + +############################################################ +# Driver # +############################################################ +main() { + parse_arguments "$@" + validate_environment + check_permissions + setup_directory +} + +main "$@" diff --git a/scripts/globus/setup_globus.sh b/scripts/globus/setup_globus.sh index 876f17ee1..523bb8d8d 100755 --- a/scripts/globus/setup_globus.sh +++ b/scripts/globus/setup_globus.sh @@ -1,6 +1,10 @@ #!/bin/env bash -set -uf -o pipefail +# The setup script must throw an error if there is a problem. This has +# implications on the CI pipelines as well as the ability to detect problems +# when standing up datafed. +# -e turns on failures if script hits a problem +set -euf -o pipefail SCRIPT=$(realpath "$0") SOURCE=$(dirname "$SCRIPT") @@ -59,7 +63,7 @@ GATEWAY_NAME="${DATAFED_GCS_ROOT_NAME} Storage Gateway" COLLECTION_NAME="${DATAFED_GCS_ROOT_NAME} Collection Mapped" GUEST_COLLECTION_NAME="${DATAFED_GCS_ROOT_NAME} Collection Guest" -gateway_line=$( globus-connect-server storage-gateway list | grep "$GATEWAY_NAME" ) +gateway_line=$( globus-connect-server storage-gateway list | grep "$GATEWAY_NAME" || echo "") echo "$DATAFED_GLOBUS_REPO_USER" cat << EOF > mapping.json @@ -113,7 +117,7 @@ fi mkdir -p "${DATAFED_GCS_COLLECTION_ROOT_PATH}/${DATAFED_REPO_ID_AND_DIR}/user" mkdir -p "${DATAFED_GCS_COLLECTION_ROOT_PATH}/${DATAFED_REPO_ID_AND_DIR}/project" -collection_line=$( globus-connect-server collection list | grep "$COLLECTION_NAME" ) +collection_line=$( globus-connect-server collection list | grep "$COLLECTION_NAME" || echo "") spaces_in_name=$(echo $GATEWAY_NAME | awk '{print gsub("[ \t]",""); exit}') columns=$(( $spaces_in_name + 3 )) diff --git a/scripts/install_authz_dependencies.sh b/scripts/install_authz_dependencies.sh index a63e37314..21839870e 100755 --- a/scripts/install_authz_dependencies.sh +++ b/scripts/install_authz_dependencies.sh @@ -11,11 +11,13 @@ source "${PROJECT_ROOT}/scripts/utils.sh" source "${PROJECT_ROOT}/scripts/dependency_install_functions.sh" packages=("host" "libtool" "build-essential" "g++" "gcc" "autoconf" - "automake" "make" "git" "python3-pkg-resources" "python3-pip" "pkg-config" - "libglobus-common-dev" "wget" "jq" "sudo" "libboost-all-dev" "python3-venv") + "automake" "make" "git" "pkg-config" + "libglobus-common-dev" "wget" "jq" "sudo" "libboost-all-dev" "python${DATAFED_PYTHON_VERSION}" "python${DATAFED_PYTHON_VERSION}-venv" "libgssapi-krb5-2") pip_packages=("setuptools" "distro" "jwt" "globus_sdk") externals=("cmake" "protobuf" "libsodium" "libzmq" ) +install_python + local_UNIFY=false if [ $# -eq 1 ]; then @@ -47,8 +49,7 @@ if [[ $local_UNIFY = false ]]; then "$SUDO_CMD" apt-get install -y "${packages[@]}" init_python source "${DATAFED_PYTHON_ENV}/bin/activate" - python3 -m pip install --upgrade pip - python3 -m pip install "${pip_packages[@]}" + "python${DATAFED_PYTHON_VERSION}" -m pip install "${pip_packages[@]}" for ext in "${externals[@]}"; do install_dep_by_name "$ext" diff --git a/scripts/install_client_dependencies.sh b/scripts/install_client_dependencies.sh index 2c475fa4b..0638f87ff 100755 --- a/scripts/install_client_dependencies.sh +++ b/scripts/install_client_dependencies.sh @@ -10,7 +10,10 @@ PROJECT_ROOT=$(realpath "${SOURCE}/..") source "${PROJECT_ROOT}/scripts/utils.sh" source "${PROJECT_ROOT}/scripts/dependency_install_functions.sh" -packages=("python3-pkg-resources" "python3-pip" "pkg-config" "python3-venv") +packages=("pkg-config" "python${DATAFED_PYTHON_VERSION}" "python${DATAFED_PYTHON_VERSION}-venv") +pip_packages=("setuptools") + +install_python sudo_command # This script will install all of the dependencies needed by DataFed 1.0 @@ -20,7 +23,8 @@ sudo_command init_python source "${DATAFED_PYTHON_ENV}/bin/activate" -python3 -m pip install -r "${PROJECT_ROOT}/python/datafed_pkg/requirements.txt" +"python${DATAFED_PYTHON_VERSION}" -m pip install "${pip_packages[@]}" +"python${DATAFED_PYTHON_VERSION}" -m pip install -r "${PROJECT_ROOT}/python/datafed_pkg/requirements.txt" install_protobuf cd ~ diff --git a/scripts/install_core_dependencies.sh b/scripts/install_core_dependencies.sh index c79ee55d2..bf7ea6316 100755 --- a/scripts/install_core_dependencies.sh +++ b/scripts/install_core_dependencies.sh @@ -10,12 +10,14 @@ PROJECT_ROOT=$(realpath ${SOURCE}/..) source "${PROJECT_ROOT}/scripts/utils.sh" source "${PROJECT_ROOT}/scripts/dependency_install_functions.sh" -packages=("libtool" "build-essential" "g++" "gcc" "make" "libboost-all-dev" "pkg-config" "autoconf" "automake" "unzip" "wget" "rapidjson-dev" "libkrb5-dev" "git" "python3-pkg-resources" "python3-pip" "python3-venv") +packages=("libtool" "build-essential" "g++" "gcc" "make" "libboost-all-dev" "pkg-config" "autoconf" "automake" "unzip" "wget" "rapidjson-dev" "libkrb5-dev" "git" "python${DATAFED_PYTHON_VERSION}" "python${DATAFED_PYTHON_VERSION}-venv") pip_packages=("setuptools") # NOTE the order matters here externals=("cmake" "nlohmann_json" "json_schema_validator" "protobuf" "libsodium" "libzmq" "libopenssl" "zlib" "libcurl") +install_python + local_UNIFY=false if [ $# -eq 1 ]; then @@ -46,8 +48,8 @@ if [[ $local_UNIFY = false ]]; then "$SUDO_CMD" apt-get install -y "${packages[@]}" init_python source "${DATAFED_PYTHON_ENV}/bin/activate" - python3 -m pip install --upgrade pip - python3 -m pip install "${pip_packages[@]}" + "python${DATAFED_PYTHON_VERSION}" -m pip install --upgrade pip + "python${DATAFED_PYTHON_VERSION}" -m pip install "${pip_packages[@]}" for ext in "${externals[@]}"; do install_dep_by_name "$ext" diff --git a/scripts/install_dependencies.sh b/scripts/install_dependencies.sh index 4ae49ac84..0fbdacdbe 100755 --- a/scripts/install_dependencies.sh +++ b/scripts/install_dependencies.sh @@ -117,7 +117,7 @@ if [ ${#all_pip_packages_array[@]} -gt 0 ]; then echo "DEPENDENCIES (${all_pip_packages_array[@]})" init_python source "${DATAFED_PYTHON_ENV}/bin/activate" - python3 -m pip install "${all_pip_packages_array[@]}" + "python${DATAFED_PYTHON_VERSION}" -m pip install "${all_pip_packages_array[@]}" fi all_externals=$(cat "$ext_file_path") diff --git a/scripts/install_docs_dependencies.sh b/scripts/install_docs_dependencies.sh index 06ee7c3de..179382bad 100755 --- a/scripts/install_docs_dependencies.sh +++ b/scripts/install_docs_dependencies.sh @@ -10,7 +10,7 @@ PROJECT_ROOT=$(realpath ${SOURCE}/..) source "${PROJECT_ROOT}/scripts/utils.sh" source "${PROJECT_ROOT}/scripts/dependency_install_functions.sh" -packages=("g++" "gcc" "make" "python3-pkg-resources" "python3-pip" "pkg-config" "python3-venv") +packages=("g++" "gcc" "make" "pkg-config" "python${DATAFED_PYTHON_VERSION}" "python${DATAFED_PYTHON_VERSION}-venv") externals=("cmake" "protobuf") pip_packages=("setuptools" "sphinx" "sphinx-rtd-theme" "sphinx-autoapi") @@ -44,8 +44,8 @@ if [[ $local_UNIFY = false ]]; then "$SUDO_CMD" apt-get install -y "${packages[@]}" init_python source "${DATAFED_PYTHON_ENV}/bin/activate" - python3 -m pip install --upgrade pip - python3 -m pip install "${pip_packages[@]}" + "python${DATAFED_PYTHON_VERSION}" -m pip install --upgrade pip + "python${DATAFED_PYTHON_VERSION}" -m pip install "${pip_packages[@]}" for ext in "${externals[@]}"; do install_dep_by_name "$ext" diff --git a/scripts/install_end_to_end_test_dependencies.sh b/scripts/install_end_to_end_test_dependencies.sh index a4627aceb..ea1e5bddf 100755 --- a/scripts/install_end_to_end_test_dependencies.sh +++ b/scripts/install_end_to_end_test_dependencies.sh @@ -11,7 +11,7 @@ source "${PROJECT_ROOT}/scripts/utils.sh" source "${PROJECT_ROOT}/scripts/dependency_install_functions.sh" packages=("libtool" "build-essential" "g++" "gcc" "make" "libboost-all-dev" "pkg-config" "autoconf" "automake" "unzip" "libcurl4-openssl-dev" "wget" - "rapidjson-dev" "libkrb5-dev" "git" "python3-pkg-resources" "python3-pip" "python3-venv" "libssl-dev") + "rapidjson-dev" "libkrb5-dev" "git" "python${DATAFED_PYTHON_VERSION}" "python${DATAFED_PYTHON_VERSION}-venv" "libssl-dev") pip_packages=("setuptools") @@ -47,8 +47,8 @@ if [[ $local_UNIFY = false ]]; then "$SUDO_CMD" apt-get install -y "${packages[@]}" init_python source "${DATAFED_PYTHON_ENV}/bin/activate" - python3 -m pip install --upgrade pip - python3 -m pip install "${pip_packages[@]}" + "python${DATAFED_PYTHON_VERSION}" -m pip install --upgrade pip + "python${DATAFED_PYTHON_VERSION}" -m pip install "${pip_packages[@]}" for ext in "${externals[@]}"; do install_dep_by_name "$ext" diff --git a/scripts/install_foxx.sh b/scripts/install_foxx.sh index e755a3720..75ea608c6 100755 --- a/scripts/install_foxx.sh +++ b/scripts/install_foxx.sh @@ -1,8 +1,17 @@ #!/bin/bash -# -e has been removed so that if an error occurs the PASSWORD File is deleted and not left lying around -# -u has been removed because we have no guarantees that the env variables are defined -set -f -o pipefail +# History +# +# -e has been added back, password file deletion should be handled by another +# means such as the CI after script section. If the API fails to install, it +# could lead to improper testing the CI env. +# +# -e has been removed so that if an error occurs the PASSWORD File is deleted +# and not left lying around +# +# -u has been removed because we have no guarantees that the env variables are +# defined +set -ef -o pipefail SCRIPT=$(realpath "$0") SOURCE=$(dirname "$SCRIPT") @@ -138,7 +147,7 @@ fi basic_auth="$local_DATABASE_USER:$local_DATAFED_DATABASE_PASSWORD" url="http://${local_DATAFED_DATABASE_HOST}:${local_DATABASE_PORT}/_api/database/user" # Do not output to /dev/null we need the output -code=$(curl -s -o /dev/null -w "%{http_code}" --user "$basic_auth" "$url") +code=$(LD_LIBRARY_PATH="${DATAFED_DEPENDENCIES_INSTALL_PATH}:$LD_LIBRARY_PATH" curl -s -o /dev/null -w "%{http_code}" --user "$basic_auth" "$url") if [[ "$code" != "200" ]]; then echo "Error detected in attempting to connect to database at $url" @@ -149,7 +158,7 @@ fi url2="http://${local_DATAFED_DATABASE_HOST}:${local_DATABASE_PORT}/_api/database" # We are now going to initialize the DataFed database in Arango, but only if sdms database does # not exist -output=$(curl -s -i --dump - --user "$basic_auth" "$url2") +output=$(LD_LIBRARY_PATH="${DATAFED_DEPENDENCIES_INSTALL_PATH}:$LD_LIBRARY_PATH" curl -s -i --user "$basic_auth" "$url2") echo "Output: $output" @@ -223,7 +232,7 @@ echo "$local_DATAFED_DATABASE_PASSWORD" > "${PATH_TO_PASSWD_FILE}" echo "$FOUND_API" - RESULT=$(curl -s http://${local_DATAFED_DATABASE_HOST}:8529/_db/sdms/api/${local_FOXX_MAJOR_API_VERSION}/version) + RESULT=$(LD_LIBRARY_PATH="${DATAFED_DEPENDENCIES_INSTALL_PATH}:$LD_LIBRARY_PATH" curl -s http://${local_DATAFED_DATABASE_HOST}:8529/_db/sdms/api/${local_FOXX_MAJOR_API_VERSION}/version) CODE=$(echo "${RESULT}" | jq '.code' ) echo "Code is $CODE" if [ -z "${FOUND_API}" ] @@ -233,6 +242,7 @@ echo "$local_DATAFED_DATABASE_PASSWORD" > "${PATH_TO_PASSWD_FILE}" then INSTALL_API="TRUE" # Remove the api at this point + # WARNING Foxx and arangosh arguments differ --server is used for Foxx not --server.endpoint "${FOXX_PREFIX}foxx" remove \ "/api/${local_FOXX_MAJOR_API_VERSION}" \ --server "http://${local_DATAFED_DATABASE_HOST}:${local_DATABASE_PORT}" \ @@ -244,6 +254,7 @@ echo "$local_DATAFED_DATABASE_PASSWORD" > "${PATH_TO_PASSWD_FILE}" echo "$RESULT" if [ "${INSTALL_API}" == "TRUE" ] then + # WARNING Foxx and arangosh arguments differ --server is used for Foxx not --server.endpoint "${FOXX_PREFIX}foxx" install \ --server "http://${local_DATAFED_DATABASE_HOST}:${local_DATABASE_PORT}" \ -u "${local_DATABASE_USER}" \ @@ -253,6 +264,7 @@ echo "$local_DATAFED_DATABASE_PASSWORD" > "${PATH_TO_PASSWD_FILE}" "${PROJECT_ROOT}/core/database/foxx/" else echo "DataFed Foxx Services have already been uploaded, replacing to ensure consisency" + # WARNING Foxx and arangosh arguments differ --server is used for Foxx not --server.endpoint "${FOXX_PREFIX}foxx" replace \ --server "http://${local_DATAFED_DATABASE_HOST}:${local_DATABASE_PORT}" \ -u "${local_DATABASE_USER}" \ diff --git a/scripts/install_python_client_dependencies.sh b/scripts/install_python_client_dependencies.sh index a8467a3f0..aa627e2e5 100755 --- a/scripts/install_python_client_dependencies.sh +++ b/scripts/install_python_client_dependencies.sh @@ -17,7 +17,7 @@ sudo_command "$SUDO_CMD" dpkg --configure -a "$SUDO_CMD" apt-get install -y libtool build-essential g++ gcc make libboost-all-dev \ pkg-config autoconf automake unzip libcurl4-openssl-dev wget \ -rapidjson-dev libkrb5-dev git python3-pkg-resources python3-pip python3-venv libssl-dev +rapidjson-dev libkrb5-dev git "python${DATAFED_PYTHON_VERSION}" "python${DATAFED_PYTHON_VERSION}-venv" libssl-dev cd ~ install_cmake @@ -27,8 +27,8 @@ cd ~ init_python source "${DATAFED_PYTHON_ENV}/bin/activate" -python3 -m pip install --upgrade pip -python3 -m pip install setuptools +"python${DATAFED_PYTHON_VERSION}" -m pip install --upgrade pip +"python${DATAFED_PYTHON_VERSION}" -m pip install setuptools install_protobuf cd ~ diff --git a/scripts/install_repo_dependencies.sh b/scripts/install_repo_dependencies.sh index 723a3ad81..0bff1c7d8 100755 --- a/scripts/install_repo_dependencies.sh +++ b/scripts/install_repo_dependencies.sh @@ -10,10 +10,12 @@ PROJECT_ROOT=$(realpath ${SOURCE}/..) source "${PROJECT_ROOT}/scripts/utils.sh" source "${PROJECT_ROOT}/scripts/dependency_install_functions.sh" -packages=("libtool" "wget" "build-essential" "g++" "gcc" "libboost-all-dev" "pkg-config" "autoconf" "automake" "make" "unzip" "git" "python3-pkg-resources" "python3-pip" "python3-venv") +packages=("libtool" "wget" "build-essential" "g++" "gcc" "libboost-all-dev" "pkg-config" "autoconf" "automake" "make" "unzip" "git" "python${DATAFED_PYTHON_VERSION}" "python${DATAFED_PYTHON_VERSION}-venv") pip_packages=("setuptools") externals=("cmake" "protobuf" "libsodium" "libzmq") +install_python + local_UNIFY=false if [ $# -eq 1 ]; then @@ -46,8 +48,8 @@ if [[ $local_UNIFY = false ]]; then init_python source "${DATAFED_PYTHON_ENV}/bin/activate" - python3 -m pip install --upgrade pip - python3 -m pip install "${pip_packages[@]}" + "python${DATAFED_PYTHON_VERSION}" -m pip install --upgrade pip + "python${DATAFED_PYTHON_VERSION}" -m pip install "${pip_packages[@]}" for ext in "${externals[@]}"; do install_dep_by_name "$ext" diff --git a/scripts/install_ws_dependencies.sh b/scripts/install_ws_dependencies.sh index 5f124a540..d28e30b5b 100755 --- a/scripts/install_ws_dependencies.sh +++ b/scripts/install_ws_dependencies.sh @@ -11,9 +11,11 @@ source "${PROJECT_ROOT}/scripts/utils.sh" source "${SOURCE}/dependency_versions.sh" source "${PROJECT_ROOT}/scripts/dependency_install_functions.sh" -packages=("curl" "python3" "g++" "make" "wget") +packages=("curl" "python${DATAFED_PYTHON_VERSION}" "g++" "make" "wget") externals=("cmake" "nvm" "node" "ws_node_packages") +install_python + Help() { echo "$(basename $0) install web dependencies." diff --git a/tests/end-to-end/setup.sh b/tests/end-to-end/setup.sh index 2b9b55926..96cad4d13 100755 --- a/tests/end-to-end/setup.sh +++ b/tests/end-to-end/setup.sh @@ -166,8 +166,7 @@ echo "HTTP_CODE: ${HTTP_CODE}" FIRST_INT=${HTTP_CODE:0:1} if [ "${FIRST_INT}" -ne "2" ] then - response=$( curl --user "${basic_auth}" -X GET - "http://${local_DATAFED_DATABASE_HOST}:${local_DATAFED_DATABASE_PORT}/_db/${local_DATABASE_NAME}/api/${local_FOXX_MAJOR_API_VERSION}/usr/create?name=Data%20Fed&uid=datafed89&uuids=%5B\"${DATAFED_USER89_GLOBUS_UUID}\"%5D&password=${local_DATAFED_USER89_PASSWORD}&email=datafed89%40gmail.com&is_admin=true&secret=${DATAFED_ZEROMQ_SYSTEM_SECRET}" ) + response=$( curl --user "${basic_auth}" -X GET "http://${local_DATAFED_DATABASE_HOST}:${local_DATAFED_DATABASE_PORT}/_db/${local_DATABASE_NAME}/api/${local_FOXX_MAJOR_API_VERSION}/usr/create?name=Data%20Fed&uid=datafed89&uuids=%5B\"${DATAFED_USER89_GLOBUS_UUID}\"%5D&password=${local_DATAFED_USER89_PASSWORD}&email=datafed89%40gmail.com&is_admin=true&secret=${DATAFED_ZEROMQ_SYSTEM_SECRET}" ) CODE=$(echo $response | jq .code ) ERROR_MSG=$(echo $response | jq .errorMessage ) echo "$ERROR_MSG" diff --git a/tests/end-to-end/web-UI/playwright.config.js b/tests/end-to-end/web-UI/playwright.config.js index 463065522..1e83946f1 100644 --- a/tests/end-to-end/web-UI/playwright.config.js +++ b/tests/end-to-end/web-UI/playwright.config.js @@ -1,69 +1,66 @@ // @ts-check -const { defineConfig, devices } = require('@playwright/test'); +const { defineConfig, devices } = require("@playwright/test"); /** * @see https://playwright.dev/docs/test-configuration */ module.exports = defineConfig({ - //If the server is slow, consider increasing the timeout (in ms) - timeout: 30000, + //If the server is slow, consider increasing the timeout (in ms) + timeout: 30000, - globalSetup: require.resolve('./auth.setup'), + globalSetup: require.resolve("./auth.setup"), - testDir: './scripts', + testDir: "./scripts", - /* Run tests in files in parallel */ - fullyParallel: false, + /* Run tests in files in parallel */ + fullyParallel: false, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: process.env.CI ? 2 : 0, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, - /* Opt out of parallel tests on CI. */ - workers: 1, + /* Opt out of parallel tests on CI. */ + workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'html', + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: "html", - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - - ignoreHTTPSErrors: true, - - launchOptions: { - args: ['--ignore-certificate-errors'], - }, - storageState: './.auth/auth.json' - }, - + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: "on-first-retry", + ignoreHTTPSErrors: true, - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, + launchOptions: { + args: ["--ignore-certificate-errors"], + }, + storageState: "./.auth/auth.json", }, - // { - // name: 'firefox', - // use: { - // ...devices['Desktop Firefox'], - // }, - // }, + /* Configure projects for major browsers */ + projects: [ + { + name: "chromium", + use: { + ...devices["Desktop Chrome"], + }, + }, - // { - // name: 'webkit', - // use: { - // ...devices['Desktop Safari'], - // }, - // }, - ], -}); + // { + // name: 'firefox', + // use: { + // ...devices['Desktop Firefox'], + // }, + // }, + // { + // name: 'webkit', + // use: { + // ...devices['Desktop Safari'], + // }, + // }, + ], +}); diff --git a/tests/end-to-end/web-UI/scripts/testingBasicFunction.spec.js b/tests/end-to-end/web-UI/scripts/testingBasicFunction.spec.js index 430c6c4eb..c45c37898 100644 --- a/tests/end-to-end/web-UI/scripts/testingBasicFunction.spec.js +++ b/tests/end-to-end/web-UI/scripts/testingBasicFunction.spec.js @@ -1,46 +1,54 @@ -import { test, expect } from '@playwright/test'; - -// checking visibility and expanding some dropdowns -test('test visibility', async ({page}) => { - try { - console.log("******Begin test******"); - // Temporary fix - let domain = process.env.DATAFED_DOMAIN; - await page.goto('https://' + domain + '/'); - if (await page.getByRole('button', { name: 'Log In / Register' }).isVisible()) { - console.log("NOT LOGGED IN"); - } - if (await expect(page.getByText('Continue Registration')).toBeVisible()) { - await page.getByText('Continue Registration').click({timeout: 20000}); - } - await expect(page.locator('.ui-icon').first()).toBeVisible({ - timeout: 20000 - }); - await expect(page.getByText('DataFed - Scientific Data')).toBeVisible(); - await expect(page.getByRole('link', { name: 'My Data' })).toBeVisible(); - await expect(page.getByRole('link', { name: 'Catalog' })).toBeVisible(); - await expect(page.getByRole('button', { name: '' })).toBeVisible(); +import { test, expect } from "@playwright/test"; - await page.getByRole('treeitem', { name: '  Public Collections' }).getByRole('button').click(); - await page.getByRole('treeitem', { name: '  Public Collections' }).getByRole('group').click(); - await page.getByRole('treeitem', { name: '  Allocations' }).getByRole('button').click(); - await page.getByRole('treeitem', { name: '  Project Data' }).getByRole('button').click(); - await page.getByRole('treeitem', { name: '  Shared Data' }).getByRole('button').click(); - await page.getByRole('treeitem', { name: '  Saved Queries' }).locator('span').first().click(); - await page.getByRole('treeitem', { name: '  Saved Queries' }).getByRole('button').click(); - await page.getByText('Provenance Annotate Upload').click({ timeout: 20000 }); - await page.getByRole('treeitem', { name: '  By User' }).getByRole('button').click(); - - } catch (error) { +// checking visibility and expanding some dropdowns +test("test visibility", async ({ page }) => { + try { + console.log("******Begin test******"); + // Temporary fix + let domain = process.env.DATAFED_DOMAIN; + await page.goto("https://" + domain + "/"); + if (await page.getByRole("button", { name: "Log In / Register" }).isVisible()) { + console.log("NOT LOGGED IN"); + } + if (await expect(page.getByText("Continue Registration")).toBeVisible()) { + await page.getByText("Continue Registration").click({ timeout: 20000 }); + } + await expect(page.locator(".ui-icon").first()).toBeVisible({ + timeout: 20000, + }); + await expect(page.getByText("DataFed - Scientific Data")).toBeVisible(); + await expect(page.getByRole("link", { name: "My Data" })).toBeVisible(); + await expect(page.getByRole("link", { name: "Catalog" })).toBeVisible(); + await expect(page.getByRole("button", { name: "" })).toBeVisible(); - // element not visible, either the test broke due to tags changing, or not logged in - // try to log out, because if not logged out, future tests will fail due to globus being annoying - if (await page.getByRole('button', { name: '' }).isVisible()) { - await page.getByRole('button', { name: '' }).click(); - } else { - // if in here, check if you logged out properly - throw error; + await page + .getByRole("treeitem", { name: "  Public Collections" }) + .getByRole("button") + .click(); + await page + .getByRole("treeitem", { name: "  Public Collections" }) + .getByRole("group") + .click(); + await page.getByRole("treeitem", { name: "  Allocations" }).getByRole("button").click(); + await page.getByRole("treeitem", { name: "  Project Data" }).getByRole("button").click(); + await page.getByRole("treeitem", { name: "  Shared Data" }).getByRole("button").click(); + await page + .getByRole("treeitem", { name: "  Saved Queries" }) + .locator("span") + .first() + .click(); + await page.getByRole("treeitem", { name: "  Saved Queries" }).getByRole("button").click(); + await page.getByText("Provenance Annotate Upload").click({ timeout: 20000 }); + await page.getByRole("treeitem", { name: "  By User" }).getByRole("button").click(); + } catch (error) { + // element not visible, either the test broke due to tags changing, or not logged in + // try to log out, because if not logged out, future tests will fail due to globus being annoying + if (await page.getByRole("button", { name: "" }).isVisible()) { + await page.getByRole("button", { name: "" }).click(); + } else { + // if in here, check if you logged out properly + throw error; + } } - } - //removed logout + //removed logout }); diff --git a/web/datafed-ws.js b/web/datafed-ws.js index 143326e76..4355ca091 100755 --- a/web/datafed-ws.js +++ b/web/datafed-ws.js @@ -1,6 +1,6 @@ #!/usr/bin/env node -'use strict'; +"use strict"; /* This is the DataFed web server that provides both the web portal application (/ui) and the web API (/api). @@ -11,29 +11,38 @@ User authentication is provided by Globus Auth API, and session information is s */ -if ( process.argv.length != 3 ){ +if (process.argv.length != 3) { throw "Invalid arguments, usage: datafed-ws config-file"; } -const web_version = require('./version.js'); -const express = require('express'); // For REST api -var session = require('express-session'); -//var bodyParser = require('body-parser'); -const sanitizeHtml = require('sanitize-html'); -var cookieParser = require('cookie-parser'); // cookies for user state -var http = require('http'); -var https = require('https'); -const crypto = require('crypto'); -const helmet = require('helmet'); -const fs = require('fs'); -const ini = require('ini'); -var protobuf = require("protobufjs"); -var zmq = require("zeromq"); +import web_version from "./version.js"; +import express from "express"; // For REST api +import session from "express-session"; +import sanitizeHtml from "sanitize-html"; +import cookieParser from "cookie-parser"; // cookies for user state +import http from "http"; +import https from "https"; +import crypto from "crypto"; +import helmet from "helmet"; +import fs from "fs"; +import ini from "ini"; +import protobuf from "protobufjs"; +import zmq from "zeromq"; +import ECT from "ect"; // for html templates +import ClientOAuth2 from "client-oauth2"; +import { v4 as uuidv4 } from "uuid"; + +import { fileURLToPath } from "url"; +import { dirname } from "path"; + +import OAuthTokenHandler, { AccessTokenType } from "./services/auth/TokenHandler.js"; +import { generateConsentURL } from "./services/auth/ConsentHandler.js"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +var ectRenderer = ECT({ watch: true, root: __dirname + "/views", ext: ".ect" }); const app = express(); -var ECT = require('ect'); // for html templates -var ectRenderer = ECT({ watch: true, root: __dirname + '/views', ext : '.ect' }); -const ClientOAuth2 = require('client-oauth2'); -const { v4: uuidv4 } = require('uuid'); const MAX_CTX = 50; @@ -47,12 +56,12 @@ var g_host, g_test, g_msg_by_id = {}, g_msg_by_name = {}, - g_core_sock = zmq.socket('dealer'), + g_core_sock = zmq.socket("dealer"), g_core_serv_addr, g_globus_auth, g_extern_url, g_oauth_credentials, - g_ctx = new Array( MAX_CTX ), + g_ctx = new Array(MAX_CTX), g_ctx_next = 0, g_client_id, g_client_secret, @@ -73,62 +82,66 @@ const nullfr = Buffer.from([]); g_ctx.fill(null); - const LogLevel = { - TRACE: 0, - DEBUG: 1, - INFO: 2, - WARNING: 3, - ERROR: 4, - CRITICAL: 5 + CRITICAL: 0, + ERROR: 1, + WARNING: 2, + INFO: 3, + DEBUG: 4, + TRACE: 5, }; class Logger { - constructor(level) { - this._level = level - } - - log(message_type, function_name, line_number, message, correlation_id) { - const now = new Date(); - const isoDateTime = now.toISOString(); - var log_line = `${isoDateTime} datafed-ws ${message_type} datafed-ws.js:${function_name}:${line_number} \{ \"thread_id\": 0, \"message\": \"${message}\" `; - if( correlation_id !== "") { - log_line += `, \"correlation_id\": \"${correlation_id}\"`; + constructor(level) { + this._level = level; } - log_line += ` \}`; - console.log(log_line); - } - critical(function_name, line_number, message, correlation_id = "") { - if( this._level >= LogLevel.CRITICAL ) { - this.log("CRIT", function_name, line_number, message, correlation_id); + log(message_type, function_name, line_number, message, correlation_id) { + const now = new Date(); + const isoDateTime = now.toISOString(); + var log_line = `${isoDateTime} datafed-ws ${message_type} datafed-ws.js:${function_name}:${line_number} \{ \"thread_id\": 0, \"message\": \"${message}\" `; + if (correlation_id !== "") { + log_line += `, \"correlation_id\": \"${correlation_id}\"`; + } + log_line += ` \}`; + console.log(log_line); } - } - error(function_name, line_number, message, correlation_id = "") { - if( this._level >= LogLevel.ERROR ) { - this.log("ERROR", function_name, line_number, message, correlation_id); + + critical(function_name, line_number, message, correlation_id = "") { + if (this._level >= LogLevel.CRITICAL) { + this.log("CRIT", function_name, line_number, message, correlation_id); + } } - } - warning(function_name, line_number, message, correlation_id = "") { - if( this._level >= LogLevel.WARNING ) { - this.log("WARNING", function_name, line_number, message, correlation_id); + + error(function_name, line_number, message, correlation_id = "") { + if (this._level >= LogLevel.ERROR) { + this.log("ERROR", function_name, line_number, message, correlation_id); + } } - } - info(function_name, line_number, message, correlation_id = "") { - if( this._level >= LogLevel.INFO ) { - this.log("INFO", function_name, line_number, message, correlation_id); + + warning(function_name, line_number, message, correlation_id = "") { + if (this._level >= LogLevel.WARNING) { + this.log("WARNING", function_name, line_number, message, correlation_id); + } } - } - debug(function_name, line_number, message, correlation_id = "") { - if( this._level >= LogLevel.DEBUG ) { - this.log("DEBUG", function_name, line_number, message, correlation_id); + + info(function_name, line_number, message, correlation_id = "") { + if (this._level >= LogLevel.INFO) { + this.log("INFO", function_name, line_number, message, correlation_id); + } } - } - trace(function_name, line_number, message, correlation_id = "") { - if( this._level >= LogLevel.TRACE ) { - this.log("TRACE", function_name, line_number, message, correlation_id); + + debug(function_name, line_number, message, correlation_id = "") { + if (this._level >= LogLevel.DEBUG) { + this.log("DEBUG", function_name, line_number, message, correlation_id); + } + } + + trace(function_name, line_number, message, correlation_id = "") { + if (this._level >= LogLevel.TRACE) { + this.log("TRACE", function_name, line_number, message, correlation_id); + } } - } } const logger = new Logger(LogLevel.INFO); @@ -138,121 +151,179 @@ function getCurrentLineNumber() { const lineMatches = stackTrace.match(/:\d+:\d+/g); if (lineMatches && lineMatches.length > 1) { - const lineNumber = lineMatches[1].substring(1); - return parseInt(lineNumber, 10); - } + const lineNumber = lineMatches[1].substring(1); + return parseInt(lineNumber, 10); + } return undefined; // Line number could not be determined } -function startServer(){ +function startServer() { logger.info(startServer.name, getCurrentLineNumber(), `Host: ${g_host}`); logger.info(startServer.name, getCurrentLineNumber(), `Port: ${g_port}`); - const message = "TLS:" + g_tls?"Yes":"No"; + const message = "TLS:" + g_tls ? "Yes" : "No"; logger.info(startServer.name, getCurrentLineNumber(), message); - if ( g_tls ){ - logger.debug(startServer.name, getCurrentLineNumber(), `Server key file: ${g_server_key_file}`); - logger.debug(startServer.name, getCurrentLineNumber(), `Server cert file: ${g_server_cert_file}`); - logger.debug(startServer.name, getCurrentLineNumber(), `Server chain file: ${g_server_chain_file}`); + if (g_tls) { + logger.debug( + startServer.name, + getCurrentLineNumber(), + `Server key file: ${g_server_key_file}`, + ); + logger.debug( + startServer.name, + getCurrentLineNumber(), + `Server cert file: ${g_server_cert_file}`, + ); + logger.debug( + startServer.name, + getCurrentLineNumber(), + `Server chain file: ${g_server_chain_file}`, + ); } logger.info(startServer.name, getCurrentLineNumber(), `External URL: ${g_extern_url}`); logger.info(startServer.name, getCurrentLineNumber(), `Core server addr: ${g_core_serv_addr}`); logger.info(startServer.name, getCurrentLineNumber(), `Test mode: ${g_test}`); - g_core_sock.connect( g_core_serv_addr ); - sendMessageDirect( "VersionRequest", "", {}, function( reply ) { - if ( !reply ){ - logger.error(startServer.name, getCurrentLineNumber(), "ERROR: No reply from core server" ); - }else if ( reply.api_major != g_ver_api_major || reply.api_minor < g_ver_api_minor || reply.api_minor > ( g_ver_api_minor + 9) ) { - logger.error(startServer.name, getCurrentLineNumber(), "ERROR: Incompatible api version detected (" + reply.api_major + "." + reply.api_minor + "." + reply.api_patch + ")" ); - }else{ - var warning_msg = "WARNING: A newer web server may be available the latest release version is: (" + reply.release_year + "." + reply.release_month + "." + reply.release_day + "." + reply.release_hour + "." + reply.release_minute - if( reply.release_year > g_ver_release_year ) { - logger.warning(startServer.name, getCurrentLineNumber(),warning_msg); - } else if( reply.release_year == g_ver_release_year ) { - if( reply.release_month > g_ver_release_month ) { - logger.warning(startServer.name, getCurrentLineNumber(),warning_msg); - } else if (reply.release_month == g_ver_release_month) { - if( reply.release_day > g_ver_release_day ) { - logger.warning(startServer.name, getCurrentLineNumber(),warning_msg); - } else if(reply.release_day == g_ver_release_day) { - if( reply.release_hour > g_ver_release_hour ) { - logger.warning(startServer.name, getCurrentLineNumber(),warning_msg); - } else if(reply.release_hour == g_ver_release_hour) { - if( reply.release_minute > g_ver_release_minute ) { - logger.warning(startServer.name, getCurrentLineNumber(),warning_msg); - } + g_core_sock.connect(g_core_serv_addr); + sendMessageDirect("VersionRequest", "", {}, function (reply) { + if (!reply) { + logger.error( + startServer.name, + getCurrentLineNumber(), + "ERROR: No reply from core server", + ); + } else if ( + reply.api_major != g_ver_api_major || + reply.api_minor < g_ver_api_minor || + reply.api_minor > g_ver_api_minor + 9 + ) { + logger.error( + startServer.name, + getCurrentLineNumber(), + "ERROR: Incompatible api version detected (" + + reply.api_major + + "." + + reply.api_minor + + "." + + reply.api_patch + + ")", + ); + } else { + var warning_msg = + "WARNING: A newer web server may be available the latest release version is: (" + + reply.release_year + + "." + + reply.release_month + + "." + + reply.release_day + + "." + + reply.release_hour + + "." + + reply.release_minute; + if (reply.release_year > g_ver_release_year) { + logger.warning(startServer.name, getCurrentLineNumber(), warning_msg); + } else if (reply.release_year == g_ver_release_year) { + if (reply.release_month > g_ver_release_month) { + logger.warning(startServer.name, getCurrentLineNumber(), warning_msg); + } else if (reply.release_month == g_ver_release_month) { + if (reply.release_day > g_ver_release_day) { + logger.warning(startServer.name, getCurrentLineNumber(), warning_msg); + } else if (reply.release_day == g_ver_release_day) { + if (reply.release_hour > g_ver_release_hour) { + logger.warning(startServer.name, getCurrentLineNumber(), warning_msg); + } else if (reply.release_hour == g_ver_release_hour) { + if (reply.release_minute > g_ver_release_minute) { + logger.warning( + startServer.name, + getCurrentLineNumber(), + warning_msg, + ); + } + } + } } - } } - } g_oauth_credentials = { clientId: g_client_id, clientSecret: g_client_secret, - authorizationUri: 'https://auth.globus.org/v2/oauth2/authorize', - accessTokenUri: 'https://auth.globus.org/v2/oauth2/token', + authorizationUri: "https://auth.globus.org/v2/oauth2/authorize", + accessTokenUri: "https://auth.globus.org/v2/oauth2/token", redirectUri: g_extern_url + "/ui/authn", - scopes: 'urn:globus:auth:scope:transfer.api.globus.org:all offline_access openid' + scopes: "urn:globus:auth:scope:transfer.api.globus.org:all offline_access openid", }; - g_globus_auth = new ClientOAuth2( g_oauth_credentials ); + g_globus_auth = new ClientOAuth2(g_oauth_credentials); var server; - if ( g_tls ){ - var privateKey = fs.readFileSync( g_server_key_file, 'utf8'); - var certificate = fs.readFileSync( g_server_cert_file, 'utf8'); + if (g_tls) { + var privateKey = fs.readFileSync(g_server_key_file, "utf8"); + var certificate = fs.readFileSync(g_server_cert_file, "utf8"); var chain; - if ( g_server_chain_file ){ - chain = fs.readFileSync( g_server_chain_file, 'utf8'); + if (g_server_chain_file) { + chain = fs.readFileSync(g_server_chain_file, "utf8"); } - server = https.createServer({ - key: privateKey, - cert: certificate, - ca: chain, - secureOptions: crypto.SSL_OP_NO_SSLv2 | crypto.SSL_OP_NO_SSLv3 - }, app ); - }else{ + server = https.createServer( + { + key: privateKey, + cert: certificate, + ca: chain, + secureOptions: crypto.SSL_OP_NO_SSLv2 | crypto.SSL_OP_NO_SSLv3, + }, + app, + ); + } else { server = http.createServer({}, app); } - server.listen( g_port ); + server.listen(g_port); } }); } loadSettings(); -express.static.mime.define({'application/javascript': ['js']}); +express.static.mime.define({ "application/javascript": ["js"] }); // Enforce HSTS app.use(helmet()); -app.use( express.static( __dirname + '/static' )); +app.use(express.static(__dirname + "/static")); // body size limit = 100*max metadata size, which is 100 Kb -app.use( express.json({ type: 'application/json', limit: '1048576'})); -app.use( express.text({ type: 'text/plain', limit: '1048576'})); +app.use(express.json({ type: "application/json", limit: "1048576" })); +app.use(express.text({ type: "text/plain", limit: "1048576" })); // Setup session management and cookie settings -app.use( session({ - secret: g_session_secret, - resave: false, - rolling: true, - saveUninitialized: false, - cookie: { - httpOnly: true, - maxAge: 432000000, // 5 days in msec - secure: true, // can't be true if load balancer in use - sameSite: "lax" +app.use( + session({ + secret: g_session_secret, + resave: false, + rolling: true, + saveUninitialized: false, + cookie: { + httpOnly: true, + maxAge: 432000000, // 5 days in msec + secure: true, // can't be true if load balancer in use + sameSite: "lax", + }, + }), +); + +function storeCollectionId(req, res, next) { + if (req.query.collection_id) { + req.session.collection_id = req.query.collection_id; + // TODO: assuming collection is specifically mapped and not HA/other variants + req.session.collection_type = "mapped"; } -})); + next(); +} -app.use( cookieParser( g_session_secret )); +app.use(cookieParser(g_session_secret)); app.use( helmet({ hsts: { - maxAge: 31536000 + maxAge: 31536000, }, - contentSecurityPolicy:{ + contentSecurityPolicy: { useDefaults: true, directives: { "script-src": [ @@ -261,80 +332,118 @@ app.use( "https://cdnjs.cloudflare.com", "https://cdn.jsdelivr.net", "https://d3js.org", - "blob:" + "blob:", ], - "img-src": [ "*", "data:" ] - } - } - }) + "img-src": ["*", "data:"], + }, + }, + }), ); -app.use( function( req, res, next ){ - res.setHeader('Content-Language','en-US'); +app.use(function (req, res, next) { + res.setHeader("Content-Language", "en-US"); next(); }); -app.set( 'view engine', 'ect' ); -app.engine( 'ect', ectRenderer.render ); +app.set("view engine", "ect"); +app.engine("ect", ectRenderer.render); -app.get('/', (a_req, a_resp) => { - if ( a_req.session.uid && a_req.session.reg ) - a_resp.redirect( '/ui/main' ); - else{ - a_resp.redirect( '/ui/welcome' ); +app.get("/", (a_req, a_resp) => { + if (a_req.session.uid && a_req.session.reg) a_resp.redirect("/ui/main"); + else { + a_resp.redirect("/ui/welcome"); } }); -app.get('/ui/welcome', (a_req, a_resp) => { - if ( a_req.session.uid && a_req.session.reg ) - a_resp.redirect( '/ui/main' ); - else{ - logger.debug('/ui/welcome', getCurrentLineNumber(), "Access welcome from: " + a_req.connection.remoteAddress ); +app.get("/ui/welcome", (a_req, a_resp) => { + if (a_req.session.uid && a_req.session.reg) a_resp.redirect("/ui/main"); + else { + logger.debug( + "/ui/welcome", + getCurrentLineNumber(), + "Access welcome from: " + a_req.connection.remoteAddress, + ); - var theme = a_req.cookies['datafed-theme']|| "light"; - const nonce = crypto.randomBytes(16).toString('base64'); + var theme = a_req.cookies["datafed-theme"] || "light"; + const nonce = crypto.randomBytes(16).toString("base64"); a_resp.locals.nonce = nonce; - a_resp.setHeader('Content-Security-Policy', `script-src 'nonce-${nonce}' auth.globus.org`); - a_resp.render('index',{nonce:a_resp.locals.nonce, theme:theme,version:g_version,test_mode:g_test,...g_google_analytics}); + a_resp.setHeader("Content-Security-Policy", `script-src 'nonce-${nonce}' auth.globus.org`); + a_resp.render("index", { + nonce: a_resp.locals.nonce, + theme: theme, + version: g_version, + test_mode: g_test, + ...g_google_analytics, + }); } }); -app.get('/ui/main', (a_req, a_resp) => { - if ( a_req.session.uid && a_req.session.reg ){ - logger.info('/ui/main', getCurrentLineNumber(), "Access main (" + a_req.session.uid + ") from " + a_req.connection.remoteAddress ); +app.get("/ui/main", (a_req, a_resp) => { + if (a_req.session.uid && a_req.session.reg) { + logger.info( + "/ui/main", + getCurrentLineNumber(), + "Access main (" + a_req.session.uid + ") from " + a_req.connection.remoteAddress, + ); - var theme = a_req.cookies['datafed-theme'] || "light"; - const nonce = crypto.randomBytes(16).toString('base64'); + var theme = a_req.cookies["datafed-theme"] || "light"; + const nonce = crypto.randomBytes(16).toString("base64"); a_resp.locals.nonce = nonce; - a_resp.setHeader('Content-Security-Policy', `script-src 'nonce-${nonce}'`); - a_resp.render('main',{nonce:a_resp.locals.nonce,user_uid:a_req.session.uid,theme:theme,version:g_version,test_mode:g_test,...g_google_analytics}); - }else{ + a_resp.setHeader("Content-Security-Policy", `script-src 'nonce-${nonce}'`); + a_resp.render("main", { + nonce: a_resp.locals.nonce, + user_uid: a_req.session.uid, + theme: theme, + version: g_version, + test_mode: g_test, + ...g_google_analytics, + }); + } else { // datafed-user cookie not set, so clear datafed-id before redirect //a_resp.clearCookie( 'datafed-id' ); - a_resp.redirect( '/' ); + a_resp.redirect("/"); } }); /* This is the post-Globus registration page where user may enter a password before continuing to main -*/ -app.get('/ui/register', (a_req, a_resp) => { - logger.debug('/ui/register', getCurrentLineNumber(), "Begin registering."); - - if ( !a_req.session.uid ){ - logger.info('/ui/register', getCurrentLineNumber(), " - no uid, go to /"); - a_resp.redirect( '/' ); - } else if ( a_req.session.reg ){ - logger.info('/ui/register', getCurrentLineNumber(), " - already registered, go to /ui/main"); - a_resp.redirect( '/ui/main' ); + */ +app.get("/ui/register", (a_req, a_resp) => { + logger.debug("/ui/register", getCurrentLineNumber(), "Begin registering."); + + if (!a_req.session.uid) { + logger.info("/ui/register", getCurrentLineNumber(), " - no uid, go to /"); + a_resp.redirect("/"); + } else if (a_req.session.reg) { + logger.info( + "/ui/register", + getCurrentLineNumber(), + " - already registered, go to /ui/main", + ); + a_resp.redirect("/ui/main"); } else { - logger.info('/ui/register', getCurrentLineNumber(), " - registration access (" + a_req.session.uid + ") from " + a_req.connection.remoteAddress ); - - var theme = a_req.cookies['datafed-theme'] || "light"; - const clean = sanitizeHtml( a_req.session.name ); - const nonce = crypto.randomBytes(16).toString('base64'); + logger.info( + "/ui/register", + getCurrentLineNumber(), + " - registration access (" + + a_req.session.uid + + ") from " + + a_req.connection.remoteAddress, + ); + + var theme = a_req.cookies["datafed-theme"] || "light"; + const clean = sanitizeHtml(a_req.session.name); + const nonce = crypto.randomBytes(16).toString("base64"); a_resp.locals.nonce = nonce; - a_resp.setHeader('Content-Security-Policy', `script-src 'nonce-${nonce}' auth.globus.org`); - a_resp.render('register', {nonce:a_resp.locals.nonce, uid: a_req.session.uid, uname: clean, theme: theme, version: g_version, test_mode: g_test, ...g_google_analytics }); + a_resp.setHeader("Content-Security-Policy", `script-src 'nonce-${nonce}' auth.globus.org`); + a_resp.render("register", { + nonce: a_resp.locals.nonce, + uid: a_req.session.uid, + uname: clean, + theme: theme, + version: g_version, + test_mode: g_test, + ...g_google_analytics, + }); } }); @@ -342,1469 +451,1941 @@ app.get('/ui/register', (a_req, a_resp) => { User should be unknown at this point (if session were valid, would be redirected to /ui/main). This is the beginning of the OAuth loop through Globus Auth and will redirect to /ui/authn */ -app.get('/ui/login', (a_req, a_resp) => { - if ( a_req.session.uid && a_req.session.reg ){ - a_resp.redirect( '/ui/main' ); +app.get("/ui/login", (a_req, a_resp) => { + if (a_req.session.uid && a_req.session.reg) { + a_resp.redirect("/ui/main"); } else { - logger.info('/ui/login', getCurrentLineNumber(), "User (" + a_req.session.uid + ") from " + a_req.connection.remoteAddress + "log-in" ); + logger.info( + "/ui/login", + getCurrentLineNumber(), + "User (" + a_req.session.uid + ") from " + a_req.connection.remoteAddress + "log-in", + ); var uri = g_globus_auth.code.getUri(); a_resp.redirect(uri); } }); - -app.get('/ui/logout', (a_req, a_resp) => { - logger.info('/ui/logout', getCurrentLineNumber(), "User (" + a_req.session.uid + ") from " + a_req.connection.remoteAddress + " logout" ); +app.get("/ui/logout", (a_req, a_resp) => { + logger.info( + "/ui/logout", + getCurrentLineNumber(), + "User (" + a_req.session.uid + ") from " + a_req.connection.remoteAddress + " logout", + ); //a_resp.clearCookie( 'datafed-id' ); //a_resp.clearCookie( 'datafed-user', { path: "/ui" } ); - a_req.session.destroy( function(){ - a_resp.clearCookie( 'connect.sid' ); - a_resp.redirect("https://auth.globus.org/v2/web/logout?redirect_name=DataFed&redirect_uri="+g_extern_url); + a_req.session.destroy(function () { + a_resp.clearCookie("connect.sid"); + a_resp.redirect( + "https://auth.globus.org/v2/web/logout?redirect_name=DataFed&redirect_uri=" + + g_extern_url, + ); }); }); -app.get('/ui/error', (a_req, a_resp) => { - const nonce = crypto.randomBytes(16).toString('base64'); +app.get("/ui/error", (a_req, a_resp) => { + const nonce = crypto.randomBytes(16).toString("base64"); a_resp.locals.nonce = nonce; - a_resp.setHeader('Content-Security-Policy', `script-src 'nonce-${nonce}'`); - a_resp.render('error',{nonce:a_resp.locals.nonce,theme:"light",version:g_version,test_mode:g_test,...g_google_analytics}); + a_resp.setHeader("Content-Security-Policy", `script-src 'nonce-${nonce}'`); + a_resp.render("error", { + nonce: a_resp.locals.nonce, + theme: "light", + version: g_version, + test_mode: g_test, + ...g_google_analytics, + }); }); /* This is the OAuth redirect URL after a user authenticates with Globus -*/ -app.get('/ui/authn', ( a_req, a_resp ) => { - logger.info('/ui/authn', getCurrentLineNumber(), "Globus authenticated - log in to DataFed" ); + */ +app.get("/ui/authn", (a_req, a_resp) => { + logger.info("/ui/authn", getCurrentLineNumber(), "Globus authenticated - log in to DataFed"); /* This after Globus authentication. Loads Globus tokens and identity information. - The user is then checked in DataFed and, if present redirected to the main page; otherwise, sent to - the registration page. - */ - - g_globus_auth.code.getToken( a_req.originalUrl ).then( function( client_token ) { - - var xfr_token = client_token.data.other_tokens[0]; +The user is then checked in DataFed and, if present redirected to the main page; otherwise, sent to +the registration page. +*/ - const opts = { - hostname: 'auth.globus.org', - method: 'POST', - path: '/v2/oauth2/token/introspect', - rejectUnauthorized: true, - auth: g_oauth_credentials.clientId + ":" + g_oauth_credentials.clientSecret, - headers:{ - 'Content-Type' : 'application/x-www-form-urlencoded', - 'Accept' : 'application/json', + g_globus_auth.code.getToken(a_req.originalUrl).then( + function (client_token) { + let token_handler; + try { + token_handler = new OAuthTokenHandler(client_token); + } catch (err) { + a_resp.redirect("/ui/error"); + logger.error("/ui/authn", getCurrentLineNumber(), err); + throw err; } - }; - - // Request user info from token - const req = https.request( opts, (res) => { - var data = ''; + let xfr_token = token_handler.extractTransferToken(); + + const opts = { + hostname: "auth.globus.org", + method: "POST", + path: "/v2/oauth2/token/introspect", + rejectUnauthorized: true, + auth: g_oauth_credentials.clientId + ":" + g_oauth_credentials.clientSecret, + headers: { + "Content-Type": "application/x-www-form-urlencoded", + Accept: "application/json", + }, + }; - res.on('data', (chunk) => { - data += chunk; + // Request user info from token + const req = https.request(opts, (res) => { + var data = ""; + + res.on("data", (chunk) => { + data += chunk; + }); + + res.on("end", () => { + if (res.statusCode >= 200 && res.statusCode < 300) { + const userinfo = JSON.parse(data); + const uid = userinfo.username.substring(0, userinfo.username.indexOf("@")); + + logger.info( + "/ui/authn", + getCurrentLineNumber(), + "User: " + uid + " authenticated, verifying DataFed account", + ); + sendMessageDirect( + "UserFindByUUIDsRequest", + "datafed-ws", + { uuid: userinfo.identities_set }, + function (reply) { + if (!reply) { + logger.error( + "/ui/authn", + getCurrentLineNumber(), + "Error - Find user call failed.", + ); + a_resp.redirect("/ui/error"); + } else if (!reply.user || !reply.user.length) { + // Not registered + logger.info( + "/ui/authn", + getCurrentLineNumber(), + "User: " + uid + "not registered", + ); + + if ( + token_handler.getTokenType() === + AccessTokenType.GLOBUS_TRANSFER + ) { + // Log error and do not register user in case of non-auth token + logger.error( + "/ui/authn", + getCurrentLineNumber(), + "Transfer token received for non-existent user.", + ); + a_resp.redirect("/ui/error"); + } + + // Store all data need for registration in session (temporarily) + a_req.session.uid = uid; + a_req.session.name = userinfo.name; + a_req.session.email = userinfo.email; + a_req.session.uuids = userinfo.identities_set; + a_req.session.acc_tok = xfr_token.access_token; + a_req.session.acc_tok_ttl = xfr_token.expires_in; + a_req.session.ref_tok = xfr_token.refresh_token; + + a_resp.redirect("/ui/register"); + } else { + logger.info( + "/ui/authn", + getCurrentLineNumber(), + "User: " + + uid + + " verified, acc:" + + xfr_token.access_token + + ", ref: " + + xfr_token.refresh_token + + ", exp:" + + xfr_token.expires_in, + ); + + // Store only data needed for active session + a_req.session.uid = uid; + a_req.session.reg = true; + + let redirect_path = "/ui/main"; + + // Note: context/optional params for arbitrary input + const token_context = { + // passed values are mutable + resource_server: client_token.data.resource_sever, + collection_id: a_req.session.collection_id, + scope: xfr_token.scope, + }; + try { + const optional_data = + token_handler.constructOptionalData(token_context); + + // Refresh Globus access & refresh tokens to Core/DB + // NOTE: core services seem entirely in charge of refreshing tokens once they are set (ClientWorker.cpp). + // This should only be triggered when new tokens are coming in, like when a token expires or a transfer token is created. + setAccessToken( + a_req.session.uid, + xfr_token.access_token, + xfr_token.refresh_token, + xfr_token.expires_in, + optional_data, + ); + } catch (err) { + redirect_path = "/ui/error"; + logger.error("/ui/authn", getCurrentLineNumber(), err); + delete a_req.session.collection_id; + } + + // TODO Account may be disable from SDMS (active = false) + a_resp.redirect(redirect_path); + } + }, + ); + } else { + // TODO - Not sure this is required - req.on('error'...) should catch this? + logger.error( + "ui/authn", + getCurrentLineNumber(), + "Error: Globus introspection failed. User token:", + xfr_token, + ); + a_resp.redirect("/ui/error"); + } + }); }); - res.on('end', () => { - - if ( res.statusCode >= 200 && res.statusCode < 300 ){ - var userinfo = JSON.parse( data ), - uid = userinfo.username.substr( 0, userinfo.username.indexOf( "@" )); - - logger.info('/ui/authn', getCurrentLineNumber(), 'User: ' + uid + ' authenticated, verifying DataFed account' ); - sendMessageDirect( "UserFindByUUIDsRequest", "datafed-ws", { uuid: userinfo.identities_set }, function( reply ) { - if ( !reply ) { - logger.error('/ui/authn', getCurrentLineNumber(), "Error - Find user call failed." ); - a_resp.redirect( "/ui/error" ); - } else if ( !reply.user || !reply.user.length ) { - // Not registered - logger.info('/ui/authn', getCurrentLineNumber(), "User: " + uid + "not registered" ); - - // Store all data need for registration in session (temporarily) - a_req.session.uid = uid; - a_req.session.name = userinfo.name; - a_req.session.email = userinfo.email; - a_req.session.uuids = userinfo.identities_set; - a_req.session.acc_tok = xfr_token.access_token; - a_req.session.acc_tok_ttl = xfr_token.expires_in; - a_req.session.ref_tok = xfr_token.refresh_token; - - a_resp.redirect( "/ui/register" ); - } else { - logger.info('/ui/authn', getCurrentLineNumber(), 'User: ' + uid + ' verified, acc:' + xfr_token.access_token + ", ref: " + xfr_token.refresh_token + ", exp:" + xfr_token.expires_in ); - - // Store only data needed for active session - a_req.session.uid = uid; - a_req.session.reg = true; - - // Refresh Globus access & refresh tokens to Core/DB - setAccessToken( uid, xfr_token.access_token, xfr_token.refresh_token, xfr_token.expires_in ); - - // TODO Account may be disable from SDMS (active = false) - a_resp.redirect( "/ui/main" ); - } - }); - }else{ - // TODO - Not sure this is required - req.on('error'...) should catch this? - logger.error('ui/authn', getCurrentLineNumber(), "Error: Globus introspection failed. User token:", xfr_token ); - a_resp.redirect( "/ui/error" ); - } + req.on("error", (e) => { + logger.error( + "ui/authn", + getCurrentLineNumber(), + "Error: Globus introspection failed. User token:", + xfr_token, + ); + a_resp.redirect("/ui/error"); }); - }); - - req.on('error', (e) => { - logger.error('ui/authn', getCurrentLineNumber(),"Error: Globus introspection failed. User token:", xfr_token ); - a_resp.redirect( "/ui/error" ); - }); - req.write( 'token=' + client_token.accessToken + '&include=identities_set' ); - req.end(); - }, function( reason ){ - logger.error('ui/authn', getCurrentLineNumber(),"Error: Globus get token failed. Reason:", reason ); - a_resp.redirect( "/ui/error" ); - }); + req.write("token=" + client_token.accessToken + "&include=identities_set"); + req.end(); + }, + function (reason) { + logger.error( + "ui/authn", + getCurrentLineNumber(), + "Error: Globus get token failed. Reason:", + reason, + ); + a_resp.redirect("/ui/error"); + }, + ); }); -app.get('/api/usr/register', ( a_req, a_resp ) => { - logger.debug('/api/usr/register', getCurrentLineNumber(), "Starting register." ); +app.get("/api/usr/register", (a_req, a_resp) => { + logger.debug("/api/usr/register", getCurrentLineNumber(), "Starting register."); - if ( !a_req.session.uid ){ - logger.error('/api/usr/register', getCurrentLineNumber(), 'Error: not authenticated.' ); + if (!a_req.session.uid) { + logger.error("/api/usr/register", getCurrentLineNumber(), "Error: not authenticated."); throw "Error: not authenticated."; - } else if ( a_req.session.reg ){ - logger.error('/api/usr/register', getCurrentLineNumber(), 'Already registered' ); + } else if (a_req.session.reg) { + logger.error("/api/usr/register", getCurrentLineNumber(), "Already registered"); throw "Error: already registered."; } else { - logger.info('/api/usr/register', getCurrentLineNumber(), 'Registering user' + a_req.session.uid ); - - sendMessageDirect( "UserCreateRequest", "", { - uid: a_req.session.uid, - password: a_req.query.pw, - name: a_req.session.name, - email: a_req.session.email, - uuid: a_req.session.uuids, - secret: g_system_secret - }, function( reply ) { - if ( !reply ) { - logger.error('/api/usr/register', getCurrentLineNumber(),"Error: user registration failed - empty reply from server"); - a_resp.status(500).send( "Empty reply from server" ); - } else if ( reply.errCode ) { - if ( reply.errMsg ) { - logger.error('/api/usr/register', getCurrentLineNumber(),"Error: user registration failed - ", reply.errMsg); - a_resp.status(500).send( reply.errMsg ); + logger.info( + "/api/usr/register", + getCurrentLineNumber(), + "Registering user" + a_req.session.uid, + ); + + sendMessageDirect( + "UserCreateRequest", + "", + { + uid: a_req.session.uid, + password: a_req.query.pw, + name: a_req.session.name, + email: a_req.session.email, + uuid: a_req.session.uuids, + secret: g_system_secret, + }, + function (reply) { + if (!reply) { + logger.error( + "/api/usr/register", + getCurrentLineNumber(), + "Error: user registration failed - empty reply from server", + ); + a_resp.status(500).send("Empty reply from server"); + } else if (reply.errCode) { + if (reply.errMsg) { + logger.error( + "/api/usr/register", + getCurrentLineNumber(), + "Error: user registration failed - ", + reply.errMsg, + ); + a_resp.status(500).send(reply.errMsg); + } else { + logger.error( + "/api/usr/register", + getCurrentLineNumber(), + "Error: user registration failed - code:", + reply.errCode, + ); + a_resp.status(500).send("Error code: " + reply.errCode); + } } else { - logger.error('/api/usr/register', getCurrentLineNumber(),"Error: user registration failed - code:", reply.errCode); - a_resp.status(500).send( "Error code: " + reply.errCode ); + // Save access token + try { + setAccessToken( + a_req.session.uid, + a_req.session.acc_tok, + a_req.session.ref_tok, + a_req.session.acc_tok_ttl, + ); + } catch (err) { + logger.error("/api/usr/register", getCurrentLineNumber(), err); + throw err; + } finally { + // Remove data not needed for active session + delete a_req.session.name; + delete a_req.session.email; + delete a_req.session.uuids; + delete a_req.session.acc_tok; + delete a_req.session.acc_tok_ttl; + delete a_req.session.ref_tok; + delete a_req.session.uuids; + } + + // Set session as registered user + a_req.session.reg = true; + + a_resp.send(reply); } - } else { - // Save access token - setAccessToken( a_req.session.uid, a_req.session.acc_tok, a_req.session.ref_tok, a_req.session.acc_tok_ttl ); - - // Set session as registered user - a_req.session.reg = true; - - // Remove data not needed for active session - delete a_req.session.name; - delete a_req.session.email; - delete a_req.session.uuids; - delete a_req.session.acc_tok; - delete a_req.session.acc_tok_ttl; - delete a_req.session.ref_tok; - delete a_req.session.uuids; - - a_resp.send( reply ); - } - }); + }, + ); } }); -app.get('/api/msg/daily', ( a_req, a_resp ) => { - sendMessageDirect( "DailyMessageRequest", null, {}, function( reply ) { - a_resp.json( reply ); +app.get("/api/msg/daily", (a_req, a_resp) => { + sendMessageDirect("DailyMessageRequest", null, {}, function (reply) { + a_resp.json(reply); }); }); -app.get('/api/usr/find/by_uuids', ( a_req, a_resp ) => { - sendMessage( "UserFindByUUIDsRequest", { uuid: a_req.query.uuids }, a_req, a_resp, function( reply ) { - a_resp.json( reply.user[0] ); - }); +app.get("/api/usr/find/by_uuids", (a_req, a_resp) => { + sendMessage( + "UserFindByUUIDsRequest", + { uuid: a_req.query.uuids }, + a_req, + a_resp, + function (reply) { + a_resp.json(reply.user[0]); + }, + ); }); -app.get('/api/usr/find/by_name_uid', ( a_req, a_resp ) => { - var par = {nameUid: a_req.query.name_uid}; - if ( a_req.query.offset != undefined && a_req.query.count != undefined ){ +app.get("/api/usr/find/by_name_uid", (a_req, a_resp) => { + var par = { nameUid: a_req.query.name_uid }; + if (a_req.query.offset != undefined && a_req.query.count != undefined) { par.offset = a_req.query.offset; par.count = a_req.query.count; } - sendMessage( "UserFindByNameUIDRequest", par, a_req, a_resp, function( reply ) { - a_resp.send( reply ); + sendMessage("UserFindByNameUIDRequest", par, a_req, a_resp, function (reply) { + a_resp.send(reply); }); }); -app.get('/api/usr/view', ( a_req, a_resp ) => { - sendMessage( "UserViewRequest", { uid: a_req.query.id, details:(a_req.query.details=="true"?true:false)}, a_req, a_resp, function( reply ) { - a_resp.json( reply.user[0] ); - }); +app.get("/api/usr/view", (a_req, a_resp) => { + sendMessage( + "UserViewRequest", + { uid: a_req.query.id, details: a_req.query.details == "true" ? true : false }, + a_req, + a_resp, + function (reply) { + a_resp.json(reply.user[0]); + }, + ); }); -app.get('/api/usr/update', ( a_req, a_resp ) => { +app.get("/api/usr/update", (a_req, a_resp) => { var params = { uid: a_req.query.uid }; - if ( a_req.query.email != undefined ) - params.email = a_req.query.email; - if ( a_req.query.pw != undefined ) - params.password = a_req.query.pw; - if ( a_req.query.opts != undefined ){ + if (a_req.query.email != undefined) params.email = a_req.query.email; + if (a_req.query.pw != undefined) params.password = a_req.query.pw; + if (a_req.query.opts != undefined) { params.options = a_req.query.opts; } - sendMessage( "UserUpdateRequest", params, a_req, a_resp, function( reply ) { - a_resp.json( reply.user[0] ); + sendMessage("UserUpdateRequest", params, a_req, a_resp, function (reply) { + a_resp.json(reply.user[0]); }); }); -app.get('/api/usr/revoke_cred', ( a_req, a_resp ) => { - sendMessage( "RevokeCredentialsRequest", {}, a_req, a_resp, function( reply ) { +app.get("/api/usr/revoke_cred", (a_req, a_resp) => { + sendMessage("RevokeCredentialsRequest", {}, a_req, a_resp, function (reply) { a_resp.json({}); }); }); -app.get('/api/usr/list/all', ( a_req, a_resp ) => { +app.get("/api/usr/list/all", (a_req, a_resp) => { var par = {}; - if ( a_req.query.offset != undefined && a_req.query.count != undefined ){ + if (a_req.query.offset != undefined && a_req.query.count != undefined) { par.offset = a_req.query.offset; par.count = a_req.query.count; } - sendMessage( "UserListAllRequest", par, a_req, a_resp, function( reply ) { + sendMessage("UserListAllRequest", par, a_req, a_resp, function (reply) { a_resp.json(reply); }); - }); -app.get('/api/usr/list/collab', ( a_req, a_resp ) => { +app.get("/api/usr/list/collab", (a_req, a_resp) => { var par = {}; - if ( a_req.query.offset != undefined && a_req.query.count != undefined ){ + if (a_req.query.offset != undefined && a_req.query.count != undefined) { par.offset = a_req.query.offset; par.count = a_req.query.count; } - sendMessage( "UserListCollabRequest", par, a_req, a_resp, function( reply ) { + sendMessage("UserListCollabRequest", par, a_req, a_resp, function (reply) { a_resp.json(reply); }); - }); -app.post('/api/prj/create', ( a_req, a_resp ) => { - sendMessage( "ProjectCreateRequest", a_req.body, a_req, a_resp, function( reply ) { - if ( reply.proj ) - a_resp.send(reply.proj); - else - a_resp.send([]); +app.post("/api/prj/create", (a_req, a_resp) => { + sendMessage("ProjectCreateRequest", a_req.body, a_req, a_resp, function (reply) { + if (reply.proj) a_resp.send(reply.proj); + else a_resp.send([]); }); }); -app.post('/api/prj/update', ( a_req, a_resp ) => { - sendMessage( "ProjectUpdateRequest", a_req.body, a_req, a_resp, function( reply ) { - if ( reply.proj ) - a_resp.send(reply.proj); - else - a_resp.send([]); +app.post("/api/prj/update", (a_req, a_resp) => { + sendMessage("ProjectUpdateRequest", a_req.body, a_req, a_resp, function (reply) { + if (reply.proj) a_resp.send(reply.proj); + else a_resp.send([]); }); }); -app.get('/api/prj/delete', ( a_req, a_resp ) => { - sendMessage( "ProjectDeleteRequest", { id: JSON.parse(a_req.query.ids)}, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/prj/delete", (a_req, a_resp) => { + sendMessage( + "ProjectDeleteRequest", + { id: JSON.parse(a_req.query.ids) }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/prj/view', ( a_req, a_resp ) => { - sendMessage( "ProjectViewRequest", { id: a_req.query.id }, a_req, a_resp, function( reply ) { - if ( reply.proj && reply.proj.length ) - a_resp.send(reply.proj[0]); - else - a_resp.send(); +app.get("/api/prj/view", (a_req, a_resp) => { + sendMessage("ProjectViewRequest", { id: a_req.query.id }, a_req, a_resp, function (reply) { + if (reply.proj && reply.proj.length) a_resp.send(reply.proj[0]); + else a_resp.send(); }); }); -app.get('/api/prj/list', ( a_req, a_resp ) => { +app.get("/api/prj/list", (a_req, a_resp) => { var params = {}; - if ( a_req.query.owner != undefined ) - params.asOwner = a_req.query.owner=="true"?true:false; - if ( a_req.query.admin != undefined ) - params.asAdmin = a_req.query.admin=="true"?true:false; - if ( a_req.query.member != undefined ) - params.asMember = a_req.query.member=="true"?true:false; - if ( a_req.query.sort != undefined ) - params.sort = a_req.query.sort; - if ( a_req.query.offset != undefined && a_req.query.count != undefined ){ + if (a_req.query.owner != undefined) params.asOwner = a_req.query.owner == "true" ? true : false; + if (a_req.query.admin != undefined) params.asAdmin = a_req.query.admin == "true" ? true : false; + if (a_req.query.member != undefined) + params.asMember = a_req.query.member == "true" ? true : false; + if (a_req.query.sort != undefined) params.sort = a_req.query.sort; + if (a_req.query.offset != undefined && a_req.query.count != undefined) { params.offset = a_req.query.offset; params.count = a_req.query.count; } - sendMessage( "ProjectListRequest", params, a_req, a_resp, function( reply ) { + sendMessage("ProjectListRequest", params, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.post('/api/prj/search', ( a_req, a_resp ) => { - sendMessage( "ProjectSearchRequest", a_req.body, a_req, a_resp, function( reply ) { - a_resp.send(reply.item?reply.item:[]); +app.post("/api/prj/search", (a_req, a_resp) => { + sendMessage("ProjectSearchRequest", a_req.body, a_req, a_resp, function (reply) { + a_resp.send(reply.item ? reply.item : []); }); }); -app.get('/api/grp/create', ( a_req, a_resp ) => { - var params = { +app.get("/api/grp/create", (a_req, a_resp) => { + var params = { group: { uid: a_req.query.uid, gid: a_req.query.gid, - } + }, }; - if ( a_req.query.title != undefined ) - params.group.title = a_req.query.title; - if ( a_req.query.desc != undefined ) - params.group.desc = a_req.query.desc; - if ( a_req.query.member != undefined ) - params.group.member = JSON.parse( a_req.query.member ); + if (a_req.query.title != undefined) params.group.title = a_req.query.title; + if (a_req.query.desc != undefined) params.group.desc = a_req.query.desc; + if (a_req.query.member != undefined) params.group.member = JSON.parse(a_req.query.member); - sendMessage( "GroupCreateRequest", params, a_req, a_resp, function( reply ) { + sendMessage("GroupCreateRequest", params, a_req, a_resp, function (reply) { a_resp.send(reply.group[0]); }); }); -app.get('/api/grp/update', ( a_req, a_resp ) => { - var params = { +app.get("/api/grp/update", (a_req, a_resp) => { + var params = { uid: a_req.query.uid, - gid: a_req.query.gid + gid: a_req.query.gid, }; - if ( a_req.query.title != undefined ) - params.title = a_req.query.title; - if ( a_req.query.desc != undefined ) - params.desc = a_req.query.desc; - if ( a_req.query.add != undefined ) - params.addUid = JSON.parse( a_req.query.add ); - if ( a_req.query.rem != undefined ) - params.remUid = JSON.parse( a_req.query.rem ); + if (a_req.query.title != undefined) params.title = a_req.query.title; + if (a_req.query.desc != undefined) params.desc = a_req.query.desc; + if (a_req.query.add != undefined) params.addUid = JSON.parse(a_req.query.add); + if (a_req.query.rem != undefined) params.remUid = JSON.parse(a_req.query.rem); - sendMessage( "GroupUpdateRequest", params, a_req, a_resp, function( reply ) { + sendMessage("GroupUpdateRequest", params, a_req, a_resp, function (reply) { a_resp.send(reply.group[0]); }); }); -app.get('/api/grp/view', ( a_req, a_resp ) => { - sendMessage( "GroupViewRequest", { uid: a_req.query.uid, gid: a_req.query.gid }, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/grp/view", (a_req, a_resp) => { + sendMessage( + "GroupViewRequest", + { uid: a_req.query.uid, gid: a_req.query.gid }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/grp/list', ( a_req, a_resp ) => { - sendMessage( "GroupListRequest", { uid: a_req.query.uid }, a_req, a_resp, function( reply ) { - a_resp.send(reply.group?reply.group:[]); +app.get("/api/grp/list", (a_req, a_resp) => { + sendMessage("GroupListRequest", { uid: a_req.query.uid }, a_req, a_resp, function (reply) { + a_resp.send(reply.group ? reply.group : []); }); }); -app.get('/api/grp/delete', ( a_req, a_resp ) => { - sendMessage( "GroupDeleteRequest", { uid: a_req.query.uid, gid: a_req.query.gid }, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/grp/delete", (a_req, a_resp) => { + sendMessage( + "GroupDeleteRequest", + { uid: a_req.query.uid, gid: a_req.query.gid }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/query/list', ( a_req, a_resp ) => { +app.get("/api/query/list", (a_req, a_resp) => { var par = {}; - if ( a_req.query.offset != undefined && a_req.query.count != undefined ){ + if (a_req.query.offset != undefined && a_req.query.count != undefined) { par.offset = a_req.query.offset; par.count = a_req.query.count; } - sendMessage( "QueryListRequest", par, a_req, a_resp, function( reply ) { - a_resp.send(reply.item?reply.item:[]); + sendMessage("QueryListRequest", par, a_req, a_resp, function (reply) { + a_resp.send(reply.item ? reply.item : []); }); }); - -app.post('/api/query/create', ( a_req, a_resp ) => { - sendMessage( "QueryCreateRequest", {title: a_req.query.title, query: a_req.body }, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.post("/api/query/create", (a_req, a_resp) => { + sendMessage( + "QueryCreateRequest", + { title: a_req.query.title, query: a_req.body }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.post('/api/query/update', ( a_req, a_resp ) => { - var params = {id:a_req.query.id}; - if ( a_req.query.title ) - params.title = a_req.query.title; - if ( a_req.body ) - params.query = a_req.body; +app.post("/api/query/update", (a_req, a_resp) => { + var params = { id: a_req.query.id }; + if (a_req.query.title) params.title = a_req.query.title; + if (a_req.body) params.query = a_req.body; - sendMessage( "QueryUpdateRequest", params, a_req, a_resp, function( reply ) { + sendMessage("QueryUpdateRequest", params, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/query/delete', ( a_req, a_resp ) => { - sendMessage( "QueryDeleteRequest", { id: JSON.parse(a_req.query.ids)}, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/query/delete", (a_req, a_resp) => { + sendMessage( + "QueryDeleteRequest", + { id: JSON.parse(a_req.query.ids) }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/query/view', ( a_req, a_resp ) => { - sendMessage( "QueryViewRequest", {id:a_req.query.id}, a_req, a_resp, function( reply ) { +app.get("/api/query/view", (a_req, a_resp) => { + sendMessage("QueryViewRequest", { id: a_req.query.id }, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/query/exec', ( a_req, a_resp ) => { +app.get("/api/query/exec", (a_req, a_resp) => { var msg = { - id : a_req.query.id + id: a_req.query.id, }; - if ( a_req.query.offset != undefined && a_req.query.count != undefined ){ + if (a_req.query.offset != undefined && a_req.query.count != undefined) { msg.offset = a_req.query.offset; msg.count = a_req.query.count; } - sendMessage( "QueryExecRequest", msg, a_req, a_resp, function( reply ) { + sendMessage("QueryExecRequest", msg, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); - -app.post('/api/dat/search', ( a_req, a_resp ) => { - sendMessage( "SearchRequest", a_req.body, a_req, a_resp, function( reply ) { +app.post("/api/dat/search", (a_req, a_resp) => { + sendMessage("SearchRequest", a_req.body, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.post('/api/dat/create', ( a_req, a_resp ) => { - sendMessage( "RecordCreateRequest", a_req.body, a_req, a_resp, function( reply ) { +app.post("/api/dat/create", (a_req, a_resp) => { + sendMessage("RecordCreateRequest", a_req.body, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.post('/api/dat/create/batch', ( a_req, a_resp ) => { - sendMessage( "RecordCreateBatchRequest", {records:a_req.body}, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.post("/api/dat/create/batch", (a_req, a_resp) => { + sendMessage( + "RecordCreateBatchRequest", + { records: a_req.body }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.post('/api/dat/update', ( a_req, a_resp ) => { - sendMessage( "RecordUpdateRequest", a_req.body, a_req, a_resp, function( reply ) { - if ( reply.data && reply.data.length ){ - logger.debug('/api/dat/update', getCurrentLineNumber(), "User: " + a_req.session.uid + " - data update, id: " + reply.data[0].id ); +app.post("/api/dat/update", (a_req, a_resp) => { + sendMessage("RecordUpdateRequest", a_req.body, a_req, a_resp, function (reply) { + if (reply.data && reply.data.length) { + logger.debug( + "/api/dat/update", + getCurrentLineNumber(), + "User: " + a_req.session.uid + " - data update, id: " + reply.data[0].id, + ); } a_resp.send(reply); }); }); -app.post('/api/dat/update/batch', ( a_req, a_resp ) => { - sendMessage( "RecordUpdateBatchRequest", {records:a_req.body}, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.post("/api/dat/update/batch", (a_req, a_resp) => { + sendMessage( + "RecordUpdateBatchRequest", + { records: a_req.body }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/dat/lock', ( a_req, a_resp ) => { - sendMessage( "RecordLockRequest", { id: JSON.parse(a_req.query.ids), lock: a_req.query.lock=="true"?true:false}, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/dat/lock", (a_req, a_resp) => { + sendMessage( + "RecordLockRequest", + { id: JSON.parse(a_req.query.ids), lock: a_req.query.lock == "true" ? true : false }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/dat/lock/toggle', ( a_req, a_resp ) => { - sendMessage( "RecordLockToggleRequest", { id: a_req.query.id }, a_req, a_resp, function( reply ) { +app.get("/api/dat/lock/toggle", (a_req, a_resp) => { + sendMessage("RecordLockToggleRequest", { id: a_req.query.id }, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/dat/copy', ( a_req, a_resp ) => { - var params = { +app.get("/api/dat/copy", (a_req, a_resp) => { + var params = { sourceId: a_req.query.src, - destId: a_req.query.dst + destId: a_req.query.dst, }; - sendMessage( "DataCopyRequest", params, a_req, a_resp, function( reply ) { + sendMessage("DataCopyRequest", params, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/dat/delete', ( a_req, a_resp ) => { - sendMessage( "RecordDeleteRequest", { id: JSON.parse(a_req.query.ids) }, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/dat/delete", (a_req, a_resp) => { + sendMessage( + "RecordDeleteRequest", + { id: JSON.parse(a_req.query.ids) }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/dat/view', ( a_req, a_resp ) => { - sendMessage( "RecordViewRequest", { id: a_req.query.id }, a_req, a_resp, function( reply ) { - if ( reply.data && reply.data.length ) - a_resp.send( reply ); - else - a_resp.send(); +app.get("/api/dat/view", (a_req, a_resp) => { + sendMessage("RecordViewRequest", { id: a_req.query.id }, a_req, a_resp, function (reply) { + if (reply.data && reply.data.length) a_resp.send(reply); + else a_resp.send(); }); }); -app.get('/api/dat/export', ( a_req, a_resp ) => { - sendMessage( "RecordExportRequest", { id: JSON.parse( a_req.query.ids )}, a_req, a_resp, function( reply ) { - a_resp.send( reply ); - }); +app.get("/api/dat/export", (a_req, a_resp) => { + sendMessage( + "RecordExportRequest", + { id: JSON.parse(a_req.query.ids) }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/dat/list/by_alloc', ( a_req, a_resp ) => { - var par = { +app.get("/api/dat/list/by_alloc", (a_req, a_resp) => { + var par = { repo: a_req.query.repo, - subject: a_req.query.subject + subject: a_req.query.subject, }; - if ( a_req.query.offset != undefined && a_req.query.count != undefined ){ + if (a_req.query.offset != undefined && a_req.query.count != undefined) { par.offset = a_req.query.offset; par.count = a_req.query.count; } - sendMessage( "RecordListByAllocRequest", par, a_req, a_resp, function( reply ) { + sendMessage("RecordListByAllocRequest", par, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/dat/get', ( a_req, a_resp ) => { +app.get("/api/dat/get", (a_req, a_resp) => { + var par = { id: JSON.parse(a_req.query.id) }; - var par = { id: JSON.parse( a_req.query.id )}; + if (a_req.query.path) par.path = a_req.query.path; - if ( a_req.query.path ) - par.path = a_req.query.path; + if (a_req.query.encrypt != undefined) par.encrypt = a_req.query.encrypt; - if ( a_req.query.encrypt != undefined ) - par.encrypt = a_req.query.encrypt; + if (a_req.query.orig_fname) par.origFname = true; - if ( a_req.query.orig_fname ) - par.origFname = true; + if (a_req.query.check) par.check = a_req.query.check; - if ( a_req.query.check ) - par.check = a_req.query.check; + const { collection_id, collection_type } = a_req.query; + par.collectionId = collection_id; + par.collectionType = collection_type; - sendMessage( "DataGetRequest", par, a_req, a_resp, function( reply ) { + sendMessage("DataGetRequest", par, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/dat/put', ( a_req, a_resp ) => { +app.get("/api/dat/put", (a_req, a_resp) => { var par = { id: a_req.query.id }; - if ( a_req.query.path ) - par.path = a_req.query.path; + if (a_req.query.path) par.path = a_req.query.path; - if ( a_req.query.encrypt != undefined ) - par.encrypt = a_req.query.encrypt; + if (a_req.query.encrypt != undefined) par.encrypt = a_req.query.encrypt; - if ( a_req.query.ext ) - par.ext = a_req.query.ext; + if (a_req.query.ext) par.ext = a_req.query.ext; - if ( a_req.query.check ) - par.check = a_req.query.check; + if (a_req.query.check) par.check = a_req.query.check; - sendMessage( "DataPutRequest", par, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); -}); + const { collection_id, collection_type } = a_req.query; + par.collectionId = collection_id; + par.collectionType = collection_type; -app.get('/api/dat/dep/get', ( a_req, a_resp ) => { - sendMessage( "RecordGetDependenciesRequest", { id: a_req.query.ids }, a_req, a_resp, function( reply ) { + sendMessage("DataPutRequest", par, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/dat/dep/graph/get', ( a_req, a_resp ) => { - sendMessage( "RecordGetDependencyGraphRequest", { id: a_req.query.id }, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/dat/dep/get", (a_req, a_resp) => { + sendMessage( + "RecordGetDependenciesRequest", + { id: a_req.query.ids }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/dat/alloc_chg', ( a_req, a_resp ) => { +app.get("/api/dat/dep/graph/get", (a_req, a_resp) => { + sendMessage( + "RecordGetDependencyGraphRequest", + { id: a_req.query.id }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); +}); +app.get("/api/dat/alloc_chg", (a_req, a_resp) => { var params = { id: JSON.parse(a_req.query.id) }; - if ( a_req.query.repo_id ) - params.repoId = a_req.query.repo_id; - if ( a_req.query.proj_id ) - params.projId = a_req.query.proj_id; - if ( a_req.query.check ) - params.check = true; - - sendMessage( "RecordAllocChangeRequest", params, a_req, a_resp, function( reply ) { + if (a_req.query.repo_id) params.repoId = a_req.query.repo_id; + if (a_req.query.proj_id) params.projId = a_req.query.proj_id; + if (a_req.query.check) params.check = true; + + sendMessage("RecordAllocChangeRequest", params, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/dat/owner_chg', ( a_req, a_resp ) => { +app.get("/api/dat/owner_chg", (a_req, a_resp) => { var params = { id: JSON.parse(a_req.query.id), collId: a_req.query.coll_id }; - if ( a_req.query.repo_id ) - params.repoId = a_req.query.repo_id; - if ( a_req.query.proj_id ) - params.projId = a_req.query.proj_id; - if ( a_req.query.check ) - params.check = true; + if (a_req.query.repo_id) params.repoId = a_req.query.repo_id; + if (a_req.query.proj_id) params.projId = a_req.query.proj_id; + if (a_req.query.check) params.check = true; - - sendMessage( "RecordOwnerChangeRequest", params, a_req, a_resp, function( reply ) { + sendMessage("RecordOwnerChangeRequest", params, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.post('/api/metadata/validate', ( a_req, a_resp ) => { - sendMessage( "MetadataValidateRequest", a_req.body, a_req, a_resp, function( reply ) { +app.post("/api/metadata/validate", (a_req, a_resp) => { + sendMessage("MetadataValidateRequest", a_req.body, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/perms/check', ( a_req, a_resp ) => { +app.get("/api/perms/check", (a_req, a_resp) => { var params = { id: a_req.query.id }; - if ( a_req.query.perms != undefined ) - params.perms = a_req.query.perms; - if ( a_req.query.any != undefined ) - params.any = a_req.query.any; - sendMessage( "CheckPermsRequest", params, a_req, a_resp, function( reply ) { + if (a_req.query.perms != undefined) params.perms = a_req.query.perms; + if (a_req.query.any != undefined) params.any = a_req.query.any; + sendMessage("CheckPermsRequest", params, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/perms/get', ( a_req, a_resp ) => { +app.get("/api/perms/get", (a_req, a_resp) => { var params = { id: a_req.query.id }; - if ( a_req.query.perms != undefined ) - params.perms = a_req.query.perms; - sendMessage( "GetPermsRequest", params, a_req, a_resp, function( reply ) { + if (a_req.query.perms != undefined) params.perms = a_req.query.perms; + sendMessage("GetPermsRequest", params, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/acl/view', ( a_req, a_resp ) => { - sendMessage( "ACLViewRequest", { id: a_req.query.id }, a_req, a_resp, function( reply ) { +app.get("/api/acl/view", (a_req, a_resp) => { + sendMessage("ACLViewRequest", { id: a_req.query.id }, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/acl/update', ( a_req, a_resp ) => { - sendMessage( "ACLUpdateRequest", { id: a_req.query.id, rules: a_req.query.rules }, a_req, a_resp, function( reply ) { - if ( reply.rule && reply.rule.length ){ - logger.debug('/api/acl/update', getCurrentLineNumber(), "User: " + a_req.session.uid + " - ACL update, id: " + a_req.query.id + " " + a_req.query.rules ); - } - a_resp.send(reply); - }); +app.get("/api/acl/update", (a_req, a_resp) => { + sendMessage( + "ACLUpdateRequest", + { id: a_req.query.id, rules: a_req.query.rules }, + a_req, + a_resp, + function (reply) { + if (reply.rule && reply.rule.length) { + logger.debug( + "/api/acl/update", + getCurrentLineNumber(), + "User: " + + a_req.session.uid + + " - ACL update, id: " + + a_req.query.id + + " " + + a_req.query.rules, + ); + } + a_resp.send(reply); + }, + ); }); -app.get('/api/acl/shared/list', ( a_req, a_resp ) => { - sendMessage( "ACLSharedListRequest", {incUsers:a_req.query.inc_users?true:false,incProjects:a_req.query.inc_projects?true:false}, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/acl/shared/list", (a_req, a_resp) => { + sendMessage( + "ACLSharedListRequest", + { + incUsers: a_req.query.inc_users ? true : false, + incProjects: a_req.query.inc_projects ? true : false, + }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/acl/shared/list/items', ( a_req, a_resp ) => { - sendMessage( "ACLSharedListItemsRequest", {owner:a_req.query.owner}, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/acl/shared/list/items", (a_req, a_resp) => { + sendMessage( + "ACLSharedListItemsRequest", + { owner: a_req.query.owner }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); - -app.get('/api/note/create', ( a_req, a_resp ) => { - var params = { +app.get("/api/note/create", (a_req, a_resp) => { + var params = { type: a_req.query.type, subject: a_req.query.subject, title: a_req.query.title, comment: a_req.query.comment, - activate: a_req.query.activate + activate: a_req.query.activate, }; - sendMessage( "NoteCreateRequest", params, a_req, a_resp, function( reply ) { + sendMessage("NoteCreateRequest", params, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/note/update', ( a_req, a_resp ) => { - var params = { +app.get("/api/note/update", (a_req, a_resp) => { + var params = { id: a_req.query.id, comment: a_req.query.comment, }; - if ( a_req.query.new_type ) - params.newType = a_req.query.new_type; + if (a_req.query.new_type) params.newType = a_req.query.new_type; - if ( a_req.query.new_state ) - params.newState = a_req.query.new_state; + if (a_req.query.new_state) params.newState = a_req.query.new_state; - if ( a_req.query.new_title ) - params.newTitle = a_req.query.new_title; + if (a_req.query.new_title) params.newTitle = a_req.query.new_title; - sendMessage( "NoteUpdateRequest", params, a_req, a_resp, function( reply ) { + sendMessage("NoteUpdateRequest", params, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/note/comment/edit', ( a_req, a_resp ) => { - var params = { +app.get("/api/note/comment/edit", (a_req, a_resp) => { + var params = { id: a_req.query.id, comment: a_req.query.comment, - commentIdx: a_req.query.comment_idx + commentIdx: a_req.query.comment_idx, }; - sendMessage( "NoteCommentEditRequest", params, a_req, a_resp, function( reply ) { + sendMessage("NoteCommentEditRequest", params, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/note/view', ( a_req, a_resp ) => { - sendMessage( "NoteViewRequest", { id:a_req.query.id}, a_req, a_resp, function( reply ) { +app.get("/api/note/view", (a_req, a_resp) => { + sendMessage("NoteViewRequest", { id: a_req.query.id }, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/note/list/by_subject', ( a_req, a_resp ) => { - sendMessage( "NoteListBySubjectRequest", { subject:a_req.query.subject}, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/note/list/by_subject", (a_req, a_resp) => { + sendMessage( + "NoteListBySubjectRequest", + { subject: a_req.query.subject }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/tag/search', ( a_req, a_resp ) => { +app.get("/api/tag/search", (a_req, a_resp) => { var par = { name: a_req.query.name }; - if ( a_req.query.offset != undefined && a_req.query.count != undefined ){ + if (a_req.query.offset != undefined && a_req.query.count != undefined) { par.offset = a_req.query.offset; par.count = a_req.query.count; } - sendMessage( "TagSearchRequest", par, a_req, a_resp, function( reply ) { + sendMessage("TagSearchRequest", par, a_req, a_resp, function (reply) { a_resp.json(reply); }); }); -app.get('/api/tag/autocomp', ( a_req, a_resp ) => { +app.get("/api/tag/autocomp", (a_req, a_resp) => { var par = { name: a_req.query.term, offset: 0, count: 20 }; - sendMessage( "TagSearchRequest", par, a_req, a_resp, function( reply ) { - var res = [], tag; - if ( reply.tag ){ - for ( var i in reply.tag ){ + sendMessage("TagSearchRequest", par, a_req, a_resp, function (reply) { + var res = [], + tag; + if (reply.tag) { + for (var i in reply.tag) { tag = reply.tag[i]; res.push({ value: tag.name, label: tag.name + " (" + tag.count + ")" }); } } - a_resp.json( res ); + a_resp.json(res); }); }); // TODO This doesn't seem to be used anymore -app.get('/api/tag/list/by_count', ( a_req, a_resp ) => { +app.get("/api/tag/list/by_count", (a_req, a_resp) => { var par = {}; - if ( a_req.query.offset != undefined && a_req.query.count != undefined ){ + if (a_req.query.offset != undefined && a_req.query.count != undefined) { par.offset = a_req.query.offset; par.count = a_req.query.count; } - sendMessage( "TagListByCountRequest", par, a_req, a_resp, function( reply ) { + sendMessage("TagListByCountRequest", par, a_req, a_resp, function (reply) { a_resp.json(reply); }); }); -app.get('/api/task/list', ( a_req, a_resp ) => { +app.get("/api/task/list", (a_req, a_resp) => { var params = {}; - if ( a_req.query.since ) - params.since = a_req.query.since; - sendMessage( "TaskListRequest", params, a_req, a_resp, function( reply ) { + if (a_req.query.since) params.since = a_req.query.since; + sendMessage("TaskListRequest", params, a_req, a_resp, function (reply) { a_resp.json(reply); }); }); -app.get('/api/task/view', ( a_req, a_resp ) => { - sendMessage( "TaskViewRequest", {"taskId":a_req.query.id}, a_req, a_resp, function( reply ) { +app.get("/api/task/view", (a_req, a_resp) => { + sendMessage("TaskViewRequest", { taskId: a_req.query.id }, a_req, a_resp, function (reply) { a_resp.json(reply); }); }); -app.post('/api/col/create', ( a_req, a_resp ) => { - sendMessage( "CollCreateRequest", a_req.body, a_req, a_resp, function( reply ) { +app.post("/api/col/create", (a_req, a_resp) => { + sendMessage("CollCreateRequest", a_req.body, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.post('/api/col/update', ( a_req, a_resp ) => { - sendMessage( "CollUpdateRequest", a_req.body, a_req, a_resp, function( reply ) { +app.post("/api/col/update", (a_req, a_resp) => { + sendMessage("CollUpdateRequest", a_req.body, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/col/delete', ( a_req, a_resp ) => { - sendMessage( "CollDeleteRequest", { id: JSON.parse(a_req.query.ids)}, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/col/delete", (a_req, a_resp) => { + sendMessage( + "CollDeleteRequest", + { id: JSON.parse(a_req.query.ids) }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/col/view', ( a_req, a_resp ) => { - sendMessage( "CollViewRequest", { id: a_req.query.id }, a_req, a_resp, function( reply ) { - if ( reply.coll && reply.coll.length ){ +app.get("/api/col/view", (a_req, a_resp) => { + sendMessage("CollViewRequest", { id: a_req.query.id }, a_req, a_resp, function (reply) { + if (reply.coll && reply.coll.length) { a_resp.send(reply.coll[0]); - }else{ + } else { a_resp.send(); } }); }); -app.get('/api/col/read', ( a_req, a_resp ) => { +app.get("/api/col/read", (a_req, a_resp) => { var par = { id: a_req.query.id }; - if ( a_req.query.offset != undefined && a_req.query.count != undefined ){ + if (a_req.query.offset != undefined && a_req.query.count != undefined) { par.offset = a_req.query.offset; par.count = a_req.query.count; } - sendMessage( "CollReadRequest", par, a_req, a_resp, function( reply ) { + sendMessage("CollReadRequest", par, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/col/get_parents', ( a_req, a_resp ) => { - sendMessage( "CollGetParentsRequest", { id: a_req.query.id }, a_req, a_resp, function( reply ) { +app.get("/api/col/get_parents", (a_req, a_resp) => { + sendMessage("CollGetParentsRequest", { id: a_req.query.id }, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/col/get_offset', ( a_req, a_resp ) => { - sendMessage( "CollGetOffsetRequest", { id: a_req.query.id, item: a_req.query.item_id, pageSz: a_req.query.page_sz}, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/col/get_offset", (a_req, a_resp) => { + sendMessage( + "CollGetOffsetRequest", + { id: a_req.query.id, item: a_req.query.item_id, pageSz: a_req.query.page_sz }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/col/move', ( a_req, a_resp ) => { - sendMessage( "CollMoveRequest", { srcId: a_req.query.src_id, dstId: a_req.query.dst_id, item: JSON.parse(a_req.query.items) }, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/col/move", (a_req, a_resp) => { + sendMessage( + "CollMoveRequest", + { + srcId: a_req.query.src_id, + dstId: a_req.query.dst_id, + item: JSON.parse(a_req.query.items), + }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/col/link', ( a_req, a_resp ) => { - sendMessage( "CollWriteRequest", { id: a_req.query.coll, add: JSON.parse(a_req.query.items) }, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/col/link", (a_req, a_resp) => { + sendMessage( + "CollWriteRequest", + { id: a_req.query.coll, add: JSON.parse(a_req.query.items) }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/col/unlink', ( a_req, a_resp ) => { - sendMessage( "CollWriteRequest", { id: a_req.query.coll, rem: JSON.parse(a_req.query.items) }, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/col/unlink", (a_req, a_resp) => { + sendMessage( + "CollWriteRequest", + { id: a_req.query.coll, rem: JSON.parse(a_req.query.items) }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/col/published/list', ( a_req, a_resp ) => { +app.get("/api/col/published/list", (a_req, a_resp) => { var par = { subject: a_req.query.subject }; - if ( a_req.query.offset != undefined && a_req.query.count != undefined ){ + if (a_req.query.offset != undefined && a_req.query.count != undefined) { par.offset = a_req.query.offset; par.count = a_req.query.count; } - sendMessage( "CollListPublishedRequest", par, a_req, a_resp, function( reply ) { + sendMessage("CollListPublishedRequest", par, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); - -app.post('/api/cat/search', ( a_req, a_resp ) => { - sendMessage( "CatalogSearchRequest", a_req.body, a_req, a_resp, function( reply ) { +app.post("/api/cat/search", (a_req, a_resp) => { + sendMessage("CatalogSearchRequest", a_req.body, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); +app.get("/api/globus/consent_url", storeCollectionId, (a_req, a_resp) => { + const { requested_scopes, state, refresh_tokens, query_params } = a_req.query; -app.post('/api/col/pub/search/data', ( a_req, a_resp ) => { - sendMessage( "RecordSearchPublishedRequest", a_req.body, a_req, a_resp, function( reply ) { + const consent_url = generateConsentURL( + g_oauth_credentials.clientId, + g_oauth_credentials.redirectUri, + refresh_tokens, + requested_scopes, + query_params, + state, + ); + + a_resp.json({ consent_url }); +}); + +app.post("/api/col/pub/search/data", (a_req, a_resp) => { + sendMessage("RecordSearchPublishedRequest", a_req.body, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); - -app.get('/api/repo/list', ( a_req, a_resp ) => { +app.get("/api/repo/list", (a_req, a_resp) => { var params = {}; - if ( a_req.query.all ) - params.all = a_req.query.all; - if ( a_req.query.details ) - params.details = a_req.query.details; - sendMessage( "RepoListRequest", params, a_req, a_resp, function( reply ) { - a_resp.json(reply.repo?reply.repo:[]); + if (a_req.query.all) params.all = a_req.query.all; + if (a_req.query.details) params.details = a_req.query.details; + sendMessage("RepoListRequest", params, a_req, a_resp, function (reply) { + a_resp.json(reply.repo ? reply.repo : []); }); }); -app.get('/api/repo/view', ( a_req, a_resp ) => { - sendMessage( "RepoViewRequest", {id:a_req.query.id}, a_req, a_resp, function( reply ) { - a_resp.json(reply.repo?reply.repo:[]); +app.get("/api/repo/view", (a_req, a_resp) => { + sendMessage("RepoViewRequest", { id: a_req.query.id }, a_req, a_resp, function (reply) { + a_resp.json(reply.repo ? reply.repo : []); }); }); -app.post('/api/repo/create', ( a_req, a_resp ) => { - sendMessage( "RepoCreateRequest", a_req.body, a_req, a_resp, function( reply ) { +app.post("/api/repo/create", (a_req, a_resp) => { + sendMessage("RepoCreateRequest", a_req.body, a_req, a_resp, function (reply) { a_resp.json({}); }); }); -app.post('/api/repo/update', ( a_req, a_resp ) => { - sendMessage( "RepoUpdateRequest", a_req.body, a_req, a_resp, function( reply ) { +app.post("/api/repo/update", (a_req, a_resp) => { + sendMessage("RepoUpdateRequest", a_req.body, a_req, a_resp, function (reply) { a_resp.json({}); }); }); -app.get('/api/repo/delete', ( a_req, a_resp ) => { - sendMessage( "RepoDeleteRequest", {id:a_req.query.id}, a_req, a_resp, function( reply ) { +app.get("/api/repo/delete", (a_req, a_resp) => { + sendMessage("RepoDeleteRequest", { id: a_req.query.id }, a_req, a_resp, function (reply) { a_resp.json({}); }); }); -app.get('/api/repo/calc_size', ( a_req, a_resp ) => { - sendMessage( "RepoCalcSizeRequest", {recurse:a_req.query.recurse=="true"?true:false,item:JSON.parse(a_req.query.items)}, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/repo/calc_size", (a_req, a_resp) => { + sendMessage( + "RepoCalcSizeRequest", + { + recurse: a_req.query.recurse == "true" ? true : false, + item: JSON.parse(a_req.query.items), + }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/repo/alloc/list/by_repo', ( a_req, a_resp ) => { - sendMessage( "RepoListAllocationsRequest", {id:a_req.query.id}, a_req, a_resp, function( reply ) { - a_resp.json(reply.alloc?reply.alloc:[]); - }); +app.get("/api/repo/alloc/list/by_repo", (a_req, a_resp) => { + sendMessage( + "RepoListAllocationsRequest", + { id: a_req.query.id }, + a_req, + a_resp, + function (reply) { + a_resp.json(reply.alloc ? reply.alloc : []); + }, + ); }); -app.get('/api/repo/alloc/list/by_subject', ( a_req, a_resp ) => { +app.get("/api/repo/alloc/list/by_subject", (a_req, a_resp) => { var par = {}; - if ( a_req.query.subject != undefined ) - par.subject = a_req.query.subject; - if ( a_req.query.stats == "true" ) - par.stats = true; + if (a_req.query.subject != undefined) par.subject = a_req.query.subject; + if (a_req.query.stats == "true") par.stats = true; - sendMessage( "RepoListSubjectAllocationsRequest", par, a_req, a_resp, function( reply ) { - a_resp.json(reply.alloc?reply.alloc:[]); + sendMessage("RepoListSubjectAllocationsRequest", par, a_req, a_resp, function (reply) { + a_resp.json(reply.alloc ? reply.alloc : []); }); }); -app.get('/api/repo/alloc/list/by_object', ( a_req, a_resp ) => { - sendMessage( "RepoListObjectAllocationsRequest", {id:a_req.query.id}, a_req, a_resp, function( reply ) { - a_resp.json(reply.alloc?reply.alloc:[]); - }); +app.get("/api/repo/alloc/list/by_object", (a_req, a_resp) => { + sendMessage( + "RepoListObjectAllocationsRequest", + { id: a_req.query.id }, + a_req, + a_resp, + function (reply) { + a_resp.json(reply.alloc ? reply.alloc : []); + }, + ); }); -app.get('/api/repo/alloc/view', ( a_req, a_resp ) => { - sendMessage( "RepoViewAllocationRequest", {repo:a_req.query.repo,subject:a_req.query.subject}, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/repo/alloc/view", (a_req, a_resp) => { + sendMessage( + "RepoViewAllocationRequest", + { repo: a_req.query.repo, subject: a_req.query.subject }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/repo/alloc/stats', ( a_req, a_resp ) => { - sendMessage( "RepoAllocationStatsRequest", {repo:a_req.query.repo,subject:a_req.query.subject}, a_req, a_resp, function( reply ) { - a_resp.json(reply.alloc?reply.alloc:{}); - }); +app.get("/api/repo/alloc/stats", (a_req, a_resp) => { + sendMessage( + "RepoAllocationStatsRequest", + { repo: a_req.query.repo, subject: a_req.query.subject }, + a_req, + a_resp, + function (reply) { + a_resp.json(reply.alloc ? reply.alloc : {}); + }, + ); }); -app.get('/api/repo/alloc/create', ( a_req, a_resp ) => { - sendMessage( "RepoAllocationCreateRequest", {repo:a_req.query.repo,subject:a_req.query.subject,dataLimit:a_req.query.data_limit,recLimit:a_req.query.rec_limit}, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/repo/alloc/create", (a_req, a_resp) => { + sendMessage( + "RepoAllocationCreateRequest", + { + repo: a_req.query.repo, + subject: a_req.query.subject, + dataLimit: a_req.query.data_limit, + recLimit: a_req.query.rec_limit, + }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/repo/alloc/delete', ( a_req, a_resp ) => { - sendMessage( "RepoAllocationDeleteRequest", {repo:a_req.query.repo,subject:a_req.query.subject}, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/repo/alloc/delete", (a_req, a_resp) => { + sendMessage( + "RepoAllocationDeleteRequest", + { repo: a_req.query.repo, subject: a_req.query.subject }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/repo/alloc/set', ( a_req, a_resp ) => { - sendMessage( "RepoAllocationSetRequest", {repo:a_req.query.repo,subject:a_req.query.subject,dataLimit:a_req.query.data_limit,recLimit:a_req.query.rec_limit}, a_req, a_resp, function( reply ) { - a_resp.send(reply); - }); +app.get("/api/repo/alloc/set", (a_req, a_resp) => { + sendMessage( + "RepoAllocationSetRequest", + { + repo: a_req.query.repo, + subject: a_req.query.subject, + dataLimit: a_req.query.data_limit, + recLimit: a_req.query.rec_limit, + }, + a_req, + a_resp, + function (reply) { + a_resp.send(reply); + }, + ); }); -app.get('/api/repo/alloc/set/default', ( a_req, a_resp ) => { - var par = {repo:a_req.query.repo}; - if ( a_req.query.subject ) - par.subject = a_req.query.subject; +app.get("/api/repo/alloc/set/default", (a_req, a_resp) => { + var par = { repo: a_req.query.repo }; + if (a_req.query.subject) par.subject = a_req.query.subject; - sendMessage( "RepoAllocationSetDefaultRequest", par, a_req, a_resp, function( reply ) { + sendMessage("RepoAllocationSetDefaultRequest", par, a_req, a_resp, function (reply) { a_resp.send(reply); }); }); -app.get('/api/top/list/topics', ( a_req, a_resp ) => { - var par = {} +app.get("/api/top/list/topics", (a_req, a_resp) => { + var par = {}; - if ( a_req.query.id ) - par.topicId = a_req.query.id; + if (a_req.query.id) par.topicId = a_req.query.id; - if ( a_req.query.offset != undefined && a_req.query.count != undefined ){ + if (a_req.query.offset != undefined && a_req.query.count != undefined) { par.offset = a_req.query.offset; par.count = a_req.query.count; } - sendMessage( "TopicListTopicsRequest", par, a_req, a_resp, function( reply ) { + sendMessage("TopicListTopicsRequest", par, a_req, a_resp, function (reply) { a_resp.json(reply); }); }); -app.get('/api/top/list/coll', ( a_req, a_resp ) => { - var par = {topicId:a_req.query.id}; - if ( a_req.query.offset != undefined && a_req.query.count != undefined ){ +app.get("/api/top/list/coll", (a_req, a_resp) => { + var par = { topicId: a_req.query.id }; + if (a_req.query.offset != undefined && a_req.query.count != undefined) { par.offset = a_req.query.offset; par.count = a_req.query.count; } - sendMessage( "TopicListCollectionsRequest", par, a_req, a_resp, function( reply ) { + sendMessage("TopicListCollectionsRequest", par, a_req, a_resp, function (reply) { a_resp.json(reply); }); }); -app.get('/api/top/view', ( a_req, a_resp ) => { - sendMessage( "TopicViewRequest", { id: a_req.query.id }, a_req, a_resp, function( reply ) { +app.get("/api/top/view", (a_req, a_resp) => { + sendMessage("TopicViewRequest", { id: a_req.query.id }, a_req, a_resp, function (reply) { a_resp.json(reply); }); }); -app.get('/api/top/search', ( a_req, a_resp ) => { - sendMessage( "TopicSearchRequest", {phrase:a_req.query.phrase}, a_req, a_resp, function( reply ) { - a_resp.json(reply); - }); +app.get("/api/top/search", (a_req, a_resp) => { + sendMessage( + "TopicSearchRequest", + { phrase: a_req.query.phrase }, + a_req, + a_resp, + function (reply) { + a_resp.json(reply); + }, + ); }); -app.get('/api/sch/view', ( a_req, a_resp ) => { - sendMessage( "SchemaViewRequest", { id: a_req.query.id, resolve: a_req.query.resolve }, a_req, a_resp, function( reply ) { - a_resp.json(reply); - }); +app.get("/api/sch/view", (a_req, a_resp) => { + sendMessage( + "SchemaViewRequest", + { id: a_req.query.id, resolve: a_req.query.resolve }, + a_req, + a_resp, + function (reply) { + a_resp.json(reply); + }, + ); }); -app.post('/api/sch/search', ( a_req, a_resp ) => { - sendMessage( "SchemaSearchRequest", a_req.body, a_req, a_resp, function( reply ) { +app.post("/api/sch/search", (a_req, a_resp) => { + sendMessage("SchemaSearchRequest", a_req.body, a_req, a_resp, function (reply) { a_resp.json(reply); }); }); -app.post('/api/sch/create', ( a_req, a_resp ) => { - sendMessage( "SchemaCreateRequest", a_req.body, a_req, a_resp, function( reply ) { +app.post("/api/sch/create", (a_req, a_resp) => { + sendMessage("SchemaCreateRequest", a_req.body, a_req, a_resp, function (reply) { a_resp.json(reply); }); }); -app.post('/api/sch/revise', ( a_req, a_resp ) => { - sendMessage( "SchemaReviseRequest", a_req.body, a_req, a_resp, function( reply ) { +app.post("/api/sch/revise", (a_req, a_resp) => { + sendMessage("SchemaReviseRequest", a_req.body, a_req, a_resp, function (reply) { a_resp.json(reply); }); }); -app.post('/api/sch/update', ( a_req, a_resp ) => { - sendMessage( "SchemaUpdateRequest", a_req.body, a_req, a_resp, function( reply ) { +app.post("/api/sch/update", (a_req, a_resp) => { + sendMessage("SchemaUpdateRequest", a_req.body, a_req, a_resp, function (reply) { a_resp.json(reply); }); }); -app.post('/api/sch/delete', ( a_req, a_resp ) => { - sendMessage( "SchemaDeleteRequest", { id: a_req.query.id }, a_req, a_resp, function( reply ) { +app.post("/api/sch/delete", (a_req, a_resp) => { + sendMessage("SchemaDeleteRequest", { id: a_req.query.id }, a_req, a_resp, function (reply) { a_resp.json(reply); }); }); -app.get('/ui/ep/view', ( a_req, a_resp ) => { - - sendMessage( "UserGetAccessTokenRequest", {}, a_req, a_resp, function( reply ) { +app.get("/ui/ep/view", (a_req, a_resp) => { + // TODO: include message data if needed + sendMessage("UserGetAccessTokenRequest", {}, a_req, a_resp, function (reply) { const opts = { - hostname: 'transfer.api.globusonline.org', - method: 'GET', - path: '/v0.10/endpoint/' + encodeURIComponent(a_req.query.ep), + hostname: "transfer.api.globusonline.org", + method: "GET", + path: "/v0.10/endpoint/" + encodeURIComponent(a_req.query.ep), rejectUnauthorized: true, - headers:{ - Authorization: ' Bearer ' + reply.access - } + headers: { + Authorization: " Bearer " + reply.access, + }, }; - const req = https.request( opts, (res) => { - var data = ''; + const req = https.request(opts, (res) => { + var data = ""; - res.on('data', (chunk) => { + res.on("data", (chunk) => { data += chunk; }); - res.on('end', () => { + res.on("end", () => { a_resp.json(JSON.parse(data)); }); }); - req.on('error', (e) => { - a_resp.status( 500 ); - a_resp.send( "Globus endpoint view failed." ); + req.on("error", (e) => { + a_resp.status(500); + a_resp.send("Globus endpoint view failed."); }); req.end(); }); }); -app.get('/ui/ep/autocomp', ( a_req, a_resp ) => { - - sendMessage( "UserGetAccessTokenRequest", {}, a_req, a_resp, function( reply ) { - +app.get("/ui/ep/autocomp", (a_req, a_resp) => { + // TODO: include message data if needed + sendMessage("UserGetAccessTokenRequest", {}, a_req, a_resp, function (reply) { const opts = { - hostname: 'transfer.api.globusonline.org', - method: 'GET', - path: '/v0.10/endpoint_search?filter_scope=all&fields=display_name,canonical_name,id,description,organization,activated,expires_in,default_directory&filter_fulltext='+encodeURIComponent(a_req.query.term), + hostname: "transfer.api.globusonline.org", + method: "GET", + path: + "/v0.10/endpoint_search?filter_scope=all&fields=display_name,canonical_name,id,description,organization,activated,expires_in,default_directory&filter_fulltext=" + + encodeURIComponent(a_req.query.term), rejectUnauthorized: true, - headers:{ - Authorization: ' Bearer ' + reply.access - } + headers: { + Authorization: " Bearer " + reply.access, + }, }; - const req = https.request( opts, (res) => { - var data = ''; + const req = https.request(opts, (res) => { + var data = ""; - res.on('data', (chunk) => { + res.on("data", (chunk) => { data += chunk; }); - res.on('end', () => { + res.on("end", () => { a_resp.json(JSON.parse(data)); }); }); - req.on('error', (e) => { - a_resp.status( 500 ); - a_resp.send( "Globus endpoint search failed." ); + req.on("error", (e) => { + a_resp.status(500); + a_resp.send("Globus endpoint search failed."); }); req.end(); }); }); -app.get('/ui/ep/recent/load', ( a_req, a_resp ) => { - sendMessage( "UserGetRecentEPRequest", {}, a_req, a_resp, function( reply ) { - a_resp.json(reply.ep?reply.ep:[]); +app.get("/ui/ep/recent/load", (a_req, a_resp) => { + sendMessage("UserGetRecentEPRequest", {}, a_req, a_resp, function (reply) { + a_resp.json(reply.ep ? reply.ep : []); }); }); -app.post('/ui/ep/recent/save', ( a_req, a_resp ) => { - sendMessage( "UserSetRecentEPRequest", a_req.body, a_req, a_resp, function( reply ) { +app.post("/ui/ep/recent/save", (a_req, a_resp) => { + sendMessage("UserSetRecentEPRequest", a_req.body, a_req, a_resp, function (reply) { a_resp.json({}); }); }); -app.get('/ui/ep/dir/list', ( a_req, a_resp ) => { - sendMessage( "UserGetAccessTokenRequest", {}, a_req, a_resp, function( reply ) { +app.get("/ui/ep/dir/list", (a_req, a_resp) => { + const message_data = { + collectionId: a_req.query.collection_id, + collectionType: a_req.query.collection_type, + }; + const get_from_globus_api = (token, original_reply) => { const opts = { - hostname: 'transfer.api.globusonline.org', - method: 'GET', - path: '/v0.10/operation/endpoint/' + encodeURIComponent(a_req.query.ep) + '/ls?path=' + encodeURIComponent(a_req.query.path) + '&show_hidden=' + a_req.query.hidden, + hostname: "transfer.api.globusonline.org", + method: "GET", + path: + "/v0.10/operation/endpoint/" + + encodeURIComponent(a_req.query.ep) + + "/ls?path=" + + encodeURIComponent(a_req.query.path) + + "&show_hidden=" + + a_req.query.hidden, rejectUnauthorized: true, - headers:{ - Authorization: ' Bearer ' + reply.access - } + headers: { + Authorization: " Bearer " + token, + }, }; - const req = https.request( opts, (res) => { - var data = ''; + const req = https.request(opts, (res) => { + let data = ""; - res.on('data', (chunk) => { + res.on("data", (chunk) => { data += chunk; }); - res.on('end', () => { - a_resp.json(JSON.parse(data)); + res.on("end", () => { + let res_json = JSON.parse(data); + res_json.needs_consent = original_reply.needsConsent; + a_resp.json(res_json); }); }); - req.on('error', (e) => { - a_resp.status( 500 ); - a_resp.send( "Globus endpoint directoy listing failed." ); + req.on("error", (e) => { + a_resp.status(500); + a_resp.send("Globus endpoint directoy listing failed."); }); req.end(); - }); - -}); - + }; -app.get('/ui/theme/load', ( a_req, a_resp ) => { - var theme = a_req.cookies['datafed-theme']; - a_resp.send( theme ); + sendMessage("UserGetAccessTokenRequest", { ...message_data }, a_req, a_resp, function (reply) { + if (reply.needsConsent) { + sendMessage("UserGetAccessTokenRequest", {}, a_req, a_resp, (base_token_reply) => { + // TODO: does a failed refresh token affect this? will base token be valid? + get_from_globus_api(base_token_reply.access, reply); + }); + } else { + get_from_globus_api(reply.access, reply); + } + }); }); -app.get('/ui/theme/save', ( a_req, a_resp ) => { - a_resp.cookie( 'datafed-theme', a_req.query.theme, { httpOnly: true, path: "/ui", maxAge: 31536000000 /*1 year in msec */ }); - a_resp.send("{\"ok\":true}"); +app.get("/ui/theme/load", (a_req, a_resp) => { + var theme = a_req.cookies["datafed-theme"]; + a_resp.send(theme); }); - -function setAccessToken( a_uid, a_acc_tok, a_ref_tok, a_expires_sec ) { - logger.info(setAccessToken.name, getCurrentLineNumber(), "setAccessToken uid: " + a_uid + " expires in: " + a_expires_sec); - sendMessageDirect( "UserSetAccessTokenRequest", a_uid, { access: a_acc_tok, refresh: a_ref_tok, expiresIn: a_expires_sec }, function( reply ){ +app.get("/ui/theme/save", (a_req, a_resp) => { + a_resp.cookie("datafed-theme", a_req.query.theme, { + httpOnly: true, + path: "/ui", + maxAge: 31536000000 /*1 year in msec */, + }); + a_resp.send('{"ok":true}'); +}); + +/** Puts message on ZeroMQ to set a user access token + * + * @param {string} a_uid - UID to which the access token belongs + * @param {string} a_acc_tok - Access token to be associated with user + * @param {string} a_ref_tok - Refresh token for access token + * @param {number} a_expires_sec - Time until expiration of access token + * @param {OptionalData} [token_optional_params] - Optional params for DataFed to process access token accordingly + * + * @throws Error - When a reply is not received from sendMessageDirect + */ +function setAccessToken(a_uid, a_acc_tok, a_ref_tok, a_expires_sec, token_optional_params = {}) { + logger.info( + setAccessToken.name, + getCurrentLineNumber(), + "setAccessToken uid: " + a_uid + " expires in: " + a_expires_sec, + ); + let message_data = { access: a_acc_tok, refresh: a_ref_tok, expiresIn: a_expires_sec }; + if (token_optional_params && Object.keys(token_optional_params).length > 0) { + message_data = { ...token_optional_params, ...message_data }; + } + sendMessageDirect("UserSetAccessTokenRequest", a_uid, message_data, function (reply) { // Should be an AckReply + if (!reply) { + logger.error("setAccessToken", getCurrentLineNumber(), "failed."); + throw new Error("setAccessToken failed"); + } }); } - -function allocRequestContext( a_resp, a_callback ) { +function allocRequestContext(a_resp, a_callback) { var ctx = g_ctx_next; // At max ctx, must search for first free slot - if ( ctx == MAX_CTX ) { - ctx = g_ctx.indexOf( null ); - if ( ctx == -1 ) { - logger.critical(allocRequestContext.name, getCurrentLineNumber(), "ERROR: out of msg contexts!!!"); - if ( a_resp ) { + if (ctx == MAX_CTX) { + ctx = g_ctx.indexOf(null); + if (ctx == -1) { + logger.critical( + allocRequestContext.name, + getCurrentLineNumber(), + "ERROR: out of msg contexts!!!", + ); + if (a_resp) { logger.error(allocRequestContext.name, getCurrentLineNumber(), "SEND FAIL"); - a_resp.status( 503 ); - a_resp.send( "DataFed server busy." ); + a_resp.status(503); + a_resp.send("DataFed server busy."); } } } // Set next ctx value, or flag for search - if ( ++g_ctx_next < MAX_CTX ) { - if ( g_ctx[g_ctx_next] ) - g_ctx_next = MAX_CTX; + if (++g_ctx_next < MAX_CTX) { + if (g_ctx[g_ctx_next]) g_ctx_next = MAX_CTX; } - a_callback( ctx ); + a_callback(ctx); } - -function sendMessage( a_msg_name, a_msg_data, a_req, a_resp, a_cb, a_anon ) { +function sendMessage(a_msg_name, a_msg_data, a_req, a_resp, a_cb, a_anon) { var client = a_req.session.uid; - if ( !client ){ - logger.info(sendMessage.name, getCurrentLineNumber(), "NO AUTH :" + a_msg_name + ":" + a_req.connection.remoteAddress ); + if (!client) { + logger.info( + sendMessage.name, + getCurrentLineNumber(), + "NO AUTH :" + a_msg_name + ":" + a_req.connection.remoteAddress, + ); throw "Not Authenticated"; } - a_resp.setHeader('Content-Type', 'application/json'); - - allocRequestContext( a_resp, function( ctx ){ + a_resp.setHeader("Content-Type", "application/json"); + allocRequestContext(a_resp, function (ctx) { var msg = g_msg_by_name[a_msg_name]; - if ( !msg ) - throw "Invalid message type: " + a_msg_name; + if (!msg) throw "Invalid message type: " + a_msg_name; var msg_buf = msg.encode(a_msg_data).finish(); var frame = Buffer.alloc(8); - frame.writeUInt32BE( msg_buf.length, 0 ); - frame.writeUInt8( msg._pid, 4 ); - frame.writeUInt8( msg._mid, 5 ); - frame.writeUInt16BE( ctx, 6 ); - - g_ctx[ctx] = function( a_reply ) { - if ( !a_reply ) { - logger.error(sendMessage.name, getCurrentLineNumber(), "Error - reply handler: empty reply"); - a_resp.status(500).send( "Empty reply" ); - } else if ( a_reply.errCode ) { - if ( a_reply.errMsg ) { - logger.error(sendMessage.name, getCurrentLineNumber(), "Error - reply handler: " + a_reply.errMsg); - a_resp.status(500).send( a_reply.errMsg ); + frame.writeUInt32BE(msg_buf.length, 0); + frame.writeUInt8(msg._pid, 4); + frame.writeUInt8(msg._mid, 5); + frame.writeUInt16BE(ctx, 6); + + g_ctx[ctx] = function (a_reply) { + if (!a_reply) { + logger.error( + sendMessage.name, + getCurrentLineNumber(), + "Error - reply handler: empty reply", + ); + a_resp.status(500).send("Empty reply"); + } else if (a_reply.errCode) { + if (a_reply.errMsg) { + logger.error( + sendMessage.name, + getCurrentLineNumber(), + "Error - reply handler: " + a_reply.errMsg, + ); + a_resp.status(500).send(a_reply.errMsg); } else { - logger.error(sendMessage.name, getCurrentLineNumber(), "Error - reply handler: " + a_reply.errCode); - a_resp.status(500).send( "error code: " + a_reply.errCode ); + logger.error( + sendMessage.name, + getCurrentLineNumber(), + "Error - reply handler: " + a_reply.errCode, + ); + a_resp.status(500).send("error code: " + a_reply.errCode); } } else { - a_cb( a_reply ); + a_cb(a_reply); } }; var route_count = Buffer.alloc(4); - route_count.writeUInt32BE( 0, 0 ); - if ( msg_buf.length ) { + route_count.writeUInt32BE(0, 0); + if (msg_buf.length) { g_core_sock.send("BEGIN_DATAFED", zmq.ZMQ_SNDMORE); - g_core_sock.send(route_count ,zmq.ZMQ_SNDMORE); - g_core_sock.send(nullfr ,zmq.ZMQ_SNDMORE); + g_core_sock.send(route_count, zmq.ZMQ_SNDMORE); + g_core_sock.send(nullfr, zmq.ZMQ_SNDMORE); const corr_id = uuidv4(); - g_core_sock.send(corr_id ,zmq.ZMQ_SNDMORE); - g_core_sock.send("no_key" ,zmq.ZMQ_SNDMORE); - g_core_sock.send(client,zmq.ZMQ_SNDMORE); - g_core_sock.send(frame ,zmq.ZMQ_SNDMORE); + g_core_sock.send(corr_id, zmq.ZMQ_SNDMORE); + g_core_sock.send("no_key", zmq.ZMQ_SNDMORE); + g_core_sock.send(client, zmq.ZMQ_SNDMORE); + g_core_sock.send(frame, zmq.ZMQ_SNDMORE); g_core_sock.send(msg_buf); - logger.debug(sendMessage.name, getCurrentLineNumber(), "MsgType is: " + msg._msg_type + " Writing ctx to frame, " + ctx + " buffer size " + msg_buf.length, corr_id); + logger.debug( + sendMessage.name, + getCurrentLineNumber(), + "MsgType is: " + + msg._msg_type + + " Writing ctx to frame, " + + ctx + + " buffer size " + + msg_buf.length, + corr_id, + ); } else { g_core_sock.send("BEGIN_DATAFED", zmq.ZMQ_SNDMORE); - g_core_sock.send(route_count ,zmq.ZMQ_SNDMORE); - g_core_sock.send(nullfr ,zmq.ZMQ_SNDMORE); + g_core_sock.send(route_count, zmq.ZMQ_SNDMORE); + g_core_sock.send(nullfr, zmq.ZMQ_SNDMORE); const corr_id = uuidv4(); - g_core_sock.send(corr_id ,zmq.ZMQ_SNDMORE); - g_core_sock.send("no_key" ,zmq.ZMQ_SNDMORE); - g_core_sock.send(client ,zmq.ZMQ_SNDMORE); - g_core_sock.send(frame ,zmq.ZMQ_SNDMORE ); + g_core_sock.send(corr_id, zmq.ZMQ_SNDMORE); + g_core_sock.send("no_key", zmq.ZMQ_SNDMORE); + g_core_sock.send(client, zmq.ZMQ_SNDMORE); + g_core_sock.send(frame, zmq.ZMQ_SNDMORE); g_core_sock.send(nullfr); - logger.debug(sendMessage.name, getCurrentLineNumber(), "MsgType is: " + msg._msg_type + " Writing ctx to frame, " + ctx + " buffer size " + msg_buf.length, corr_id); - + logger.debug( + sendMessage.name, + getCurrentLineNumber(), + "MsgType is: " + + msg._msg_type + + " Writing ctx to frame, " + + ctx + + " buffer size " + + msg_buf.length, + corr_id, + ); } - }); } - -function sendMessageDirect( a_msg_name, a_client, a_msg_data, a_cb ) { +function sendMessageDirect(a_msg_name, a_client, a_msg_data, a_cb) { var msg = g_msg_by_name[a_msg_name]; - if ( !msg ) - throw "Invalid message type: " + a_msg_name; - - allocRequestContext( null, function( ctx ){ + if (!msg) throw "Invalid message type: " + a_msg_name; + allocRequestContext(null, function (ctx) { var msg_buf = msg.encode(a_msg_data).finish(); var frame = Buffer.alloc(8); // A protobuf message doesn't have to have a payload - frame.writeUInt32BE( msg_buf.length, 0 ); - frame.writeUInt8( msg._pid, 4 ); - frame.writeUInt8( msg._mid, 5 ); - frame.writeUInt16BE( ctx, 6 ); + frame.writeUInt32BE(msg_buf.length, 0); + frame.writeUInt8(msg._pid, 4); + frame.writeUInt8(msg._mid, 5); + frame.writeUInt16BE(ctx, 6); g_ctx[ctx] = a_cb; var route_count = Buffer.alloc(4); - route_count.writeUInt32BE( 0, 0 ); + route_count.writeUInt32BE(0, 0); - if ( msg_buf.length ) { + if (msg_buf.length) { // ZeroMQ socket g_core_sock - not Dale's code it is a library g_core_sock.send("BEGIN_DATAFED", zmq.ZMQ_SNDMORE); - g_core_sock.send(route_count ,zmq.ZMQ_SNDMORE); - g_core_sock.send(nullfr ,zmq.ZMQ_SNDMORE); + g_core_sock.send(route_count, zmq.ZMQ_SNDMORE); + g_core_sock.send(nullfr, zmq.ZMQ_SNDMORE); const corr_id = uuidv4(); - g_core_sock.send(corr_id ,zmq.ZMQ_SNDMORE); - g_core_sock.send("no_key" ,zmq.ZMQ_SNDMORE); - g_core_sock.send(a_client,zmq.ZMQ_SNDMORE); - g_core_sock.send(frame ,zmq.ZMQ_SNDMORE); + g_core_sock.send(corr_id, zmq.ZMQ_SNDMORE); + g_core_sock.send("no_key", zmq.ZMQ_SNDMORE); + g_core_sock.send(a_client, zmq.ZMQ_SNDMORE); + g_core_sock.send(frame, zmq.ZMQ_SNDMORE); g_core_sock.send(msg_buf); - logger.debug(sendMessageDirect.name, getCurrentLineNumber(), "MsgType is: " + msg._msg_type + " Direct Writing ctx to frame, " + ctx + " buffer size " + msg_buf.length, corr_id); + logger.debug( + sendMessageDirect.name, + getCurrentLineNumber(), + "MsgType is: " + + msg._msg_type + + " Direct Writing ctx to frame, " + + ctx + + " buffer size " + + msg_buf.length, + corr_id, + ); } else { g_core_sock.send("BEGIN_DATAFED", zmq.ZMQ_SNDMORE); - g_core_sock.send(route_count ,zmq.ZMQ_SNDMORE); - g_core_sock.send(nullfr ,zmq.ZMQ_SNDMORE); + g_core_sock.send(route_count, zmq.ZMQ_SNDMORE); + g_core_sock.send(nullfr, zmq.ZMQ_SNDMORE); const corr_id = uuidv4(); - g_core_sock.send(corr_id ,zmq.ZMQ_SNDMORE); - g_core_sock.send("no_key" ,zmq.ZMQ_SNDMORE); - g_core_sock.send(a_client,zmq.ZMQ_SNDMORE); - g_core_sock.send(frame,zmq.ZMQ_SNDMORE); + g_core_sock.send(corr_id, zmq.ZMQ_SNDMORE); + g_core_sock.send("no_key", zmq.ZMQ_SNDMORE); + g_core_sock.send(a_client, zmq.ZMQ_SNDMORE); + g_core_sock.send(frame, zmq.ZMQ_SNDMORE); g_core_sock.send(nullfr); - logger.debug(sendMessageDirect.name, getCurrentLineNumber(),"MsgType is: " + msg._msg_type + " Direct Writing ctx to frame, " + ctx + " buffer size " + msg_buf.length, corr_id); + logger.debug( + sendMessageDirect.name, + getCurrentLineNumber(), + "MsgType is: " + + msg._msg_type + + " Direct Writing ctx to frame, " + + ctx + + " buffer size " + + msg_buf.length, + corr_id, + ); } }); } -function processProtoFile( msg ){ +function processProtoFile(msg) { //var mlist = msg.parent.order; - var i, msg_list = []; - for ( i in msg.parent.nested ) - msg_list.push(msg.parent.nested[i]); + var i, + msg_list = []; + for (i in msg.parent.nested) msg_list.push(msg.parent.nested[i]); //msg_list.sort(); var pid = msg.values.ID; - for ( i = 1; i < msg_list.length; i++ ){ + for (i = 1; i < msg_list.length; i++) { msg = msg_list[i]; msg._pid = pid; - msg._mid = i-1; - msg._msg_type = (pid << 8) | (i-1); + msg._mid = i - 1; + msg._msg_type = (pid << 8) | (i - 1); - g_msg_by_id[ msg._msg_type ] = msg; - g_msg_by_name[ msg.name ] = msg; + g_msg_by_id[msg._msg_type] = msg; + g_msg_by_name[msg.name] = msg; } } -protobuf.load("Version.proto", function(err, root) { - if ( err ) - throw err; +protobuf.load("Version.proto", function (err, root) { + if (err) throw err; - var msg = root.lookupEnum( "Version" ); - if ( !msg ) - throw "Missing Version enum in Version.Anon proto file"; + var msg = root.lookupEnum("Version"); + if (!msg) throw "Missing Version enum in Version.Anon proto file"; - g_ver_release_year = msg.values.DATAFED_RELEASE_YEAR - g_ver_release_month = msg.values.DATAFED_RELEASE_MONTH - g_ver_release_day = msg.values.DATAFED_RELEASE_DAY - g_ver_release_hour = msg.values.DATAFED_RELEASE_HOUR - g_ver_release_minute = msg.values.DATAFED_RELEASE_MINUTE + g_ver_release_year = msg.values.DATAFED_RELEASE_YEAR; + g_ver_release_month = msg.values.DATAFED_RELEASE_MONTH; + g_ver_release_day = msg.values.DATAFED_RELEASE_DAY; + g_ver_release_hour = msg.values.DATAFED_RELEASE_HOUR; + g_ver_release_minute = msg.values.DATAFED_RELEASE_MINUTE; - g_version = g_ver_release_year + "." + g_ver_release_month + "." + g_ver_release_day + "." + g_ver_release_hour + "." + g_ver_release_minute; + g_version = + g_ver_release_year + + "." + + g_ver_release_month + + "." + + g_ver_release_day + + "." + + g_ver_release_hour + + "." + + g_ver_release_minute; - logger.info("protobuf.load", getCurrentLineNumber(),'Running Version: ' + g_version); - if ( --g_ready_start == 0 ) - startServer(); + logger.info("protobuf.load", getCurrentLineNumber(), "Running Version: " + g_version); + if (--g_ready_start == 0) startServer(); }); -protobuf.load("SDMS_Anon.proto", function(err, root) { - if ( err ) - throw err; +protobuf.load("SDMS_Anon.proto", function (err, root) { + if (err) throw err; - var msg = root.lookupEnum( "SDMS.Anon.Protocol" ); - if ( !msg ) - throw "Missing Protocol enum in SDMS.Anon proto file"; + var msg = root.lookupEnum("SDMS.Anon.Protocol"); + if (!msg) throw "Missing Protocol enum in SDMS.Anon proto file"; - processProtoFile( msg ); - if ( --g_ready_start == 0 ) - startServer(); + processProtoFile(msg); + if (--g_ready_start == 0) startServer(); }); -protobuf.load("SDMS_Auth.proto", function(err, root) { - if ( err ) - throw err; +protobuf.load("SDMS_Auth.proto", function (err, root) { + if (err) throw err; - var msg = root.lookupEnum( "SDMS.Auth.Protocol" ); - if ( !msg ) - throw "Missing Protocol enum in SDMS.Auth proto file"; + var msg = root.lookupEnum("SDMS.Auth.Protocol"); + if (!msg) throw "Missing Protocol enum in SDMS.Auth proto file"; - processProtoFile( msg ); - if ( --g_ready_start == 0 ) - startServer(); + processProtoFile(msg); + if (--g_ready_start == 0) startServer(); }); -process.on('unhandledRejection', (reason, p) => { - logger.error("process.on", getCurrentLineNumber(), 'Error - unhandled rejection at: Promise: ' + p + ' reason: ' + reason ); +process.on("unhandledRejection", (reason, p) => { + logger.error( + "process.on", + getCurrentLineNumber(), + "Error - unhandled rejection at: Promise: " + p + " reason: " + reason, + ); }); -// This is the reply part +// This is the reply part // on - method is a way of subscribing to events -g_core_sock.on('message', function( delim, header, route_count, delim2, correlation_id, key, id, frame, msg_buf ) { - frame.readUInt32BE( 0 ); - var mtype = (frame.readUInt8( 4 ) << 8 ) | frame.readUInt8( 5 ); - var ctx = frame.readUInt16BE( 6 ); - - var msg_class = g_msg_by_id[mtype]; - var msg; - - if ( msg_class ) { - // Only try to decode if there is a payload - if ( msg_buf && msg_buf.length ) { - try { - // This is unserializing the protocol message - msg = msg_class.decode( msg_buf ); - if ( !msg ) { - logger.error("g_core_sock.on", getCurrentLineNumber(), "ERROR: msg decode failed: no reason, correlation_id: " + correlation_id ); +g_core_sock.on( + "message", + function (delim, header, route_count, delim2, correlation_id, key, id, frame, msg_buf) { + frame.readUInt32BE(0); + var mtype = (frame.readUInt8(4) << 8) | frame.readUInt8(5); + var ctx = frame.readUInt16BE(6); + + var msg_class = g_msg_by_id[mtype]; + var msg; + + if (msg_class) { + // Only try to decode if there is a payload + if (msg_buf && msg_buf.length) { + try { + // This is unserializing the protocol message + msg = msg_class.decode(msg_buf); + if (!msg) { + logger.error( + "g_core_sock.on", + getCurrentLineNumber(), + "ERROR: msg decode failed: no reason, correlation_id: " + + correlation_id, + ); + } + } catch (err) { + logger.error( + "g_core_sock.on", + getCurrentLineNumber(), + "ERROR: msg decode failed: " + err + " correlation_id: " + correlation_id, + ); } - } catch ( err ) { - logger.error("g_core_sock.on", getCurrentLineNumber(), "ERROR: msg decode failed: " + err + " correlation_id: " + correlation_id ); + } else { + msg = msg_class; } } else { - msg = msg_class; + logger.error( + "g_core_sock.on", + getCurrentLineNumber(), + "ERROR: unknown msg type: " + mtype + " correlation_id: " + correlation_id, + ); } - } else { - logger.error("g_core_sock.on", getCurrentLineNumber(), "ERROR: unknown msg type: " + mtype + " correlation_id: " + correlation_id ); - } - var f = g_ctx[ctx]; - if ( f ) { - g_ctx[ctx] = null; - logger.info("g_core_sock.on", getCurrentLineNumber(),"freed ctx: " + ctx + " for msg: " + msg_class.name, correlation_id); - g_ctx_next = ctx; - f( msg ); - } else { - g_ctx[ctx] = null; - logger.error("g_core_sock.on", getCurrentLineNumber(), "ERROR: no callback found for ctxt: " + ctx + " - msg type: " + mtype + ", name: " + msg_class.name + " correlation_id: " + correlation_id ); - } -}); + var f = g_ctx[ctx]; + if (f) { + g_ctx[ctx] = null; + logger.info( + "g_core_sock.on", + getCurrentLineNumber(), + "freed ctx: " + ctx + " for msg: " + msg_class.name, + correlation_id, + ); + g_ctx_next = ctx; + f(msg); + } else { + g_ctx[ctx] = null; + logger.error( + "g_core_sock.on", + getCurrentLineNumber(), + "ERROR: no callback found for ctxt: " + + ctx + + " - msg type: " + + mtype + + ", name: " + + msg_class.name + + " correlation_id: " + + correlation_id, + ); + } + }, +); -function loadSettings(){ +function loadSettings() { g_host = "datafed.ornl.gov"; g_port = 443; g_tls = true; - g_server_key_file = '/opt/datafed/datafed-web-key.pem'; - g_server_cert_file = '/opt/datafed/datafed-web-cert.pem'; - g_core_serv_addr = 'tcp://datafed.ornl.gov:7513'; + g_server_key_file = "/opt/datafed/datafed-web-key.pem"; + g_server_cert_file = "/opt/datafed/datafed-web-cert.pem"; + g_core_serv_addr = "tcp://datafed.ornl.gov:7513"; g_test = false; - logger.info(loadSettings.name, getCurrentLineNumber(), "Reading configuration from file: " + process.argv[2] ); + logger.info( + loadSettings.name, + getCurrentLineNumber(), + "Reading configuration from file: " + process.argv[2], + ); - try{ - var config = ini.parse(fs.readFileSync(process.argv[2],'utf-8')); - - if ( config.server ){ + try { + var config = ini.parse(fs.readFileSync(process.argv[2], "utf-8")); + + if (config.server) { g_host = config.server.host || g_host; g_port = config.server.port || g_port; - if ( config.server.tls == "0" || config.server.tls == "false" ){ + if (config.server.tls == "0" || config.server.tls == "false") { g_tls = false; } g_extern_url = config.server.extern_url; - if ( g_tls ){ + if (g_tls) { g_server_key_file = config.server.key_file || g_server_key_file; g_server_cert_file = config.server.cert_file || g_server_cert_file; g_server_chain_file = config.server.chain_file; @@ -1812,37 +2393,41 @@ function loadSettings(){ g_system_secret = config.server.system_secret; g_session_secret = config.server.session_secret; g_test = config.server.test || g_test; - } - if ( config.oauth ){ + if (config.oauth) { g_client_id = config.oauth.client_id || g_client_id; g_client_secret = config.oauth.client_secret || g_client_secret; } - if ( config.core ){ + if (config.core) { g_core_serv_addr = config.core.server_address || g_core_serv_addr; } - if ( !g_extern_url ){ - g_extern_url = "http"+(g_tls?'s':'')+"://" + g_host + ":" + g_port; + if (!g_extern_url) { + g_extern_url = "http" + (g_tls ? "s" : "") + "://" + g_host + ":" + g_port; } - if ( config.operations ){ - g_google_analytics = { enableGoogleAnalytics: config.operations.google_analytics_tag !== '', googleAnalyticsTag: config.operations.google_analytics_tag }; + if (config.operations) { + g_google_analytics = { + enableGoogleAnalytics: config.operations.google_analytics_tag !== "", + googleAnalyticsTag: config.operations.google_analytics_tag, + }; } - }catch( e ){ - logger.error(loadSettings.name, getCurrentLineNumber(), "Could not open/parse configuration file: " + process.argv[2] ); - logger.error(loadSettings.name, getCurrentLineNumber(), e.message ); + } catch (e) { + logger.error( + loadSettings.name, + getCurrentLineNumber(), + "Could not open/parse configuration file: " + process.argv[2], + ); + logger.error(loadSettings.name, getCurrentLineNumber(), e.message); throw e; } - if ( !g_system_secret ){ + if (!g_system_secret) { throw "Server system secret not set."; } - if ( !g_session_secret ){ + if (!g_session_secret) { throw "Server session secret not set."; } } - -if ( --g_ready_start == 0 ) - startServer(); +if (--g_ready_start == 0) startServer(); diff --git a/web/docker/Dockerfile b/web/docker/Dockerfile index 7e699672f..6449f28da 100644 --- a/web/docker/Dockerfile +++ b/web/docker/Dockerfile @@ -48,6 +48,8 @@ RUN ${DATAFED_DEPENDENCIES_INSTALL_PATH}/bin/cmake --build build RUN ${DATAFED_DEPENDENCIES_INSTALL_PATH}/bin/cmake --build build --target install # Only part of the final install can be done here +ENTRYPOINT ["/opt/datafed/dependencies/bin/cmake", "--build", "build", "--target", "test"] + FROM ${RUNTIME} AS ws SHELL ["/bin/bash", "-c"] @@ -63,7 +65,7 @@ ENV DATAFED_DIR="$DATAFED_DIR" ENV BUILD_DIR="$BUILD_DIR" ENV DATAFED_DEFAULT_LOG_PATH="$DATAFED_INSTALL_PATH/logs" -RUN apt install -y python3 make g++ +RUN apt install -y make g++ WORKDIR ${DATAFED_DIR} @@ -86,4 +88,5 @@ WORKDIR ${BUILD_DIR} USER root -ENTRYPOINT ["/datafed/source/web/docker/entrypoint.sh", "/datafed/source/web/datafed-ws.js", "/datafed/source/config/datafed-ws.cfg" ] +ENTRYPOINT ["/datafed/source/web/docker/entrypoint.sh"] +CMD ["/datafed/source/web/datafed-ws.js", "/datafed/source/config/datafed-ws.cfg"] diff --git a/web/package.json.in b/web/package.json.in index b065848be..ee361824c 100644 --- a/web/package.json.in +++ b/web/package.json.in @@ -18,7 +18,7 @@ "sanitize-html": "^2.11.0" }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "mocha test/**/*.test.js" }, "repository": { "type": "git", @@ -34,5 +34,13 @@ "bugs": { "url": "https://github.com/ORNL/DataFed/issues" }, - "homepage": "https://github.com/ORNL/DataFed#readme" + "homepage": "https://github.com/ORNL/DataFed#readme", + "devDependencies": { + "chai": "^4", + "esm": "^3.2.25", + "mocha": "^10.8.2", + "pug": "^3.0.3", + "sinon": "17.0.0" + }, + "type": "module" } diff --git a/web/services/auth/ConsentHandler.js b/web/services/auth/ConsentHandler.js new file mode 100644 index 000000000..9cee4b3ae --- /dev/null +++ b/web/services/auth/ConsentHandler.js @@ -0,0 +1,58 @@ +import { AUTH_URL } from "./constants.js"; + +/** + * Basic implementation of `get_authorize_url` from the Globus SDK. + * + * This function generates the authorization URL that a user can follow to provide + * authorization and consent via Globus Auth. + * @param {string} client_id - The client ID of the application requesting authorization. + * @param {string} redirect_uri - The URI to redirect to after authorization. + * @param {boolean} [refresh_tokens=false] - Request refresh tokens in addition to access tokens. + * @param {Array} [requested_scopes=[]] - The scopes on the token(s) being requested. + * In the case of accessing a mapped collection, this should include the mapped + * collection's UUID, such as: `https://auth.globus.org/scopes/YOUR-UUID-HERE/data_access`. + * @param {object} [query_params={}] - Additional parameters to be included in the authorization URL. + * @param {string} [state="_default"] - Allows the application to pass information back to itself. + * + * @returns {string} The URL a user can follow to provide authorization and consent via Globus. + */ +export const generateConsentURL = ( + client_id, + redirect_uri, + refresh_tokens, + requested_scopes, + query_params, + state, +) => { + const scopes = requested_scopes || ["openid", "profile", "email", "urn:globus:auth:scope:transfer.api.globus.org:all"]; + + if (refresh_tokens) { + scopes.push("offline_access"); + } + + /* NOTE: using URLSearchParams changes encoding of " " to "+" which Globus accepts, despite saying otherwise + https://docs.globus.org/api/auth/developer-guide/#obtaining-authorization + */ + // TODO: consider moving back to custom encoding in anticipation that Globus will no longer accept a different encoding scheme + const params = new URLSearchParams({ + client_id, + redirect_uri, + scope: scopes.join(" "), // Scopes need to be separated by a space + state, + response_type: "code", + access_type: refresh_tokens === true ? "offline" : "online", + prompt: "login", + }); + + if (query_params) { + Object.entries(query_params).forEach(([key, value]) => { + if (value) { + // short-circuit on empty param values or if param already defined, + // TODO: are there cases where we may want empty params? + params.set(key, value); + } + }); + } + + return `${AUTH_URL}/v2/oauth2/authorize?${params.toString()}`; +}; diff --git a/web/services/auth/TokenHandler.js b/web/services/auth/TokenHandler.js new file mode 100644 index 000000000..ac678be3e --- /dev/null +++ b/web/services/auth/TokenHandler.js @@ -0,0 +1,189 @@ +import { AUTH_PREFIX } from "./constants.js"; + +// TODO: convert to protobufjs read of enum +export const AccessTokenType = Object.freeze({ + GENERIC: 1, + GLOBUS: 2, + GLOBUS_AUTH: 3, + GLOBUS_TRANSFER: 4, + GLOBUS_DEFAULT: 5, + ACCESS_SENTINEL: 255, +}); + +/** Handler for custom token logic + * + */ +export default class OAuthTokenHandler { + #client_token; + #other_tokens_exist = false; + #token_type; + + /** + * @typedef {object} OAuthTransferToken + * @property {string} access_token - Access token + * @property {string} [refresh_token] - Refresh token + * @property {number} expires_in - Integer time in ms until expiration + * @property {string} scope - Scope of token + */ + #oauth_transfer_token_schema = { + access_token: (input_string) => { + if (typeof input_string !== "string") { + throw new Error("Missing required parameter 'access_token': string"); + } + }, + refresh_token: (input_string) => { + if (typeof input_string !== "string") { + throw new Error("Missing required parameter 'refresh_token': string"); + } + }, + expires_in: (input_number) => { + if (typeof input_number !== "number") { + throw new Error("Missing required parameter 'expires_in': number"); + } + }, + scope: (input_string) => { + if (typeof input_string !== "string") { + throw new Error("Missing required parameter 'scope': string"); + } + }, + }; + + /** + * @param {object} client_token - OAuth token object from which to extract relevant information + * @param {OAuthTransferToken} client_token.data - Raw data object for OAuth token + * @param {Array} client_token.data.other_tokens - Other OAuth tokens passed with parent, can be empty + * @param {string} client_token.data.resource_server - Resource server on which OAuth token functions + */ + constructor(client_token) { + this.#client_token = Object.freeze(client_token); + this.#other_tokens_exist = client_token.data.other_tokens.length > 0; + this.#token_type = this.#resolveTokenType(); + this.#validateToken(); + } + + /** + * Validates client token is supported and has required properties + */ + #validateToken() { + // TODO: build capability for currently unsupported token types + switch (this.#token_type) { + case AccessTokenType.GENERIC: { + throw new Error("Unsupported token type: GENERIC"); + } + case AccessTokenType.GLOBUS: { + throw new Error("Unsupported token type: GLOBUS"); + } + case AccessTokenType.GLOBUS_AUTH: { + throw new Error("Unsupported token type: GLOBUS_AUTH"); + } + case AccessTokenType.GLOBUS_TRANSFER: { + const transfer_token = this.#client_token.data; + Object.keys(this.#oauth_transfer_token_schema).map((key) => { + // Inspired by: https://stackoverflow.com/a/38616988 + this.#oauth_transfer_token_schema[key](transfer_token[key]); + }); + break; + } + case AccessTokenType.GLOBUS_DEFAULT: { + if (!this.#other_tokens_exist) { + throw new Error( + "Default token handling requires additional transfer tokens in other_tokens field", + ); + } + const first_token = this.#client_token.data.other_tokens[0]; + Object.keys(this.#oauth_transfer_token_schema).map((key) => { + // Inspired by: https://stackoverflow.com/a/38616988 + this.#oauth_transfer_token_schema[key](first_token[key]); + }); + break; + } + case AccessTokenType.ACCESS_SENTINEL: { + throw new Error("Invalid state"); + } + } + } + + /** Resolves token type based on a provided resource server + * + * @returns {AccessTokenType | number} - Access token type + */ + #resolveTokenType() { + const resource_server = this.#client_token.data.resource_server; + switch ( + resource_server // TODO: exhaustive coverage of types + ) { + case AUTH_PREFIX: { + if (this.#other_tokens_exist) { + return AccessTokenType.GLOBUS_DEFAULT; + } + return AccessTokenType.GLOBUS_AUTH; + } + case "transfer.api.globus.org": { + return AccessTokenType.GLOBUS_TRANSFER; + } + default: { + return AccessTokenType.GENERIC; + } + } + } + + /** Allows read access to resolved token type + * + * @returns {AccessTokenType | number} - Access token type + */ + getTokenType() { + return this.#token_type; + } + + /** OptionalData object + * @typedef {object} OptionalData + * @property {AccessTokenType | number} type - The type of token being stored + * @property {string} [other] - Additional constructed data to provide more context for backend + */ + /** Constructs optional token data for SetAccessToken based on token type + * + * @param {object} token_context - Object with arbitrary keys for context when building optional data + * @param {string} [token_context.collection_id] - Globus Collection ID to be associated with token + * @param {string} [token_context.scope] - Scope(s) to be associated with token + * @returns {OptionalData} - Optional data construct with appropriate values + * @throws Error - When a required collection ID cannot be found in the session + */ + constructOptionalData(token_context) { + const token_type = this.#token_type; + let optional_data = { type: token_type }; + switch (token_type) { + case AccessTokenType.GLOBUS_AUTH: { + throw new Error("Invalid state - Globus auth tokens not currently supported"); // TODO: build capability + } + case AccessTokenType.GLOBUS_TRANSFER: { + const { collection_id, scope } = token_context; + if (!collection_id) { + throw new Error("Transfer token received without collection context"); + } + if (!scope) { + throw new Error("Transfer token received without scope context"); + } + optional_data.other = collection_id + "|" + scope; // Database API expects format `|` + break; + } + case AccessTokenType.GLOBUS_DEFAULT: { + break; + } + default: { + // TODO: exhaustive coverage of types + throw new Error("Invalid state - Unsupported token type detected."); + } + } + + return optional_data; + } + + /** + * @returns {OAuthTransferToken} - Appropriate OAuth transfer token depending upon token configuration + */ + extractTransferToken() { + return this.#token_type === AccessTokenType.GLOBUS_DEFAULT && this.#other_tokens_exist + ? this.#client_token.data.other_tokens[0] + : this.#client_token.data; // Auth tokens in DEFAULT come with an additional transfer token, but transfer tokens (which come with consent collections) will come alone (for now) + } +} diff --git a/web/services/auth/constants.js b/web/services/auth/constants.js new file mode 100644 index 000000000..1b7f76816 --- /dev/null +++ b/web/services/auth/constants.js @@ -0,0 +1,4 @@ +const AUTH_PREFIX = "auth.globus.org"; +const AUTH_URL = `https://${AUTH_PREFIX}`; + +export { AUTH_URL, AUTH_PREFIX }; diff --git a/web/static/ace/ace.js b/web/static/ace/ace.js index cb5c94415..b21598256 100644 --- a/web/static/ace/ace.js +++ b/web/static/ace/ace.js @@ -1,18 +1,17305 @@ -(function(){function o(n){var i=e;n&&(e[n]||(e[n]={}),i=e[n]);if(!i.define||!i.define.packaged)t.original=i.define,i.define=t,i.define.packaged=!0;if(!i.require||!i.require.packaged)r.original=i.require,i.require=r,i.require.packaged=!0}var ACE_NAMESPACE="",e=function(){return this}();!e&&typeof window!="undefined"&&(e=window);if(!ACE_NAMESPACE&&typeof requirejs!="undefined")return;var t=function(e,n,r){if(typeof e!="string"){t.original?t.original.apply(this,arguments):(console.error("dropping module because define wasn't a string."),console.trace());return}arguments.length==2&&(r=n),t.modules[e]||(t.payloads[e]=r,t.modules[e]=null)};t.modules={},t.payloads={};var n=function(e,t,n){if(typeof t=="string"){var i=s(e,t);if(i!=undefined)return n&&n(),i}else if(Object.prototype.toString.call(t)==="[object Array]"){var o=[];for(var u=0,a=t.length;u1&&u(t,"")>-1&&(a=RegExp(this.source,r.replace.call(o(this),"g","")),r.replace.call(e.slice(t.index),a,function(){for(var e=1;et.index&&this.lastIndex--}return t},s||(RegExp.prototype.test=function(e){var t=r.exec.call(this,e);return t&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--,!!t})}),define("ace/lib/es5-shim",["require","exports","module"],function(e,t,n){function r(){}function w(e){try{return Object.defineProperty(e,"sentinel",{}),"sentinel"in e}catch(t){}}function H(e){return e=+e,e!==e?e=0:e!==0&&e!==1/0&&e!==-1/0&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e}function B(e){var t=typeof e;return e===null||t==="undefined"||t==="boolean"||t==="number"||t==="string"}function j(e){var t,n,r;if(B(e))return e;n=e.valueOf;if(typeof n=="function"){t=n.call(e);if(B(t))return t}r=e.toString;if(typeof r=="function"){t=r.call(e);if(B(t))return t}throw new TypeError}Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!="function")throw new TypeError("Function.prototype.bind called on incompatible "+n);var i=u.call(arguments,1),s=function(){if(this instanceof s){var e=n.apply(this,i.concat(u.call(arguments)));return Object(e)===e?e:this}return n.apply(t,i.concat(u.call(arguments)))};return n.prototype&&(r.prototype=n.prototype,s.prototype=new r,r.prototype=null),s});var i=Function.prototype.call,s=Array.prototype,o=Object.prototype,u=s.slice,a=i.bind(o.toString),f=i.bind(o.hasOwnProperty),l,c,h,p,d;if(d=f(o,"__defineGetter__"))l=i.bind(o.__defineGetter__),c=i.bind(o.__defineSetter__),h=i.bind(o.__lookupGetter__),p=i.bind(o.__lookupSetter__);if([1,2].splice(0).length!=2)if(!function(){function e(e){var t=new Array(e+2);return t[0]=t[1]=0,t}var t=[],n;t.splice.apply(t,e(20)),t.splice.apply(t,e(26)),n=t.length,t.splice(5,0,"XXX"),n+1==t.length;if(n+1==t.length)return!0}())Array.prototype.splice=function(e,t){var n=this.length;e>0?e>n&&(e=n):e==void 0?e=0:e<0&&(e=Math.max(n+e,0)),e+ta)for(h=l;h--;)this[f+h]=this[a+h];if(s&&e===c)this.length=c,this.push.apply(this,i);else{this.length=c+s;for(h=0;h>>0;if(a(t)!="[object Function]")throw new TypeError;while(++s>>0,s=Array(i),o=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var u=0;u>>0,s=[],o,u=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var f=0;f>>0,s=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var o=0;o>>0,s=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var o=0;o>>0;if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");if(!i&&arguments.length==1)throw new TypeError("reduce of empty array with no initial value");var s=0,o;if(arguments.length>=2)o=arguments[1];else do{if(s in r){o=r[s++];break}if(++s>=i)throw new TypeError("reduce of empty array with no initial value")}while(!0);for(;s>>0;if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");if(!i&&arguments.length==1)throw new TypeError("reduceRight of empty array with no initial value");var s,o=i-1;if(arguments.length>=2)s=arguments[1];else do{if(o in r){s=r[o--];break}if(--o<0)throw new TypeError("reduceRight of empty array with no initial value")}while(!0);do o in this&&(s=t.call(void 0,s,r[o],o,n));while(o--);return s});if(!Array.prototype.indexOf||[0,1].indexOf(1,2)!=-1)Array.prototype.indexOf=function(t){var n=g&&a(this)=="[object String]"?this.split(""):F(this),r=n.length>>>0;if(!r)return-1;var i=0;arguments.length>1&&(i=H(arguments[1])),i=i>=0?i:Math.max(0,r+i);for(;i>>0;if(!r)return-1;var i=r-1;arguments.length>1&&(i=Math.min(i,H(arguments[1]))),i=i>=0?i:r-Math.abs(i);for(;i>=0;i--)if(i in n&&t===n[i])return i;return-1};Object.getPrototypeOf||(Object.getPrototypeOf=function(t){return t.__proto__||(t.constructor?t.constructor.prototype:o)});if(!Object.getOwnPropertyDescriptor){var y="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(t,n){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(y+t);if(!f(t,n))return;var r,i,s;r={enumerable:!0,configurable:!0};if(d){var u=t.__proto__;t.__proto__=o;var i=h(t,n),s=p(t,n);t.__proto__=u;if(i||s)return i&&(r.get=i),s&&(r.set=s),r}return r.value=t[n],r}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(t){return Object.keys(t)});if(!Object.create){var b;Object.prototype.__proto__===null?b=function(){return{__proto__:null}}:b=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(t,n){var r;if(t===null)r=b();else{if(typeof t!="object")throw new TypeError("typeof prototype["+typeof t+"] != 'object'");var i=function(){};i.prototype=t,r=new i,r.__proto__=t}return n!==void 0&&Object.defineProperties(r,n),r}}if(Object.defineProperty){var E=w({}),S=typeof document=="undefined"||w(document.createElement("div"));if(!E||!S)var x=Object.defineProperty}if(!Object.defineProperty||x){var T="Property description must be an object: ",N="Object.defineProperty called on non-object: ",C="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(t,n,r){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(N+t);if(typeof r!="object"&&typeof r!="function"||r===null)throw new TypeError(T+r);if(x)try{return x.call(Object,t,n,r)}catch(i){}if(f(r,"value"))if(d&&(h(t,n)||p(t,n))){var s=t.__proto__;t.__proto__=o,delete t[n],t[n]=r.value,t.__proto__=s}else t[n]=r.value;else{if(!d)throw new TypeError(C);f(r,"get")&&l(t,n,r.get),f(r,"set")&&c(t,n,r.set)}return t}}Object.defineProperties||(Object.defineProperties=function(t,n){for(var r in n)f(n,r)&&Object.defineProperty(t,r,n[r]);return t}),Object.seal||(Object.seal=function(t){return t}),Object.freeze||(Object.freeze=function(t){return t});try{Object.freeze(function(){})}catch(k){Object.freeze=function(t){return function(n){return typeof n=="function"?n:t(n)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(t){return t}),Object.isSealed||(Object.isSealed=function(t){return!1}),Object.isFrozen||(Object.isFrozen=function(t){return!1}),Object.isExtensible||(Object.isExtensible=function(t){if(Object(t)===t)throw new TypeError;var n="";while(f(t,n))n+="?";t[n]=!0;var r=f(t,n);return delete t[n],r});if(!Object.keys){var L=!0,A=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],O=A.length;for(var M in{toString:null})L=!1;Object.keys=function I(e){if(typeof e!="object"&&typeof e!="function"||e===null)throw new TypeError("Object.keys called on a non-object");var I=[];for(var t in e)f(e,t)&&I.push(t);if(L)for(var n=0,r=O;n=0?parseFloat((i.match(/(?:MSIE |Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]):parseFloat((i.match(/(?:Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]),t.isOldIE=t.isIE&&t.isIE<9,t.isGecko=t.isMozilla=i.match(/ Gecko\/\d+/),t.isOpera=window.opera&&Object.prototype.toString.call(window.opera)=="[object Opera]",t.isWebKit=parseFloat(i.split("WebKit/")[1])||undefined,t.isChrome=parseFloat(i.split(" Chrome/")[1])||undefined,t.isEdge=parseFloat(i.split(" Edge/")[1])||undefined,t.isAIR=i.indexOf("AdobeAIR")>=0,t.isIPad=i.indexOf("iPad")>=0,t.isAndroid=i.indexOf("Android")>=0,t.isChromeOS=i.indexOf(" CrOS ")>=0,t.isIOS=/iPad|iPhone|iPod/.test(i)&&!window.MSStream,t.isIOS&&(t.isMac=!0),t.isMobile=t.isIPad||t.isAndroid}),define("ace/lib/dom",["require","exports","module","ace/lib/useragent"],function(e,t,n){"use strict";var r=e("./useragent"),i="http://www.w3.org/1999/xhtml";t.buildDom=function o(e,t,n){if(typeof e=="string"&&e){var r=document.createTextNode(e);return t&&t.appendChild(r),r}if(!Array.isArray(e))return e;if(typeof e[0]!="string"||!e[0]){var i=[];for(var s=0;s=1.5:!0;if(typeof document!="undefined"){var s=document.createElement("div");t.HI_DPI&&s.style.transform!==undefined&&(t.HAS_CSS_TRANSFORMS=!0),!r.isEdge&&typeof s.style.animationName!="undefined"&&(t.HAS_CSS_ANIMATION=!0),s=null}t.HAS_CSS_TRANSFORMS?t.translate=function(e,t,n){e.style.transform="translate("+Math.round(t)+"px, "+Math.round(n)+"px)"}:t.translate=function(e,t,n){e.style.top=Math.round(n)+"px",e.style.left=Math.round(t)+"px"}}),define("ace/lib/oop",["require","exports","module"],function(e,t,n){"use strict";t.inherits=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})},t.mixin=function(e,t){for(var n in t)e[n]=t[n];return e},t.implement=function(e,n){t.mixin(e,n)}}),define("ace/lib/keys",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop"],function(e,t,n){"use strict";e("./fixoldbrowsers");var r=e("./oop"),i=function(){var e={MODIFIER_KEYS:{16:"Shift",17:"Ctrl",18:"Alt",224:"Meta"},KEY_MODS:{ctrl:1,alt:2,option:2,shift:4,"super":8,meta:8,command:8,cmd:8},FUNCTION_KEYS:{8:"Backspace",9:"Tab",13:"Return",19:"Pause",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"Print",45:"Insert",46:"Delete",96:"Numpad0",97:"Numpad1",98:"Numpad2",99:"Numpad3",100:"Numpad4",101:"Numpad5",102:"Numpad6",103:"Numpad7",104:"Numpad8",105:"Numpad9","-13":"NumpadEnter",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"Numlock",145:"Scrolllock"},PRINTABLE_KEYS:{32:" ",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",61:"=",65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x",89:"y",90:"z",107:"+",109:"-",110:".",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",111:"/",106:"*"}},t,n;for(n in e.FUNCTION_KEYS)t=e.FUNCTION_KEYS[n].toLowerCase(),e[t]=parseInt(n,10);for(n in e.PRINTABLE_KEYS)t=e.PRINTABLE_KEYS[n].toLowerCase(),e[t]=parseInt(n,10);return r.mixin(e,e.MODIFIER_KEYS),r.mixin(e,e.PRINTABLE_KEYS),r.mixin(e,e.FUNCTION_KEYS),e.enter=e["return"],e.escape=e.esc,e.del=e["delete"],e[173]="-",function(){var t=["cmd","ctrl","alt","shift"];for(var n=Math.pow(2,t.length);n--;)e.KEY_MODS[n]=t.filter(function(t){return n&e.KEY_MODS[t]}).join("-")+"-"}(),e.KEY_MODS[0]="",e.KEY_MODS[-1]="input-",e}();r.mixin(t,i),t.keyCodeToString=function(e){var t=i[e];return typeof t!="string"&&(t=String.fromCharCode(e)),t.toLowerCase()}}),define("ace/lib/event",["require","exports","module","ace/lib/keys","ace/lib/useragent"],function(e,t,n){"use strict";function a(e,t,n){var a=u(t);if(!i.isMac&&s){t.getModifierState&&(t.getModifierState("OS")||t.getModifierState("Win"))&&(a|=8);if(s.altGr){if((3&a)==3)return;s.altGr=0}if(n===18||n===17){var f="location"in t?t.location:t.keyLocation;if(n===17&&f===1)s[n]==1&&(o=t.timeStamp);else if(n===18&&a===3&&f===2){var l=t.timeStamp-o;l<50&&(s.altGr=!0)}}}n in r.MODIFIER_KEYS&&(n=-1),a&8&&n>=91&&n<=93&&(n=-1);if(!a&&n===13){var f="location"in t?t.location:t.keyLocation;if(f===3){e(t,a,-n);if(t.defaultPrevented)return}}if(i.isChromeOS&&a&8){e(t,a,n);if(t.defaultPrevented)return;a&=-9}return!!a||n in r.FUNCTION_KEYS||n in r.PRINTABLE_KEYS?e(t,a,n):!1}function f(){s=Object.create(null)}var r=e("./keys"),i=e("./useragent"),s=null,o=0;t.addListener=function(e,t,n){if(e.addEventListener)return e.addEventListener(t,n,!1);if(e.attachEvent){var r=function(){n.call(e,window.event)};n._wrapper=r,e.attachEvent("on"+t,r)}},t.removeListener=function(e,t,n){if(e.removeEventListener)return e.removeEventListener(t,n,!1);e.detachEvent&&e.detachEvent("on"+t,n._wrapper||n)},t.stopEvent=function(e){return t.stopPropagation(e),t.preventDefault(e),!1},t.stopPropagation=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},t.preventDefault=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},t.getButton=function(e){return e.type=="dblclick"?0:e.type=="contextmenu"||i.isMac&&e.ctrlKey&&!e.altKey&&!e.shiftKey?2:e.preventDefault?e.button:{1:0,2:2,4:1}[e.button]},t.capture=function(e,n,r){function i(e){n&&n(e),r&&r(e),t.removeListener(document,"mousemove",n,!0),t.removeListener(document,"mouseup",i,!0),t.removeListener(document,"dragstart",i,!0)}return t.addListener(document,"mousemove",n,!0),t.addListener(document,"mouseup",i,!0),t.addListener(document,"dragstart",i,!0),i},t.addTouchMoveListener=function(e,n){var r,i;t.addListener(e,"touchstart",function(e){var t=e.touches,n=t[0];r=n.clientX,i=n.clientY}),t.addListener(e,"touchmove",function(e){var t=e.touches;if(t.length>1)return;var s=t[0];e.wheelX=r-s.clientX,e.wheelY=i-s.clientY,r=s.clientX,i=s.clientY,n(e)})},t.addMouseWheelListener=function(e,n){"onmousewheel"in e?t.addListener(e,"mousewheel",function(e){var t=8;e.wheelDeltaX!==undefined?(e.wheelX=-e.wheelDeltaX/t,e.wheelY=-e.wheelDeltaY/t):(e.wheelX=0,e.wheelY=-e.wheelDelta/t),n(e)}):"onwheel"in e?t.addListener(e,"wheel",function(e){var t=.35;switch(e.deltaMode){case e.DOM_DELTA_PIXEL:e.wheelX=e.deltaX*t||0,e.wheelY=e.deltaY*t||0;break;case e.DOM_DELTA_LINE:case e.DOM_DELTA_PAGE:e.wheelX=(e.deltaX||0)*5,e.wheelY=(e.deltaY||0)*5}n(e)}):t.addListener(e,"DOMMouseScroll",function(e){e.axis&&e.axis==e.HORIZONTAL_AXIS?(e.wheelX=(e.detail||0)*5,e.wheelY=0):(e.wheelX=0,e.wheelY=(e.detail||0)*5),n(e)})},t.addMultiMouseDownListener=function(e,n,r,s){function c(e){t.getButton(e)!==0?o=0:e.detail>1?(o++,o>4&&(o=1)):o=1;if(i.isIE){var c=Math.abs(e.clientX-u)>5||Math.abs(e.clientY-a)>5;if(!f||c)o=1;f&&clearTimeout(f),f=setTimeout(function(){f=null},n[o-1]||600),o==1&&(u=e.clientX,a=e.clientY)}e._clicks=o,r[s]("mousedown",e);if(o>4)o=0;else if(o>1)return r[s](l[o],e)}function h(e){o=2,f&&clearTimeout(f),f=setTimeout(function(){f=null},n[o-1]||600),r[s]("mousedown",e),r[s](l[o],e)}var o=0,u,a,f,l={2:"dblclick",3:"tripleclick",4:"quadclick"};Array.isArray(e)||(e=[e]),e.forEach(function(e){t.addListener(e,"mousedown",c),i.isOldIE&&t.addListener(e,"dblclick",h)})};var u=!i.isMac||!i.isOpera||"KeyboardEvent"in window?function(e){return 0|(e.ctrlKey?1:0)|(e.altKey?2:0)|(e.shiftKey?4:0)|(e.metaKey?8:0)}:function(e){return 0|(e.metaKey?1:0)|(e.altKey?2:0)|(e.shiftKey?4:0)|(e.ctrlKey?8:0)};t.getModifierString=function(e){return r.KEY_MODS[u(e)]},t.addCommandKeyListener=function(e,n){var r=t.addListener;if(i.isOldGecko||i.isOpera&&!("KeyboardEvent"in window)){var o=null;r(e,"keydown",function(e){o=e.keyCode}),r(e,"keypress",function(e){return a(n,e,o)})}else{var u=null;r(e,"keydown",function(e){s[e.keyCode]=(s[e.keyCode]||0)+1;var t=a(n,e,e.keyCode);return u=e.defaultPrevented,t}),r(e,"keypress",function(e){u&&(e.ctrlKey||e.altKey||e.shiftKey||e.metaKey)&&(t.stopEvent(e),u=null)}),r(e,"keyup",function(e){s[e.keyCode]=null}),s||(f(),r(window,"focus",f))}};if(typeof window=="object"&&window.postMessage&&!i.isOldIE){var l=1;t.nextTick=function(e,n){n=n||window;var r="zero-timeout-message-"+l++,i=function(s){s.data==r&&(t.stopPropagation(s),t.removeListener(n,"message",i),e())};t.addListener(n,"message",i),n.postMessage(r,"*")}}t.$idleBlocked=!1,t.onIdle=function(e,n){return setTimeout(function r(){t.$idleBlocked?setTimeout(r,100):e()},n)},t.$idleBlockId=null,t.blockIdle=function(e){t.$idleBlockId&&clearTimeout(t.$idleBlockId),t.$idleBlocked=!0,t.$idleBlockId=setTimeout(function(){t.$idleBlocked=!1},e||100)},t.nextFrame=typeof window=="object"&&(window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame),t.nextFrame?t.nextFrame=t.nextFrame.bind(window):t.nextFrame=function(e){setTimeout(e,17)}}),define("ace/range",["require","exports","module"],function(e,t,n){"use strict";var r=function(e,t){return e.row-t.row||e.column-t.column},i=function(e,t,n,r){this.start={row:e,column:t},this.end={row:n,column:r}};(function(){this.isEqual=function(e){return this.start.row===e.start.row&&this.end.row===e.end.row&&this.start.column===e.start.column&&this.end.column===e.end.column},this.toString=function(){return"Range: ["+this.start.row+"/"+this.start.column+"] -> ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e=="object"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e=="object"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?tthis.end.column?1:0:ethis.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};else if(this.end.rowt)var r={row:t+1,column:0};else if(this.start.row0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\s\s*/,i=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(r,"")},t.stringTrimRight=function(e){return e.replace(i,"")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;nh.length?e=e.substr(9):e.substr(0,4)==h.substr(0,4)?e=e.substr(4,e.length-h.length+1):e.charAt(e.length-1)==h.charAt(0)&&(e=e.slice(0,-1)),e!=h.charAt(0)&&e.charAt(e.length-1)==h.charAt(0)&&(e=e.slice(0,-1)),e&&t.onTextInput(e)),p&&(p=!1),L&&(L=!1)},O=function(e){if(m)return;var t=c.value;A(t),T()},M=function(e,t,n){var r=e.clipboardData||window.clipboardData;if(!r||f)return;var i=l||n?"Text":"text/plain";try{return t?r.setData(i,t)!==!1:r.getData(i)}catch(e){if(!n)return M(e,t,!0)}},_=function(e,n){var s=t.getCopyText();if(!s)return r.preventDefault(e);M(e,s)?(i.isIOS&&(d=n,c.value="\n aa"+s+"a a\n",c.setSelectionRange(4,4+s.length),p={value:s}),n?t.onCut():t.onCopy(),i.isIOS||r.preventDefault(e)):(p=!0,c.value=s,c.select(),setTimeout(function(){p=!1,T(),x(),n?t.onCut():t.onCopy()}))},D=function(e){_(e,!0)},P=function(e){_(e,!1)},H=function(e){var n=M(e);typeof n=="string"?(n&&t.onPaste(n,e),i.isIE&&setTimeout(x),r.preventDefault(e)):(c.value="",v=!0)};r.addCommandKeyListener(c,t.onCommandKey.bind(t)),r.addListener(c,"select",C),r.addListener(c,"input",O),r.addListener(c,"cut",D),r.addListener(c,"copy",P),r.addListener(c,"paste",H);var B=function(e){if(m||!t.onCompositionStart||t.$readOnly)return;m={},m.canUndo=t.session.$undoManager,t.onCompositionStart(),setTimeout(j,0),t.on("mousedown",F),m.canUndo&&!t.selection.isEmpty()&&(t.insert(""),t.session.markUndoGroup(),t.selection.clearSelection()),t.session.markUndoGroup()},j=function(){if(!m||!t.onCompositionUpdate||t.$readOnly)return;var e=c.value.replace(/\x01/g,"");if(m.lastValue===e)return;t.onCompositionUpdate(e),m.lastValue&&t.undo(),m.canUndo&&(m.lastValue=e);if(m.lastValue){var n=t.selection.getRange();t.insert(m.lastValue),t.session.markUndoGroup(),m.range=t.selection.getRange(),t.selection.setRange(n),t.selection.clearSelection()}},F=function(e){if(!t.onCompositionEnd||t.$readOnly)return;var n=m;m=!1;var r=setTimeout(function(){r=null;var e=c.value.replace(/\x01/g,"");if(m)return;e==n.lastValue?T():!n.lastValue&&e&&(T(),A(e))});k=function(i){return r&&clearTimeout(r),i=i.replace(/\x01/g,""),i==n.lastValue?"":(n.lastValue&&r&&t.undo(),i)},t.onCompositionEnd(),t.removeListener("mousedown",F),e.type=="compositionend"&&n.range&&t.selection.setRange(n.range);var s=!!i.isChrome&&i.isChrome>=53||!!i.isWebKit&&i.isWebKit>=603;s&&O()},I=o.delayedCall(j,50);r.addListener(c,"compositionstart",B),r.addListener(c,"compositionupdate",function(){I.schedule()}),r.addListener(c,"keyup",function(){I.schedule()}),r.addListener(c,"keydown",function(){I.schedule()}),r.addListener(c,"compositionend",F),this.getElement=function(){return c},this.setReadOnly=function(e){c.readOnly=e},this.onContextMenu=function(e){L=!0,x(t.selection.isEmpty()),t._emit("nativecontextmenu",{target:t,domEvent:e}),this.moveToMouse(e,!0)},this.moveToMouse=function(e,n){g||(g=c.style.cssText),c.style.cssText=(n?"z-index:100000;":"")+"height:"+c.style.height+";"+(i.isIE?"opacity:0.1;":"");var o=t.container.getBoundingClientRect(),u=s.computedStyle(t.container),a=o.top+(parseInt(u.borderTopWidth)||0),f=o.left+(parseInt(o.borderLeftWidth)||0),l=o.bottom-a-c.clientHeight-2,h=function(e){c.style.left=e.clientX-f-2+"px",c.style.top=Math.min(e.clientY-a-2,l)+"px"};h(e);if(e.type!="mousedown")return;t.renderer.$keepTextAreaAtCursor&&(t.renderer.$keepTextAreaAtCursor=null),clearTimeout(q),i.isWin&&r.capture(t.container,h,R)},this.onContextMenuClose=R;var q,U=function(e){t.textInput.onContextMenu(e),R()};r.addListener(c,"mouseup",U),r.addListener(c,"mousedown",function(e){e.preventDefault(),R()}),r.addListener(t.renderer.scroller,"contextmenu",U),r.addListener(c,"contextmenu",U);if(i.isIOS){var z=null,W=!1;e.addEventListener("keydown",function(e){z&&clearTimeout(z),W=!0}),e.addEventListener("keyup",function(e){z=setTimeout(function(){W=!1},100)});var X=function(e){if(document.activeElement!==c)return;if(W)return;if(d)return setTimeout(function(){d=!1},100);var n=c.selectionStart,r=c.selectionEnd;c.setSelectionRange(4,5);if(n==r)switch(n){case 0:t.onCommandKey(null,0,u.up);break;case 1:t.onCommandKey(null,0,u.home);break;case 2:t.onCommandKey(null,a.option,u.left);break;case 4:t.onCommandKey(null,0,u.left);break;case 5:t.onCommandKey(null,0,u.right);break;case 7:t.onCommandKey(null,a.option,u.right);break;case 8:t.onCommandKey(null,0,u.end);break;case 9:t.onCommandKey(null,0,u.down)}else{switch(r){case 6:t.onCommandKey(null,a.shift,u.right);break;case 7:t.onCommandKey(null,a.shift|a.option,u.right);break;case 8:t.onCommandKey(null,a.shift,u.end);break;case 9:t.onCommandKey(null,a.shift,u.down)}switch(n){case 0:t.onCommandKey(null,a.shift,u.up);break;case 1:t.onCommandKey(null,a.shift,u.home);break;case 2:t.onCommandKey(null,a.shift|a.option,u.left);break;case 3:t.onCommandKey(null,a.shift,u.left)}}};document.addEventListener("selectionchange",X),t.on("destroy",function(){document.removeEventListener("selectionchange",X)})}};t.TextInput=c}),define("ace/keyboard/textinput",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/lib/dom","ace/lib/lang","ace/keyboard/textinput_ios"],function(e,t,n){"use strict";var r=e("../lib/event"),i=e("../lib/useragent"),s=e("../lib/dom"),o=e("../lib/lang"),u=i.isChrome<18,a=i.isIE,f=i.isChrome>63,l=400,c=e("./textinput_ios").TextInput,h=function(e,t){function C(){if(d||v)return;if(!T&&!O)return;d=!0;var e=t.selection,r=e.getRange(),i=e.cursor.row,s=r.start.column,o=r.end.column,u=t.session.getLine(i);if(r.start.row!=i){var a=t.session.getLine(i-1);s=r.start.rowi+1?f.length:o,o+=u.length+1,u=u+"\n"+f}u.length>l&&(s=E.length&&e.value===E&&E&&e.selectionEnd!==x},L=function(e){if(d)return;h?h=!1:k(n)&&(t.selectAll(),C())},A=null;this.setInputHandler=function(e){A=e},this.getInputHandler=function(){return A};var O=!1,M=function(e,r){O&&(O=!1);if(p)return C(),e&&t.onPaste(e),p=!1,"";var i=n.selectionStart,s=n.selectionEnd,o=S,u=E.length-x,a=e,f=e.length-i,l=e.length-s,c=0;while(o>0&&E[c]==e[c])c++,o--;a=a.slice(c),c=1;while(u>0&&E.length-c>S-1&&E[E.length-c]==e[e.length-c])c++,u--;return f-=c-1,l-=c-1,a=a.slice(0,a.length-c+1),!r&&f==a.length&&!o&&!u&&!l?"":(v=!0,a&&!o&&!u&&!f&&!l||b?t.onTextInput(a):t.onTextInput(a,{extendLeft:o,extendRight:u,restoreStart:f,restoreEnd:l}),v=!1,E=e,S=i,x=s,a)},_=function(e){if(d)return I();var t=n.value,r=M(t,!0);(t.length>l+100||/\n/.test(r))&&C()},D=function(e,t,n){var r=e.clipboardData||window.clipboardData;if(!r||u)return;var i=a||n?"Text":"text/plain";try{return t?r.setData(i,t)!==!1:r.getData(i)}catch(e){if(!n)return D(e,t,!0)}},P=function(e,i){var s=t.getCopyText();if(!s)return r.preventDefault(e);D(e,s)?(i?t.onCut():t.onCopy(),r.preventDefault(e)):(h=!0,n.value=s,n.select(),setTimeout(function(){h=!1,C(),i?t.onCut():t.onCopy()}))},H=function(e){P(e,!0)},B=function(e){P(e,!1)},j=function(e){var s=D(e);typeof s=="string"?(s&&t.onPaste(s,e),i.isIE&&setTimeout(C),r.preventDefault(e)):(n.value="",p=!0)};r.addCommandKeyListener(n,t.onCommandKey.bind(t)),r.addListener(n,"select",L),r.addListener(n,"input",_),r.addListener(n,"cut",H),r.addListener(n,"copy",B),r.addListener(n,"paste",j),(!("oncut"in n)||!("oncopy"in n)||!("onpaste"in n))&&r.addListener(e,"keydown",function(e){if(i.isMac&&!e.metaKey||!e.ctrlKey)return;switch(e.keyCode){case 67:B(e);break;case 86:j(e);break;case 88:H(e)}});var F=function(e){if(d||!t.onCompositionStart||t.$readOnly)return;d={};if(b)return;setTimeout(I,0),t.on("mousedown",R);var r=t.getSelectionRange();r.end.row=r.start.row,r.end.column=r.start.column,d.markerRange=r,d.selectionStart=S,t.onCompositionStart(d),d.useTextareaForIME?(n.value="",E="",S=0,x=0):(n.msGetInputContext&&(d.context=n.msGetInputContext()),n.getInputContext&&(d.context=n.getInputContext()))},I=function(){if(!d||!t.onCompositionUpdate||t.$readOnly)return;if(b)return R();if(d.useTextareaForIME)t.onCompositionUpdate(n.value);else{var e=n.value;M(e),d.markerRange&&(d.context&&(d.markerRange.start.column=d.selectionStart=d.context.compositionStartOffset),d.markerRange.end.column=d.markerRange.start.column+x-d.selectionStart)}},q=function(e){if(!t.onCompositionEnd||t.$readOnly)return;d=!1,t.onCompositionEnd(),t.off("mousedown",R),e&&_()},U=o.delayedCall(I,50).schedule.bind(null,null);r.addListener(n,"compositionstart",F),r.addListener(n,"compositionupdate",I),r.addListener(n,"keyup",z),r.addListener(n,"keydown",U),r.addListener(n,"compositionend",q),this.getElement=function(){return n},this.setCommandMode=function(e){b=e,n.readOnly=!1},this.setReadOnly=function(e){b||(n.readOnly=e)},this.setCopyWithEmptySelection=function(e){y=e},this.onContextMenu=function(e){O=!0,C(),t._emit("nativecontextmenu",{target:t,domEvent:e}),this.moveToMouse(e,!0)},this.moveToMouse=function(e,o){m||(m=n.style.cssText),n.style.cssText=(o?"z-index:100000;":"")+(i.isIE?"opacity:0.1;":"")+"text-indent: -"+(S+x)*t.renderer.characterWidth*.5+"px;";var u=t.container.getBoundingClientRect(),a=s.computedStyle(t.container),f=u.top+(parseInt(a.borderTopWidth)||0),l=u.left+(parseInt(u.borderLeftWidth)||0),c=u.bottom-f-n.clientHeight-2,h=function(e){n.style.left=e.clientX-l-2+"px",n.style.top=Math.min(e.clientY-f-2,c)+"px"};h(e);if(e.type!="mousedown")return;t.renderer.$keepTextAreaAtCursor&&(t.renderer.$keepTextAreaAtCursor=null),clearTimeout(W),i.isWin&&r.capture(t.container,h,X)},this.onContextMenuClose=X;var W,V=function(e){t.textInput.onContextMenu(e),X()};r.addListener(n,"mouseup",V),r.addListener(n,"mousedown",function(e){e.preventDefault(),X()}),r.addListener(t.renderer.scroller,"contextmenu",V),r.addListener(n,"contextmenu",V)};t.TextInput=h}),define("ace/mouse/default_handlers",["require","exports","module","ace/lib/useragent"],function(e,t,n){"use strict";function o(e){e.$clickSelection=null;var t=e.editor;t.setDefaultHandler("mousedown",this.onMouseDown.bind(e)),t.setDefaultHandler("dblclick",this.onDoubleClick.bind(e)),t.setDefaultHandler("tripleclick",this.onTripleClick.bind(e)),t.setDefaultHandler("quadclick",this.onQuadClick.bind(e)),t.setDefaultHandler("mousewheel",this.onMouseWheel.bind(e)),t.setDefaultHandler("touchmove",this.onTouchMove.bind(e));var n=["select","startSelect","selectEnd","selectAllEnd","selectByWordsEnd","selectByLinesEnd","dragWait","dragWaitEnd","focusWait"];n.forEach(function(t){e[t]=this[t]},this),e.selectByLines=this.extendSelectionBy.bind(e,"getLineRange"),e.selectByWords=this.extendSelectionBy.bind(e,"getWordRange")}function u(e,t,n,r){return Math.sqrt(Math.pow(n-e,2)+Math.pow(r-t,2))}function a(e,t){if(e.start.row==e.end.row)var n=2*t.column-e.start.column-e.end.column;else if(e.start.row==e.end.row-1&&!e.start.column&&!e.end.column)var n=t.column-4;else var n=2*t.row-e.start.row-e.end.row;return n<0?{cursor:e.start,anchor:e.end}:{cursor:e.end,anchor:e.start}}var r=e("../lib/useragent"),i=0,s=250;(function(){this.onMouseDown=function(e){var t=e.inSelection(),n=e.getDocumentPosition();this.mousedownEvent=e;var i=this.editor,s=e.getButton();if(s!==0){var o=i.getSelectionRange(),u=o.isEmpty();(u||s==1)&&i.selection.moveToPosition(n),s==2&&(i.textInput.onContextMenu(e.domEvent),r.isMozilla||e.preventDefault());return}this.mousedownEvent.time=Date.now();if(t&&!i.isFocused()){i.focus();if(this.$focusTimeout&&!this.$clickSelection&&!i.inMultiSelectMode){this.setState("focusWait"),this.captureMouse(e);return}}return this.captureMouse(e),this.startSelect(n,e.domEvent._clicks>1),e.preventDefault()},this.startSelect=function(e,t){e=e||this.editor.renderer.screenToTextCoordinates(this.x,this.y);var n=this.editor;if(!this.mousedownEvent)return;this.mousedownEvent.getShiftKey()?n.selection.selectToPosition(e):t||n.selection.moveToPosition(e),t||this.select(),n.renderer.scroller.setCapture&&n.renderer.scroller.setCapture(),n.setStyle("ace_selecting"),this.setState("select")},this.select=function(){var e,t=this.editor,n=t.renderer.screenToTextCoordinates(this.x,this.y);if(this.$clickSelection){var r=this.$clickSelection.comparePoint(n);if(r==-1)e=this.$clickSelection.end;else if(r==1)e=this.$clickSelection.start;else{var i=a(this.$clickSelection,n);n=i.cursor,e=i.anchor}t.selection.setSelectionAnchor(e.row,e.column)}t.selection.selectToPosition(n),t.renderer.scrollCursorIntoView()},this.extendSelectionBy=function(e){var t,n=this.editor,r=n.renderer.screenToTextCoordinates(this.x,this.y),i=n.selection[e](r.row,r.column);if(this.$clickSelection){var s=this.$clickSelection.comparePoint(i.start),o=this.$clickSelection.comparePoint(i.end);if(s==-1&&o<=0){t=this.$clickSelection.end;if(i.end.row!=r.row||i.end.column!=r.column)r=i.start}else if(o==1&&s>=0){t=this.$clickSelection.start;if(i.start.row!=r.row||i.start.column!=r.column)r=i.end}else if(s==-1&&o==1)r=i.end,t=i.start;else{var u=a(this.$clickSelection,r);r=u.cursor,t=u.anchor}n.selection.setSelectionAnchor(t.row,t.column)}n.selection.selectToPosition(r),n.renderer.scrollCursorIntoView()},this.selectEnd=this.selectAllEnd=this.selectByWordsEnd=this.selectByLinesEnd=function(){this.$clickSelection=null,this.editor.unsetStyle("ace_selecting"),this.editor.renderer.scroller.releaseCapture&&this.editor.renderer.scroller.releaseCapture()},this.focusWait=function(){var e=u(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),t=Date.now();(e>i||t-this.mousedownEvent.time>this.$focusTimeout)&&this.startSelect(this.mousedownEvent.getDocumentPosition())},this.onDoubleClick=function(e){var t=e.getDocumentPosition(),n=this.editor,r=n.session,i=r.getBracketRange(t);i?(i.isEmpty()&&(i.start.column--,i.end.column++),this.setState("select")):(i=n.selection.getWordRange(t.row,t.column),this.setState("selectByWords")),this.$clickSelection=i,this.select()},this.onTripleClick=function(e){var t=e.getDocumentPosition(),n=this.editor;this.setState("selectByLines");var r=n.getSelectionRange();r.isMultiLine()&&r.contains(t.row,t.column)?(this.$clickSelection=n.selection.getLineRange(r.start.row),this.$clickSelection.end=n.selection.getLineRange(r.end.row).end):this.$clickSelection=n.selection.getLineRange(t.row),this.select()},this.onQuadClick=function(e){var t=this.editor;t.selectAll(),this.$clickSelection=t.getSelectionRange(),this.setState("selectAll")},this.onMouseWheel=function(e){if(e.getAccelKey())return;e.getShiftKey()&&e.wheelY&&!e.wheelX&&(e.wheelX=e.wheelY,e.wheelY=0);var t=this.editor;this.$lastScroll||(this.$lastScroll={t:0,vx:0,vy:0,allowed:0});var n=this.$lastScroll,r=e.domEvent.timeStamp,i=r-n.t,o=i?e.wheelX/i:n.vx,u=i?e.wheelY/i:n.vy;i=1&&t.renderer.isScrollableBy(e.wheelX*e.speed,0)&&(f=!0),a<=1&&t.renderer.isScrollableBy(0,e.wheelY*e.speed)&&(f=!0);if(f)n.allowed=r;else if(r-n.allowedt.session.documentToScreenRow(l.row,l.column))return c()}if(f==s)return;f=s.text.join("
"),i.setHtml(f),i.show(),t._signal("showGutterTooltip",i),t.on("mousewheel",c);if(e.$tooltipFollowsMouse)h(u);else{var p=u.domEvent.target,d=p.getBoundingClientRect(),v=i.getElement().style;v.left=d.right+"px",v.top=d.bottom+"px"}}function c(){o&&(o=clearTimeout(o)),f&&(i.hide(),f=null,t._signal("hideGutterTooltip",i),t.removeEventListener("mousewheel",c))}function h(e){i.setPosition(e.x,e.y)}var t=e.editor,n=t.renderer.$gutterLayer,i=new a(t.container);e.editor.setDefaultHandler("guttermousedown",function(r){if(!t.isFocused()||r.getButton()!=0)return;var i=n.getRegion(r);if(i=="foldWidgets")return;var s=r.getDocumentPosition().row,o=t.session.selection;if(r.getShiftKey())o.selectTo(s,0);else{if(r.domEvent.detail==2)return t.selectAll(),r.preventDefault();e.$clickSelection=t.selection.getLineRange(s)}return e.setState("selectByLines"),e.captureMouse(r),r.preventDefault()});var o,u,f;e.editor.setDefaultHandler("guttermousemove",function(t){var n=t.domEvent.target||t.domEvent.srcElement;if(r.hasCssClass(n,"ace_fold-widget"))return c();f&&e.$tooltipFollowsMouse&&h(t),u=t;if(o)return;o=setTimeout(function(){o=null,u&&!e.isMousePressed?l():c()},50)}),s.addListener(t.renderer.$gutter,"mouseout",function(e){u=null;if(!f||o)return;o=setTimeout(function(){o=null,c()},50)}),t.on("changeSession",c)}function a(e){o.call(this,e)}var r=e("../lib/dom"),i=e("../lib/oop"),s=e("../lib/event"),o=e("../tooltip").Tooltip;i.inherits(a,o),function(){this.setPosition=function(e,t){var n=window.innerWidth||document.documentElement.clientWidth,r=window.innerHeight||document.documentElement.clientHeight,i=this.getWidth(),s=this.getHeight();e+=15,t+=15,e+i>n&&(e-=e+i-n),t+s>r&&(t-=20+s),o.prototype.setPosition.call(this,e,t)}}.call(a.prototype),t.GutterHandler=u}),define("ace/mouse/mouse_event",["require","exports","module","ace/lib/event","ace/lib/useragent"],function(e,t,n){"use strict";var r=e("../lib/event"),i=e("../lib/useragent"),s=t.MouseEvent=function(e,t){this.domEvent=e,this.editor=t,this.x=this.clientX=e.clientX,this.y=this.clientY=e.clientY,this.$pos=null,this.$inSelection=null,this.propagationStopped=!1,this.defaultPrevented=!1};(function(){this.stopPropagation=function(){r.stopPropagation(this.domEvent),this.propagationStopped=!0},this.preventDefault=function(){r.preventDefault(this.domEvent),this.defaultPrevented=!0},this.stop=function(){this.stopPropagation(),this.preventDefault()},this.getDocumentPosition=function(){return this.$pos?this.$pos:(this.$pos=this.editor.renderer.screenToTextCoordinates(this.clientX,this.clientY),this.$pos)},this.inSelection=function(){if(this.$inSelection!==null)return this.$inSelection;var e=this.editor,t=e.getSelectionRange();if(t.isEmpty())this.$inSelection=!1;else{var n=this.getDocumentPosition();this.$inSelection=t.contains(n.row,n.column)}return this.$inSelection},this.getButton=function(){return r.getButton(this.domEvent)},this.getShiftKey=function(){return this.domEvent.shiftKey},this.getAccelKey=i.isMac?function(){return this.domEvent.metaKey}:function(){return this.domEvent.ctrlKey}}).call(s.prototype)}),define("ace/mouse/dragdrop_handler",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"],function(e,t,n){"use strict";function f(e){function T(e,n){var r=Date.now(),i=!n||e.row!=n.row,s=!n||e.column!=n.column;if(!S||i||s)t.moveCursorToPosition(e),S=r,x={x:p,y:d};else{var o=l(x.x,x.y,p,d);o>a?S=null:r-S>=u&&(t.renderer.scrollCursorIntoView(),S=null)}}function N(e,n){var r=Date.now(),i=t.renderer.layerConfig.lineHeight,s=t.renderer.layerConfig.characterWidth,u=t.renderer.scroller.getBoundingClientRect(),a={x:{left:p-u.left,right:u.right-p},y:{top:d-u.top,bottom:u.bottom-d}},f=Math.min(a.x.left,a.x.right),l=Math.min(a.y.top,a.y.bottom),c={row:e.row,column:e.column};f/s<=2&&(c.column+=a.x.left=o&&t.renderer.scrollCursorIntoView(c):E=r:E=null}function C(){var e=g;g=t.renderer.screenToTextCoordinates(p,d),T(g,e),N(g,e)}function k(){m=t.selection.toOrientedRange(),h=t.session.addMarker(m,"ace_selection",t.getSelectionStyle()),t.clearSelection(),t.isFocused()&&t.renderer.$cursorLayer.setBlinking(!1),clearInterval(v),C(),v=setInterval(C,20),y=0,i.addListener(document,"mousemove",O)}function L(){clearInterval(v),t.session.removeMarker(h),h=null,t.selection.fromOrientedRange(m),t.isFocused()&&!w&&t.renderer.$cursorLayer.setBlinking(!t.getReadOnly()),m=null,g=null,y=0,E=null,S=null,i.removeListener(document,"mousemove",O)}function O(){A==null&&(A=setTimeout(function(){A!=null&&h&&L()},20))}function M(e){var t=e.types;return!t||Array.prototype.some.call(t,function(e){return e=="text/plain"||e=="Text"})}function _(e){var t=["copy","copymove","all","uninitialized"],n=["move","copymove","linkmove","all","uninitialized"],r=s.isMac?e.altKey:e.ctrlKey,i="uninitialized";try{i=e.dataTransfer.effectAllowed.toLowerCase()}catch(e){}var o="none";return r&&t.indexOf(i)>=0?o="copy":n.indexOf(i)>=0?o="move":t.indexOf(i)>=0&&(o="copy"),o}var t=e.editor,n=r.createElement("img");n.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",s.isOpera&&(n.style.cssText="width:1px;height:1px;position:fixed;top:0;left:0;z-index:2147483647;opacity:0;");var f=["dragWait","dragWaitEnd","startDrag","dragReadyEnd","onMouseDrag"];f.forEach(function(t){e[t]=this[t]},this),t.addEventListener("mousedown",this.onMouseDown.bind(e));var c=t.container,h,p,d,v,m,g,y=0,b,w,E,S,x;this.onDragStart=function(e){if(this.cancelDrag||!c.draggable){var r=this;return setTimeout(function(){r.startSelect(),r.captureMouse(e)},0),e.preventDefault()}m=t.getSelectionRange();var i=e.dataTransfer;i.effectAllowed=t.getReadOnly()?"copy":"copyMove",s.isOpera&&(t.container.appendChild(n),n.scrollTop=0),i.setDragImage&&i.setDragImage(n,0,0),s.isOpera&&t.container.removeChild(n),i.clearData(),i.setData("Text",t.session.getTextRange()),w=!0,this.setState("drag")},this.onDragEnd=function(e){c.draggable=!1,w=!1,this.setState(null);if(!t.getReadOnly()){var n=e.dataTransfer.dropEffect;!b&&n=="move"&&t.session.remove(t.getSelectionRange()),t.renderer.$cursorLayer.setBlinking(!0)}this.editor.unsetStyle("ace_dragging"),this.editor.renderer.setCursorStyle("")},this.onDragEnter=function(e){if(t.getReadOnly()||!M(e.dataTransfer))return;return p=e.clientX,d=e.clientY,h||k(),y++,e.dataTransfer.dropEffect=b=_(e),i.preventDefault(e)},this.onDragOver=function(e){if(t.getReadOnly()||!M(e.dataTransfer))return;return p=e.clientX,d=e.clientY,h||(k(),y++),A!==null&&(A=null),e.dataTransfer.dropEffect=b=_(e),i.preventDefault(e)},this.onDragLeave=function(e){y--;if(y<=0&&h)return L(),b=null,i.preventDefault(e)},this.onDrop=function(e){if(!g)return;var n=e.dataTransfer;if(w)switch(b){case"move":m.contains(g.row,g.column)?m={start:g,end:g}:m=t.moveText(m,g);break;case"copy":m=t.moveText(m,g,!0)}else{var r=n.getData("Text");m={start:g,end:t.session.insert(g,r)},t.focus(),b=null}return L(),i.preventDefault(e)},i.addListener(c,"dragstart",this.onDragStart.bind(e)),i.addListener(c,"dragend",this.onDragEnd.bind(e)),i.addListener(c,"dragenter",this.onDragEnter.bind(e)),i.addListener(c,"dragover",this.onDragOver.bind(e)),i.addListener(c,"dragleave",this.onDragLeave.bind(e)),i.addListener(c,"drop",this.onDrop.bind(e));var A=null}function l(e,t,n,r){return Math.sqrt(Math.pow(n-e,2)+Math.pow(r-t,2))}var r=e("../lib/dom"),i=e("../lib/event"),s=e("../lib/useragent"),o=200,u=200,a=5;(function(){this.dragWait=function(){var e=Date.now()-this.mousedownEvent.time;e>this.editor.getDragDelay()&&this.startDrag()},this.dragWaitEnd=function(){var e=this.editor.container;e.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()),this.selectEnd()},this.dragReadyEnd=function(e){this.editor.renderer.$cursorLayer.setBlinking(!this.editor.getReadOnly()),this.editor.unsetStyle("ace_dragging"),this.editor.renderer.setCursorStyle(""),this.dragWaitEnd()},this.startDrag=function(){this.cancelDrag=!1;var e=this.editor,t=e.container;t.draggable=!0,e.renderer.$cursorLayer.setBlinking(!1),e.setStyle("ace_dragging");var n=s.isWin?"default":"move";e.renderer.setCursorStyle(n),this.setState("dragReady")},this.onMouseDrag=function(e){var t=this.editor.container;if(s.isIE&&this.state=="dragReady"){var n=l(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);n>3&&t.dragDrop()}if(this.state==="dragWait"){var n=l(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);n>0&&(t.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()))}},this.onMouseDown=function(e){if(!this.$dragEnabled)return;this.mousedownEvent=e;var t=this.editor,n=e.inSelection(),r=e.getButton(),i=e.domEvent.detail||1;if(i===1&&r===0&&n){if(e.editor.inMultiSelectMode&&(e.getAccelKey()||e.getShiftKey()))return;this.mousedownEvent.time=Date.now();var o=e.domEvent.target||e.domEvent.srcElement;"unselectable"in o&&(o.unselectable="on");if(t.getDragDelay()){if(s.isWebKit){this.cancelDrag=!0;var u=t.container;u.draggable=!0}this.setState("dragWait")}else this.startDrag();this.captureMouse(e,this.onMouseDrag.bind(this)),e.defaultPrevented=!0}}}).call(f.prototype),t.DragdropHandler=f}),define("ace/lib/net",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";var r=e("./dom");t.get=function(e,t){var n=new XMLHttpRequest;n.open("GET",e,!0),n.onreadystatechange=function(){n.readyState===4&&t(n.responseText)},n.send(null)},t.loadScript=function(e,t){var n=r.getDocumentHead(),i=document.createElement("script");i.src=e,n.appendChild(i),i.onload=i.onreadystatechange=function(e,n){if(n||!i.readyState||i.readyState=="loaded"||i.readyState=="complete")i=i.onload=i.onreadystatechange=null,n||t()}},t.qualifyURL=function(e){var t=document.createElement("a");return t.href=e,t.href}}),define("ace/lib/event_emitter",["require","exports","module"],function(e,t,n){"use strict";var r={},i=function(){this.propagationStopped=!0},s=function(){this.defaultPrevented=!0};r._emit=r._dispatchEvent=function(e,t){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var n=this._eventRegistry[e]||[],r=this._defaultHandlers[e];if(!n.length&&!r)return;if(typeof t!="object"||!t)t={};t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=i),t.preventDefault||(t.preventDefault=s),n=n.slice();for(var o=0;o1&&(i=n[n.length-2]);var o=a[t+"Path"];return o==null?o=a.basePath:r=="/"&&(t=r=""),o&&o.slice(-1)!="/"&&(o+="/"),o+t+r+i+this.get("suffix")},t.setModuleUrl=function(e,t){return a.$moduleUrls[e]=t},t.$loading={},t.loadModule=function(n,r){var i,o;Array.isArray(n)&&(o=n[0],n=n[1]);try{i=e(n)}catch(u){}if(i&&!t.$loading[n])return r&&r(i);t.$loading[n]||(t.$loading[n]=[]),t.$loading[n].push(r);if(t.$loading[n].length>1)return;var a=function(){e([n],function(e){t._emit("load.module",{name:n,module:e});var r=t.$loading[n];t.$loading[n]=null,r.forEach(function(t){t&&t(e)})})};if(!t.get("packaged"))return a();s.loadScript(t.moduleUrl(n,o),a),f()};var f=function(){!a.basePath&&!a.workerPath&&!a.modePath&&!a.themePath&&!Object.keys(a.$moduleUrls).length&&(console.error("Unable to infer path to ace from script src,","use ace.config.set('basePath', 'path') to enable dynamic loading of modes and themes","or with webpack use ace/webpack-resolver"),f=function(){})};t.init=l}),define("ace/mouse/mouse_handler",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/mouse/default_handlers","ace/mouse/default_gutter_handler","ace/mouse/mouse_event","ace/mouse/dragdrop_handler","ace/config"],function(e,t,n){"use strict";var r=e("../lib/event"),i=e("../lib/useragent"),s=e("./default_handlers").DefaultHandlers,o=e("./default_gutter_handler").GutterHandler,u=e("./mouse_event").MouseEvent,a=e("./dragdrop_handler").DragdropHandler,f=e("../config"),l=function(e){var t=this;this.editor=e,new s(this),new o(this),new a(this);var n=function(t){var n=!document.hasFocus||!document.hasFocus()||!e.isFocused()&&document.activeElement==(e.textInput&&e.textInput.getElement());n&&window.focus(),e.focus()},u=e.renderer.getMouseEventTarget();r.addListener(u,"click",this.onMouseEvent.bind(this,"click")),r.addListener(u,"mousemove",this.onMouseMove.bind(this,"mousemove")),r.addMultiMouseDownListener([u,e.renderer.scrollBarV&&e.renderer.scrollBarV.inner,e.renderer.scrollBarH&&e.renderer.scrollBarH.inner,e.textInput&&e.textInput.getElement()].filter(Boolean),[400,300,250],this,"onMouseEvent"),r.addMouseWheelListener(e.container,this.onMouseWheel.bind(this,"mousewheel")),r.addTouchMoveListener(e.container,this.onTouchMove.bind(this,"touchmove"));var f=e.renderer.$gutter;r.addListener(f,"mousedown",this.onMouseEvent.bind(this,"guttermousedown")),r.addListener(f,"click",this.onMouseEvent.bind(this,"gutterclick")),r.addListener(f,"dblclick",this.onMouseEvent.bind(this,"gutterdblclick")),r.addListener(f,"mousemove",this.onMouseEvent.bind(this,"guttermousemove")),r.addListener(u,"mousedown",n),r.addListener(f,"mousedown",n),i.isIE&&e.renderer.scrollBarV&&(r.addListener(e.renderer.scrollBarV.element,"mousedown",n),r.addListener(e.renderer.scrollBarH.element,"mousedown",n)),e.on("mousemove",function(n){if(t.state||t.$dragDelay||!t.$dragEnabled)return;var r=e.renderer.screenToTextCoordinates(n.x,n.y),i=e.session.selection.getRange(),s=e.renderer;!i.isEmpty()&&i.insideStart(r.row,r.column)?s.setCursorStyle("default"):s.setCursorStyle("")})};(function(){this.onMouseEvent=function(e,t){this.editor._emit(e,new u(t,this.editor))},this.onMouseMove=function(e,t){var n=this.editor._eventRegistry&&this.editor._eventRegistry.mousemove;if(!n||!n.length)return;this.editor._emit(e,new u(t,this.editor))},this.onMouseWheel=function(e,t){var n=new u(t,this.editor);n.speed=this.$scrollSpeed*2,n.wheelX=t.wheelX,n.wheelY=t.wheelY,this.editor._emit(e,n)},this.onTouchMove=function(e,t){var n=new u(t,this.editor);n.speed=1,n.wheelX=t.wheelX,n.wheelY=t.wheelY,this.editor._emit(e,n)},this.setState=function(e){this.state=e},this.captureMouse=function(e,t){this.x=e.x,this.y=e.y,this.isMousePressed=!0;var n=this.editor,s=this.editor.renderer;s.$keepTextAreaAtCursor&&(s.$keepTextAreaAtCursor=null);var o=this,a=function(e){if(!e)return;if(i.isWebKit&&!e.which&&o.releaseMouse)return o.releaseMouse();o.x=e.clientX,o.y=e.clientY,t&&t(e),o.mouseEvent=new u(e,o.editor),o.$mouseMoved=!0},f=function(e){n.off("beforeEndOperation",c),clearInterval(h),l(),o[o.state+"End"]&&o[o.state+"End"](e),o.state="",s.$keepTextAreaAtCursor==null&&(s.$keepTextAreaAtCursor=!0,s.$moveTextAreaToCursor()),o.isMousePressed=!1,o.$onCaptureMouseMove=o.releaseMouse=null,e&&o.onMouseEvent("mouseup",e),n.endOperation()},l=function(){o[o.state]&&o[o.state](),o.$mouseMoved=!1};if(i.isOldIE&&e.domEvent.type=="dblclick")return setTimeout(function(){f(e)});var c=function(e){if(!o.releaseMouse)return;n.curOp.command.name&&n.curOp.selectionChanged&&(o[o.state+"End"]&&o[o.state+"End"](),o.state="",o.releaseMouse())};n.on("beforeEndOperation",c),n.startOperation({command:{name:"mouse"}}),o.$onCaptureMouseMove=a,o.releaseMouse=r.capture(this.editor.container,a,f);var h=setInterval(l,20)},this.releaseMouse=null,this.cancelContextMenu=function(){var e=function(t){if(t&&t.domEvent&&t.domEvent.type!="contextmenu")return;this.editor.off("nativecontextmenu",e),t&&t.domEvent&&r.stopEvent(t.domEvent)}.bind(this);setTimeout(e,10),this.editor.on("nativecontextmenu",e)}}).call(l.prototype),f.defineOptions(l.prototype,"mouseHandler",{scrollSpeed:{initialValue:2},dragDelay:{initialValue:i.isMac?150:0},dragEnabled:{initialValue:!0},focusTimeout:{initialValue:0},tooltipFollowsMouse:{initialValue:!0}}),t.MouseHandler=l}),define("ace/mouse/fold_handler",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";function i(e){e.on("click",function(t){var n=t.getDocumentPosition(),i=e.session,s=i.getFoldAt(n.row,n.column,1);s&&(t.getAccelKey()?i.removeFold(s):i.expandFold(s),t.stop());var o=t.domEvent&&t.domEvent.target;o&&r.hasCssClass(o,"ace_inline_button")&&r.hasCssClass(o,"ace_toggle_wrap")&&(i.setOption("wrap",!0),e.renderer.scrollCursorIntoView())}),e.on("gutterclick",function(t){var n=e.renderer.$gutterLayer.getRegion(t);if(n=="foldWidgets"){var r=t.getDocumentPosition().row,i=e.session;i.foldWidgets&&i.foldWidgets[r]&&e.session.onFoldWidgetClick(r,t),e.isFocused()||e.focus(),t.stop()}}),e.on("gutterdblclick",function(t){var n=e.renderer.$gutterLayer.getRegion(t);if(n=="foldWidgets"){var r=t.getDocumentPosition().row,i=e.session,s=i.getParentFoldRangeData(r,!0),o=s.range||s.firstRange;if(o){r=o.start.row;var u=i.getFoldAt(r,i.getLine(r).length,1);u?i.removeFold(u):(i.addFold("...",o),e.renderer.scrollCursorIntoView({row:o.start.row,column:0}))}t.stop()}})}var r=e("../lib/dom");t.FoldHandler=i}),define("ace/keyboard/keybinding",["require","exports","module","ace/lib/keys","ace/lib/event"],function(e,t,n){"use strict";var r=e("../lib/keys"),i=e("../lib/event"),s=function(e){this.$editor=e,this.$data={editor:e},this.$handlers=[],this.setDefaultHandler(e.commands)};(function(){this.setDefaultHandler=function(e){this.removeKeyboardHandler(this.$defaultHandler),this.$defaultHandler=e,this.addKeyboardHandler(e,0)},this.setKeyboardHandler=function(e){var t=this.$handlers;if(t[t.length-1]==e)return;while(t[t.length-1]&&t[t.length-1]!=this.$defaultHandler)this.removeKeyboardHandler(t[t.length-1]);this.addKeyboardHandler(e,1)},this.addKeyboardHandler=function(e,t){if(!e)return;typeof e=="function"&&!e.handleKeyboard&&(e.handleKeyboard=e);var n=this.$handlers.indexOf(e);n!=-1&&this.$handlers.splice(n,1),t==undefined?this.$handlers.push(e):this.$handlers.splice(t,0,e),n==-1&&e.attach&&e.attach(this.$editor)},this.removeKeyboardHandler=function(e){var t=this.$handlers.indexOf(e);return t==-1?!1:(this.$handlers.splice(t,1),e.detach&&e.detach(this.$editor),!0)},this.getKeyboardHandler=function(){return this.$handlers[this.$handlers.length-1]},this.getStatusText=function(){var e=this.$data,t=e.editor;return this.$handlers.map(function(n){return n.getStatusText&&n.getStatusText(t,e)||""}).filter(Boolean).join(" ")},this.$callKeyboardHandlers=function(e,t,n,r){var s,o=!1,u=this.$editor.commands;for(var a=this.$handlers.length;a--;){s=this.$handlers[a].handleKeyboard(this.$data,e,t,n,r);if(!s||!s.command)continue;s.command=="null"?o=!0:o=u.exec(s.command,this.$editor,s.args,r),o&&r&&e!=-1&&s.passEvent!=1&&s.command.passEvent!=1&&i.stopEvent(r);if(o)break}return!o&&e==-1&&(s={command:"insertstring"},o=u.exec("insertstring",this.$editor,t)),o&&this.$editor._signal&&this.$editor._signal("keyboardActivity",s),o},this.onCommandKey=function(e,t,n){var i=r.keyCodeToString(n);this.$callKeyboardHandlers(t,i,n,e)},this.onTextInput=function(e){this.$callKeyboardHandlers(-1,e)}}).call(s.prototype),t.KeyBinding=s}),define("ace/lib/bidiutil",["require","exports","module"],function(e,t,n){"use strict";function F(e,t,n,r){var i=s?d:p,c=null,h=null,v=null,m=0,g=null,y=null,b=-1,w=null,E=null,T=[];if(!r)for(w=0,r=[];w0)if(g==16){for(w=b;w-1){for(w=b;w=0;C--){if(r[C]!=N)break;t[C]=s}}}function I(e,t,n){if(o=e){u=i+1;while(u=e)u++;for(a=i,l=u-1;a=t.length||(o=n[r-1])!=b&&o!=w||(c=t[r+1])!=b&&c!=w)return E;return u&&(c=w),c==o?c:E;case k:o=r>0?n[r-1]:S;if(o==b&&r+10&&n[r-1]==b)return b;if(u)return E;p=r+1,h=t.length;while(p=1425&&d<=2303||d==64286;o=t[p];if(v&&(o==y||o==T))return y}if(r<1||(o=t[r-1])==S)return E;return n[r-1];case S:return u=!1,f=!0,s;case x:return l=!0,E;case O:case M:case D:case P:case _:u=!1;case H:return E}}function R(e){var t=e.charCodeAt(0),n=t>>8;return n==0?t>191?g:B[t]:n==5?/[\u0591-\u05f4]/.test(e)?y:g:n==6?/[\u0610-\u061a\u064b-\u065f\u06d6-\u06e4\u06e7-\u06ed]/.test(e)?A:/[\u0660-\u0669\u066b-\u066c]/.test(e)?w:t==1642?L:/[\u06f0-\u06f9]/.test(e)?b:T:n==32&&t<=8287?j[t&255]:n==254?t>=65136?T:E:E}function U(e){return e>="\u064b"&&e<="\u0655"}var r=["\u0621","\u0641"],i=["\u063a","\u064a"],s=0,o=0,u=!1,a=!1,f=!1,l=!1,c=!1,h=!1,p=[[0,3,0,1,0,0,0],[0,3,0,1,2,2,0],[0,3,0,17,2,0,1],[0,3,5,5,4,1,0],[0,3,21,21,4,0,1],[0,3,5,5,4,2,0]],d=[[2,0,1,1,0,1,0],[2,0,1,1,0,2,0],[2,0,2,1,3,2,0],[2,0,2,33,3,1,1]],v=0,m=1,g=0,y=1,b=2,w=3,E=4,S=5,x=6,T=7,N=8,C=9,k=10,L=11,A=12,O=13,M=14,_=15,D=16,P=17,H=18,B=[H,H,H,H,H,H,H,H,H,x,S,x,N,S,H,H,H,H,H,H,H,H,H,H,H,H,H,H,S,S,S,x,N,E,E,L,L,L,E,E,E,E,E,k,C,k,C,C,b,b,b,b,b,b,b,b,b,b,C,E,E,E,E,E,E,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,E,E,E,E,E,E,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,E,E,E,E,H,H,H,H,H,H,S,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,C,E,L,L,L,L,E,E,E,E,g,E,E,H,E,E,L,L,b,b,E,g,E,E,E,b,g,E,E,E,E,E],j=[N,N,N,N,N,N,N,N,N,N,N,H,H,H,g,y,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,N,S,O,M,_,D,P,C,L,L,L,L,L,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,C,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,N];t.L=g,t.R=y,t.EN=b,t.ON_R=3,t.AN=4,t.R_H=5,t.B=6,t.RLE=7,t.DOT="\u00b7",t.doBidiReorder=function(e,n,r){if(e.length<2)return{};var i=e.split(""),o=new Array(i.length),u=new Array(i.length),a=[];s=r?m:v,F(i,a,i.length,n);for(var f=0;fT&&n[f]0&&i[f-1]==="\u0644"&&/\u0622|\u0623|\u0625|\u0627/.test(i[f])&&(a[f-1]=a[f]=t.R_H,f++);i[i.length-1]===t.DOT&&(a[i.length-1]=t.B),i[0]==="\u202b"&&(a[0]=t.RLE);for(var f=0;f=0&&(e=this.session.$docRowCache[n])}return e},this.getSplitIndex=function(){var e=0,t=this.session.$screenRowCache;if(t.length){var n,r=this.session.$getRowCacheIndex(t,this.currentRow);while(this.currentRow-e>0){n=this.session.$getRowCacheIndex(t,this.currentRow-e-1);if(n!==r)break;r=n,e++}}else e=this.currentRow;return e},this.updateRowLine=function(e,t){e===undefined&&(e=this.getDocumentRow());var n=e===this.session.getLength()-1,s=n?this.EOF:this.EOL;this.wrapIndent=0,this.line=this.session.getLine(e),this.isRtlDir=this.line.charAt(0)===this.RLE;if(this.session.$useWrapMode){var o=this.session.$wrapData[e];o&&(t===undefined&&(t=this.getSplitIndex()),t>0&&o.length?(this.wrapIndent=o.indent,this.wrapOffset=this.wrapIndent*this.charWidths[r.L],this.line=tt?this.session.getOverwrite()?e:e-1:t,i=r.getVisualFromLogicalIdx(n,this.bidiMap),s=this.bidiMap.bidiLevels,o=0;!this.session.getOverwrite()&&e<=t&&s[i]%2!==0&&i++;for(var u=0;ut&&s[i]%2===0&&(o+=this.charWidths[s[i]]),this.wrapIndent&&(o+=this.isRtlDir?-1*this.wrapOffset:this.wrapOffset),this.isRtlDir&&(o+=this.rtlLineOffset),o},this.getSelections=function(e,t){var n=this.bidiMap,r=n.bidiLevels,i,s=[],o=0,u=Math.min(e,t)-this.wrapIndent,a=Math.max(e,t)-this.wrapIndent,f=!1,l=!1,c=0;this.wrapIndent&&(o+=this.isRtlDir?-1*this.wrapOffset:this.wrapOffset);for(var h,p=0;p=u&&hn+s/2){n+=s;if(r===i.length-1){s=0;break}s=this.charWidths[i[++r]]}return r>0&&i[r-1]%2!==0&&i[r]%2===0?(e0&&i[r-1]%2===0&&i[r]%2!==0?t=1+(e>n?this.bidiMap.logicalFromVisual[r]:this.bidiMap.logicalFromVisual[r-1]):this.isRtlDir&&r===i.length-1&&s===0&&i[r-1]%2===0||!this.isRtlDir&&r===0&&i[r]%2!==0?t=1+this.bidiMap.logicalFromVisual[r]:(r>0&&i[r-1]%2!==0&&s!==0&&r--,t=this.bidiMap.logicalFromVisual[r]),t===0&&this.isRtlDir&&t++,t+this.wrapIndent}}).call(o.prototype),t.BidiHandler=o}),define("ace/selection",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter","ace/range"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./lib/lang"),s=e("./lib/event_emitter").EventEmitter,o=e("./range").Range,u=function(e){this.session=e,this.doc=e.getDocument(),this.clearSelection(),this.cursor=this.lead=this.doc.createAnchor(0,0),this.anchor=this.doc.createAnchor(0,0),this.$silent=!1;var t=this;this.cursor.on("change",function(e){t.$cursorChanged=!0,t.$silent||t._emit("changeCursor"),!t.$isEmpty&&!t.$silent&&t._emit("changeSelection"),!t.$keepDesiredColumnOnChange&&e.old.column!=e.value.column&&(t.$desiredColumn=null)}),this.anchor.on("change",function(){t.$anchorChanged=!0,!t.$isEmpty&&!t.$silent&&t._emit("changeSelection")})};(function(){r.implement(this,s),this.isEmpty=function(){return this.$isEmpty||this.anchor.row==this.lead.row&&this.anchor.column==this.lead.column},this.isMultiLine=function(){return!this.$isEmpty&&this.anchor.row!=this.cursor.row},this.getCursor=function(){return this.lead.getPosition()},this.setSelectionAnchor=function(e,t){this.$isEmpty=!1,this.anchor.setPosition(e,t)},this.getAnchor=this.getSelectionAnchor=function(){return this.$isEmpty?this.getSelectionLead():this.anchor.getPosition()},this.getSelectionLead=function(){return this.lead.getPosition()},this.isBackwards=function(){var e=this.anchor,t=this.lead;return e.row>t.row||e.row==t.row&&e.column>t.column},this.getRange=function(){var e=this.anchor,t=this.lead;return this.$isEmpty?o.fromPoints(t,t):this.isBackwards()?o.fromPoints(t,e):o.fromPoints(e,t)},this.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._emit("changeSelection"))},this.selectAll=function(){this.$setSelection(0,0,Number.MAX_VALUE,Number.MAX_VALUE)},this.setRange=this.setSelectionRange=function(e,t){var n=t?e.end:e.start,r=t?e.start:e.end;this.$setSelection(n.row,n.column,r.row,r.column)},this.$setSelection=function(e,t,n,r){var i=this.$isEmpty,s=this.inMultiSelectMode;this.$silent=!0,this.$cursorChanged=this.$anchorChanged=!1,this.anchor.setPosition(e,t),this.cursor.setPosition(n,r),this.$isEmpty=!o.comparePoints(this.anchor,this.cursor),this.$silent=!1,this.$cursorChanged&&this._emit("changeCursor"),(this.$cursorChanged||this.$anchorChanged||i!=this.$isEmpty||s)&&this._emit("changeSelection")},this.$moveSelection=function(e){var t=this.lead;this.$isEmpty&&this.setSelectionAnchor(t.row,t.column),e.call(this)},this.selectTo=function(e,t){this.$moveSelection(function(){this.moveCursorTo(e,t)})},this.selectToPosition=function(e){this.$moveSelection(function(){this.moveCursorToPosition(e)})},this.moveTo=function(e,t){this.clearSelection(),this.moveCursorTo(e,t)},this.moveToPosition=function(e){this.clearSelection(),this.moveCursorToPosition(e)},this.selectUp=function(){this.$moveSelection(this.moveCursorUp)},this.selectDown=function(){this.$moveSelection(this.moveCursorDown)},this.selectRight=function(){this.$moveSelection(this.moveCursorRight)},this.selectLeft=function(){this.$moveSelection(this.moveCursorLeft)},this.selectLineStart=function(){this.$moveSelection(this.moveCursorLineStart)},this.selectLineEnd=function(){this.$moveSelection(this.moveCursorLineEnd)},this.selectFileEnd=function(){this.$moveSelection(this.moveCursorFileEnd)},this.selectFileStart=function(){this.$moveSelection(this.moveCursorFileStart)},this.selectWordRight=function(){this.$moveSelection(this.moveCursorWordRight)},this.selectWordLeft=function(){this.$moveSelection(this.moveCursorWordLeft)},this.getWordRange=function(e,t){if(typeof t=="undefined"){var n=e||this.lead;e=n.row,t=n.column}return this.session.getWordRange(e,t)},this.selectWord=function(){this.setSelectionRange(this.getWordRange())},this.selectAWord=function(){var e=this.getCursor(),t=this.session.getAWordRange(e.row,e.column);this.setSelectionRange(t)},this.getLineRange=function(e,t){var n=typeof e=="number"?e:this.lead.row,r,i=this.session.getFoldLine(n);return i?(n=i.start.row,r=i.end.row):r=n,t===!0?new o(n,0,r,this.session.getLine(r).length):new o(n,0,r+1,0)},this.selectLine=function(){this.setSelectionRange(this.getLineRange())},this.moveCursorUp=function(){this.moveCursorBy(-1,0)},this.moveCursorDown=function(){this.moveCursorBy(1,0)},this.wouldMoveIntoSoftTab=function(e,t,n){var r=e.column,i=e.column+t;return n<0&&(r=e.column-t,i=e.column),this.session.isTabStop(e)&&this.doc.getLine(e.row).slice(r,i).split(" ").length-1==t},this.moveCursorLeft=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,-1))this.moveCursorTo(t.start.row,t.start.column);else if(e.column===0)e.row>0&&this.moveCursorTo(e.row-1,this.doc.getLine(e.row-1).length);else{var n=this.session.getTabSize();this.wouldMoveIntoSoftTab(e,n,-1)&&!this.session.getNavigateWithinSoftTabs()?this.moveCursorBy(0,-n):this.moveCursorBy(0,-1)}},this.moveCursorRight=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,1))this.moveCursorTo(t.end.row,t.end.column);else if(this.lead.column==this.doc.getLine(this.lead.row).length)this.lead.row0&&(t.column=r)}}this.moveCursorTo(t.row,t.column)},this.moveCursorFileEnd=function(){var e=this.doc.getLength()-1,t=this.doc.getLine(e).length;this.moveCursorTo(e,t)},this.moveCursorFileStart=function(){this.moveCursorTo(0,0)},this.moveCursorLongWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t);this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;var i=this.session.getFoldAt(e,t,1);if(i){this.moveCursorTo(i.end.row,i.end.column);return}this.session.nonTokenRe.exec(r)&&(t+=this.session.nonTokenRe.lastIndex,this.session.nonTokenRe.lastIndex=0,r=n.substring(t));if(t>=n.length){this.moveCursorTo(e,n.length),this.moveCursorRight(),e0&&this.moveCursorWordLeft();return}this.session.tokenRe.exec(s)&&(t-=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0),this.moveCursorTo(e,t)},this.$shortWordEndIndex=function(e){var t=0,n,r=/\s/,i=this.session.tokenRe;i.lastIndex=0;if(this.session.tokenRe.exec(e))t=this.session.tokenRe.lastIndex;else{while((n=e[t])&&r.test(n))t++;if(t<1){i.lastIndex=0;while((n=e[t])&&!i.test(n)){i.lastIndex=0,t++;if(r.test(n)){if(t>2){t--;break}while((n=e[t])&&r.test(n))t++;if(t>2)break}}}}return i.lastIndex=0,t},this.moveCursorShortWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t),i=this.session.getFoldAt(e,t,1);if(i)return this.moveCursorTo(i.end.row,i.end.column);if(t==n.length){var s=this.doc.getLength();do e++,r=this.doc.getLine(e);while(e0&&/^\s*$/.test(r));t=r.length,/\s+$/.test(r)||(r="")}var s=i.stringReverse(r),o=this.$shortWordEndIndex(s);return this.moveCursorTo(e,t-o)},this.moveCursorWordRight=function(){this.session.$selectLongWords?this.moveCursorLongWordRight():this.moveCursorShortWordRight()},this.moveCursorWordLeft=function(){this.session.$selectLongWords?this.moveCursorLongWordLeft():this.moveCursorShortWordLeft()},this.moveCursorBy=function(e,t){var n=this.session.documentToScreenPosition(this.lead.row,this.lead.column),r;t===0&&(e!==0&&(this.session.$bidiHandler.isBidiRow(n.row,this.lead.row)?(r=this.session.$bidiHandler.getPosLeft(n.column),n.column=Math.round(r/this.session.$bidiHandler.charWidths[0])):r=n.column*this.session.$bidiHandler.charWidths[0]),this.$desiredColumn?n.column=this.$desiredColumn:this.$desiredColumn=n.column);var i=this.session.screenToDocumentPosition(n.row+e,n.column,r);e!==0&&t===0&&i.row===this.lead.row&&i.column===this.lead.column&&this.session.lineWidgets&&this.session.lineWidgets[i.row]&&(i.row>0||e>0)&&i.row++,this.moveCursorTo(i.row,i.column+t,t===0)},this.moveCursorToPosition=function(e){this.moveCursorTo(e.row,e.column)},this.moveCursorTo=function(e,t,n){var r=this.session.getFoldAt(e,t,1);r&&(e=r.start.row,t=r.start.column),this.$keepDesiredColumnOnChange=!0;var i=this.session.getLine(e);/[\uDC00-\uDFFF]/.test(i.charAt(t))&&i.charAt(t-1)&&(this.lead.row==e&&this.lead.column==t+1?t-=1:t+=1),this.lead.setPosition(e,t),this.$keepDesiredColumnOnChange=!1,n||(this.$desiredColumn=null)},this.moveCursorToScreen=function(e,t,n){var r=this.session.screenToDocumentPosition(e,t);this.moveCursorTo(r.row,r.column,n)},this.detach=function(){this.lead.detach(),this.anchor.detach(),this.session=this.doc=null},this.fromOrientedRange=function(e){this.setSelectionRange(e,e.cursor==e.start),this.$desiredColumn=e.desiredColumn||this.$desiredColumn},this.toOrientedRange=function(e){var t=this.getRange();return e?(e.start.column=t.start.column,e.start.row=t.start.row,e.end.column=t.end.column,e.end.row=t.end.row):e=t,e.cursor=this.isBackwards()?e.start:e.end,e.desiredColumn=this.$desiredColumn,e},this.getRangeOfMovements=function(e){var t=this.getCursor();try{e(this);var n=this.getCursor();return o.fromPoints(t,n)}catch(r){return o.fromPoints(t,t)}finally{this.moveCursorToPosition(t)}},this.toJSON=function(){if(this.rangeCount)var e=this.ranges.map(function(e){var t=e.clone();return t.isBackwards=e.cursor==e.start,t});else{var e=this.getRange();e.isBackwards=this.isBackwards()}return e},this.fromJSON=function(e){if(e.start==undefined){if(this.rangeList){this.toSingleRange(e[0]);for(var t=e.length;t--;){var n=o.fromPoints(e[t].start,e[t].end);e[t].isBackwards&&(n.cursor=n.start),this.addRange(n,!0)}return}e=e[0]}this.rangeList&&this.toSingleRange(e),this.setSelectionRange(e,e.isBackwards)},this.isEqual=function(e){if((e.length||this.rangeCount)&&e.length!=this.rangeCount)return!1;if(!e.length||!this.ranges)return this.getRange().isEqual(e);for(var t=this.ranges.length;t--;)if(!this.ranges[t].isEqual(e[t]))return!1;return!0}}).call(u.prototype),t.Selection=u}),define("ace/tokenizer",["require","exports","module","ace/config"],function(e,t,n){"use strict";var r=e("./config"),i=2e3,s=function(e){this.states=e,this.regExps={},this.matchMappings={};for(var t in this.states){var n=this.states[t],r=[],i=0,s=this.matchMappings[t]={defaultToken:"text"},o="g",u=[];for(var a=0;a1?f.onMatch=this.$applyToken:f.onMatch=f.token),c>1&&(/\\\d/.test(f.regex)?l=f.regex.replace(/\\([0-9]+)/g,function(e,t){return"\\"+(parseInt(t,10)+i+1)}):(c=1,l=this.removeCapturingGroups(f.regex)),!f.splitRegex&&typeof f.token!="string"&&u.push(f)),s[i]=a,i+=c,r.push(l),f.onMatch||(f.onMatch=null)}r.length||(s[0]=0,r.push("$")),u.forEach(function(e){e.splitRegex=this.createSplitterRegexp(e.regex,o)},this),this.regExps[t]=new RegExp("("+r.join(")|(")+")|($)",o)}};(function(){this.$setMaxTokenCount=function(e){i=e|0},this.$applyToken=function(e){var t=this.splitRegex.exec(e).slice(1),n=this.token.apply(this,t);if(typeof n=="string")return[{type:n,value:e}];var r=[];for(var i=0,s=n.length;il){var g=e.substring(l,m-v.length);h.type==p?h.value+=g:(h.type&&f.push(h),h={type:p,value:g})}for(var y=0;yi){c>2*e.length&&this.reportError("infinite loop with in ace tokenizer",{startState:t,line:e});while(l1&&n[0]!==r&&n.unshift("#tmp",r),{tokens:f,state:n.length?n:r}},this.reportError=r.reportError}).call(s.prototype),t.Tokenizer=s}),define("ace/mode/text_highlight_rules",["require","exports","module","ace/lib/lang"],function(e,t,n){"use strict";var r=e("../lib/lang"),i=function(){this.$rules={start:[{token:"empty_line",regex:"^$"},{defaultToken:"text"}]}};(function(){this.addRules=function(e,t){if(!t){for(var n in e)this.$rules[n]=e[n];return}for(var n in e){var r=e[n];for(var i=0;i=this.$rowTokens.length){this.$row+=1,e||(e=this.$session.getLength());if(this.$row>=e)return this.$row=e-1,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=0}return this.$rowTokens[this.$tokenIndex]},this.getCurrentToken=function(){return this.$rowTokens[this.$tokenIndex]},this.getCurrentTokenRow=function(){return this.$row},this.getCurrentTokenColumn=function(){var e=this.$rowTokens,t=this.$tokenIndex,n=e[t].start;if(n!==undefined)return n;n=0;while(t>0)t-=1,n+=e[t].value.length;return n},this.getCurrentTokenPosition=function(){return{row:this.$row,column:this.getCurrentTokenColumn()}},this.getCurrentTokenRange=function(){var e=this.$rowTokens[this.$tokenIndex],t=this.getCurrentTokenColumn();return new r(this.$row,t,this.$row,t+e.value.length)}}).call(i.prototype),t.TokenIterator=i}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f,l={},c={'"':'"',"'":"'"},h=function(e){var t=-1;e.multiSelect&&(t=e.selection.index,l.rangeCount!=e.multiSelect.rangeCount&&(l={rangeCount:e.multiSelect.rangeCount}));if(l[t])return f=l[t];f=l[t]={autoInsertedBrackets:0,autoInsertedRow:-1,autoInsertedLineEnd:"",maybeInsertedBrackets:0,maybeInsertedRow:-1,maybeInsertedLineStart:"",maybeInsertedLineEnd:""}},p=function(e,t,n,r){var i=e.end.row-e.start.row;return{text:n+t+r,selection:[0,e.start.column+1,i,e.end.column+(i?0:1)]}},d=function(e){this.add("braces","insertion",function(t,n,r,i,s){var u=r.getCursorPosition(),a=i.doc.getLine(u.row);if(s=="{"){h(r);var l=r.getSelectionRange(),c=i.doc.getTextRange(l);if(c!==""&&c!=="{"&&r.getWrapBehavioursEnabled())return p(l,c,"{","}");if(d.isSaneInsertion(r,i))return/[\]\}\)]/.test(a[u.column])||r.inMultiSelectMode||e&&e.braces?(d.recordAutoInsert(r,i,"}"),{text:"{}",selection:[1,1]}):(d.recordMaybeInsert(r,i,"{"),{text:"{",selection:[1,1]})}else if(s=="}"){h(r);var v=a.substring(u.column,u.column+1);if(v=="}"){var m=i.$findOpeningBracket("}",{column:u.column+1,row:u.row});if(m!==null&&d.isAutoInsertedClosing(u,a,s))return d.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else{if(s=="\n"||s=="\r\n"){h(r);var g="";d.isMaybeInsertedClosing(u,a)&&(g=o.stringRepeat("}",f.maybeInsertedBrackets),d.clearMaybeInsertedClosing());var v=a.substring(u.column,u.column+1);if(v==="}"){var y=i.findMatchingBracket({row:u.row,column:u.column+1},"}");if(!y)return null;var b=this.$getIndent(i.getLine(y.row))}else{if(!g){d.clearMaybeInsertedClosing();return}var b=this.$getIndent(a)}var w=b+i.getTabString();return{text:"\n"+w+"\n"+b+g,selection:[1,w.length,1,w.length]}}d.clearMaybeInsertedClosing()}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;f.maybeInsertedBrackets--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){h(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return p(s,o,"(",")");if(d.isSaneInsertion(n,r))return d.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){h(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&d.isAutoInsertedClosing(u,a,i))return d.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){h(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return p(s,o,"[","]");if(d.isSaneInsertion(n,r))return d.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){h(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&d.isAutoInsertedClosing(u,a,i))return d.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){var s=r.$mode.$quotes||c;if(i.length==1&&s[i]){if(this.lineCommentStart&&this.lineCommentStart.indexOf(i)!=-1)return;h(n);var o=i,u=n.getSelectionRange(),a=r.doc.getTextRange(u);if(a!==""&&(a.length!=1||!s[a])&&n.getWrapBehavioursEnabled())return p(u,a,o,o);if(!a){var f=n.getCursorPosition(),l=r.doc.getLine(f.row),d=l.substring(f.column-1,f.column),v=l.substring(f.column,f.column+1),m=r.getTokenAt(f.row,f.column),g=r.getTokenAt(f.row,f.column+1);if(d=="\\"&&m&&/escape/.test(m.type))return null;var y=m&&/string|escape/.test(m.type),b=!g||/string|escape/.test(g.type),w;if(v==o)w=y!==b,w&&/string\.end/.test(g.type)&&(w=!1);else{if(y&&!b)return null;if(y&&b)return null;var E=r.$mode.tokenRe;E.lastIndex=0;var S=E.test(d);E.lastIndex=0;var x=E.test(d);if(S||x)return null;if(v&&!/[\s;,.})\]\\]/.test(v))return null;w=!0}return{text:w?o+o:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.$mode.$quotes||c,o=r.doc.getTextRange(i);if(!i.isMultiLine()&&s.hasOwnProperty(o)){h(n);var u=r.doc.getLine(i.start.row),a=u.substring(i.start.column+1,i.start.column+2);if(a==o)return i.end.column++,i}})};d.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},d.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},d.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,f.autoInsertedLineEnd[0])||(f.autoInsertedBrackets=0),f.autoInsertedRow=r.row,f.autoInsertedLineEnd=n+i.substr(r.column),f.autoInsertedBrackets++},d.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(f.maybeInsertedBrackets=0),f.maybeInsertedRow=r.row,f.maybeInsertedLineStart=i.substr(0,r.column)+n,f.maybeInsertedLineEnd=i.substr(r.column),f.maybeInsertedBrackets++},d.isAutoInsertedClosing=function(e,t,n){return f.autoInsertedBrackets>0&&e.row===f.autoInsertedRow&&n===f.autoInsertedLineEnd[0]&&t.substr(e.column)===f.autoInsertedLineEnd},d.isMaybeInsertedClosing=function(e,t){return f.maybeInsertedBrackets>0&&e.row===f.maybeInsertedRow&&t.substr(e.column)===f.maybeInsertedLineEnd&&t.substr(0,e.column)==f.maybeInsertedLineStart},d.popAutoInsertedClosing=function(){f.autoInsertedLineEnd=f.autoInsertedLineEnd.substr(1),f.autoInsertedBrackets--},d.clearMaybeInsertedClosing=function(){f&&(f.maybeInsertedBrackets=0,f.maybeInsertedRow=-1)},r.inherits(d,i),t.CstyleBehaviour=d}),define("ace/unicode",["require","exports","module"],function(e,t,n){"use strict";var r=[48,9,8,25,5,0,2,25,48,0,11,0,5,0,6,22,2,30,2,457,5,11,15,4,8,0,2,0,18,116,2,1,3,3,9,0,2,2,2,0,2,19,2,82,2,138,2,4,3,155,12,37,3,0,8,38,10,44,2,0,2,1,2,1,2,0,9,26,6,2,30,10,7,61,2,9,5,101,2,7,3,9,2,18,3,0,17,58,3,100,15,53,5,0,6,45,211,57,3,18,2,5,3,11,3,9,2,1,7,6,2,2,2,7,3,1,3,21,2,6,2,0,4,3,3,8,3,1,3,3,9,0,5,1,2,4,3,11,16,2,2,5,5,1,3,21,2,6,2,1,2,1,2,1,3,0,2,4,5,1,3,2,4,0,8,3,2,0,8,15,12,2,2,8,2,2,2,21,2,6,2,1,2,4,3,9,2,2,2,2,3,0,16,3,3,9,18,2,2,7,3,1,3,21,2,6,2,1,2,4,3,8,3,1,3,2,9,1,5,1,2,4,3,9,2,0,17,1,2,5,4,2,2,3,4,1,2,0,2,1,4,1,4,2,4,11,5,4,4,2,2,3,3,0,7,0,15,9,18,2,2,7,2,2,2,22,2,9,2,4,4,7,2,2,2,3,8,1,2,1,7,3,3,9,19,1,2,7,2,2,2,22,2,9,2,4,3,8,2,2,2,3,8,1,8,0,2,3,3,9,19,1,2,7,2,2,2,22,2,15,4,7,2,2,2,3,10,0,9,3,3,9,11,5,3,1,2,17,4,23,2,8,2,0,3,6,4,0,5,5,2,0,2,7,19,1,14,57,6,14,2,9,40,1,2,0,3,1,2,0,3,0,7,3,2,6,2,2,2,0,2,0,3,1,2,12,2,2,3,4,2,0,2,5,3,9,3,1,35,0,24,1,7,9,12,0,2,0,2,0,5,9,2,35,5,19,2,5,5,7,2,35,10,0,58,73,7,77,3,37,11,42,2,0,4,328,2,3,3,6,2,0,2,3,3,40,2,3,3,32,2,3,3,6,2,0,2,3,3,14,2,56,2,3,3,66,5,0,33,15,17,84,13,619,3,16,2,25,6,74,22,12,2,6,12,20,12,19,13,12,2,2,2,1,13,51,3,29,4,0,5,1,3,9,34,2,3,9,7,87,9,42,6,69,11,28,4,11,5,11,11,39,3,4,12,43,5,25,7,10,38,27,5,62,2,28,3,10,7,9,14,0,89,75,5,9,18,8,13,42,4,11,71,55,9,9,4,48,83,2,2,30,14,230,23,280,3,5,3,37,3,5,3,7,2,0,2,0,2,0,2,30,3,52,2,6,2,0,4,2,2,6,4,3,3,5,5,12,6,2,2,6,67,1,20,0,29,0,14,0,17,4,60,12,5,0,4,11,18,0,5,0,3,9,2,0,4,4,7,0,2,0,2,0,2,3,2,10,3,3,6,4,5,0,53,1,2684,46,2,46,2,132,7,6,15,37,11,53,10,0,17,22,10,6,2,6,2,6,2,6,2,6,2,6,2,6,2,6,2,31,48,0,470,1,36,5,2,4,6,1,5,85,3,1,3,2,2,89,2,3,6,40,4,93,18,23,57,15,513,6581,75,20939,53,1164,68,45,3,268,4,27,21,31,3,13,13,1,2,24,9,69,11,1,38,8,3,102,3,1,111,44,25,51,13,68,12,9,7,23,4,0,5,45,3,35,13,28,4,64,15,10,39,54,10,13,3,9,7,22,4,1,5,66,25,2,227,42,2,1,3,9,7,11171,13,22,5,48,8453,301,3,61,3,105,39,6,13,4,6,11,2,12,2,4,2,0,2,1,2,1,2,107,34,362,19,63,3,53,41,11,5,15,17,6,13,1,25,2,33,4,2,134,20,9,8,25,5,0,2,25,12,88,4,5,3,5,3,5,3,2],i=0,s=[];for(var o=0;o2?r%f!=f-1:r%f==0}}var E=Infinity;w(function(e,t){var n=e.search(/\S/);n!==-1?(ne.length&&(E=e.length)}),u==Infinity&&(u=E,s=!1,o=!1),l&&u%f!=0&&(u=Math.floor(u/f)*f),w(o?m:v)},this.toggleBlockComment=function(e,t,n,r){var i=this.blockComment;if(!i)return;!i.start&&i[0]&&(i=i[0]);var s=new f(t,r.row,r.column),o=s.getCurrentToken(),u=t.selection,a=t.selection.toOrientedRange(),c,h;if(o&&/comment/.test(o.type)){var p,d;while(o&&/comment/.test(o.type)){var v=o.value.indexOf(i.start);if(v!=-1){var m=s.getCurrentTokenRow(),g=s.getCurrentTokenColumn()+v;p=new l(m,g,m,g+i.start.length);break}o=s.stepBackward()}var s=new f(t,r.row,r.column),o=s.getCurrentToken();while(o&&/comment/.test(o.type)){var v=o.value.indexOf(i.end);if(v!=-1){var m=s.getCurrentTokenRow(),g=s.getCurrentTokenColumn()+v;d=new l(m,g,m,g+i.end.length);break}o=s.stepForward()}d&&t.remove(d),p&&(t.remove(p),c=p.start.row,h=-i.start.length)}else h=i.start.length,c=n.start.row,t.insert(n.end,i.end),t.insert(n.start,i.start);a.start.row==c&&(a.start.column+=h),a.end.row==c&&(a.end.column+=h),t.selection.fromOrientedRange(a)},this.getNextLineIndent=function(e,t,n){return this.$getIndent(t)},this.checkOutdent=function(e,t,n){return!1},this.autoOutdent=function(e,t,n){},this.$getIndent=function(e){return e.match(/^\s*/)[0]},this.createWorker=function(e){return null},this.createModeDelegates=function(e){this.$embeds=[],this.$modes={};for(var t in e)if(e[t]){var n=e[t],i=n.prototype.$id,s=r.$modes[i];s||(r.$modes[i]=s=new n),r.$modes[t]||(r.$modes[t]=s),this.$embeds.push(t),this.$modes[t]=s}var o=["toggleBlockComment","toggleCommentLines","getNextLineIndent","checkOutdent","autoOutdent","transformAction","getCompletions"];for(var t=0;t=0&&t.row=0&&t.column<=e[t.row].length}function s(e,t){t.action!="insert"&&t.action!="remove"&&r(t,"delta.action must be 'insert' or 'remove'"),t.lines instanceof Array||r(t,"delta.lines must be an Array"),(!t.start||!t.end)&&r(t,"delta.start/end must be an present");var n=t.start;i(e,t.start)||r(t,"delta.start must be contained in document");var s=t.end;t.action=="remove"&&!i(e,s)&&r(t,"delta.end must contained in document for 'remove' actions");var o=s.row-n.row,u=s.column-(o==0?n.column:0);(o!=t.lines.length-1||t.lines[o].length!=u)&&r(t,"delta.range must match delta lines")}t.applyDelta=function(e,t,n){var r=t.start.row,i=t.start.column,s=e[r]||"";switch(t.action){case"insert":var o=t.lines;if(o.length===1)e[r]=s.substring(0,i)+t.lines[0]+s.substring(i);else{var u=[r,1].concat(t.lines);e.splice.apply(e,u),e[r]=s.substring(0,i)+e[r],e[r+t.lines.length-1]+=s.substring(i)}break;case"remove":var a=t.end.column,f=t.end.row;r===f?e[r]=s.substring(0,i)+s.substring(a):e.splice(r,f-r+1,s.substring(0,i)+e[f].substring(a))}}}),define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./lib/event_emitter").EventEmitter,s=t.Anchor=function(e,t,n){this.$onChange=this.onChange.bind(this),this.attach(e),typeof n=="undefined"?this.setPosition(t.row,t.column):this.setPosition(t,n)};(function(){function e(e,t,n){var r=n?e.column<=t.column:e.columnthis.row)return;var n=t(e,{row:this.row,column:this.column},this.$insertRight);this.setPosition(n.row,n.column,!0)},this.setPosition=function(e,t,n){var r;n?r={row:e,column:t}:r=this.$clipPositionToDocument(e,t);if(this.row==r.row&&this.column==r.column)return;var i={row:this.row,column:this.column};this.row=r.row,this.column=r.column,this._signal("change",{old:i,value:r})},this.detach=function(){this.document.removeEventListener("change",this.$onChange)},this.attach=function(e){this.document=e||this.document,this.document.on("change",this.$onChange)},this.$clipPositionToDocument=function(e,t){var n={};return e>=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./apply_delta").applyDelta,s=e("./lib/event_emitter").EventEmitter,o=e("./range").Range,u=e("./anchor").Anchor,a=function(e){this.$lines=[""],e.length===0?this.$lines=[""]:Array.isArray(e)?this.insertMergedLines({row:0,column:0},e):this.insert({row:0,column:0},e)};(function(){r.implement(this,s),this.setValue=function(e){var t=this.getLength()-1;this.remove(new o(0,0,t,this.getLine(t).length)),this.insert({row:0,column:0},e)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(e,t){return new u(this,e,t)},"aaa".split(/a/).length===0?this.$split=function(e){return e.replace(/\r\n|\r/g,"\n").split("\n")}:this.$split=function(e){return e.split(/\r\n|\r|\n/)},this.$detectNewLine=function(e){var t=e.match(/^.*?(\r\n|\r|\n)/m);this.$autoNewLine=t?t[1]:"\n",this._signal("changeNewLineMode")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case"windows":return"\r\n";case"unix":return"\n";default:return this.$autoNewLine||"\n"}},this.$autoNewLine="",this.$newLineMode="auto",this.setNewLineMode=function(e){if(this.$newLineMode===e)return;this.$newLineMode=e,this._signal("changeNewLineMode")},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(e){return e=="\r\n"||e=="\r"||e=="\n"},this.getLine=function(e){return this.$lines[e]||""},this.getLines=function(e,t){return this.$lines.slice(e,t+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(e){return this.getLinesForRange(e).join(this.getNewLineCharacter())},this.getLinesForRange=function(e){var t;if(e.start.row===e.end.row)t=[this.getLine(e.start.row).substring(e.start.column,e.end.column)];else{t=this.getLines(e.start.row,e.end.row),t[0]=(t[0]||"").substring(e.start.column);var n=t.length-1;e.end.row-e.start.row==n&&(t[n]=t[n].substring(0,e.end.column))}return t},this.insertLines=function(e,t){return console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."),this.insertFullLines(e,t)},this.removeLines=function(e,t){return console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."),this.removeFullLines(e,t)},this.insertNewLine=function(e){return console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead."),this.insertMergedLines(e,["",""])},this.insert=function(e,t){return this.getLength()<=1&&this.$detectNewLine(t),this.insertMergedLines(e,this.$split(t))},this.insertInLine=function(e,t){var n=this.clippedPos(e.row,e.column),r=this.pos(e.row,e.column+t.length);return this.applyDelta({start:n,end:r,action:"insert",lines:[t]},!0),this.clonePos(r)},this.clippedPos=function(e,t){var n=this.getLength();e===undefined?e=n:e<0?e=0:e>=n&&(e=n-1,t=undefined);var r=this.getLine(e);return t==undefined&&(t=r.length),t=Math.min(Math.max(t,0),r.length),{row:e,column:t}},this.clonePos=function(e){return{row:e.row,column:e.column}},this.pos=function(e,t){return{row:e,column:t}},this.$clipPosition=function(e){var t=this.getLength();return e.row>=t?(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length):(e.row=Math.max(0,e.row),e.column=Math.min(Math.max(e.column,0),this.getLine(e.row).length)),e},this.insertFullLines=function(e,t){e=Math.min(Math.max(e,0),this.getLength());var n=0;e0,r=t=0&&this.applyDelta({start:this.pos(e,this.getLine(e).length),end:this.pos(e+1,0),action:"remove",lines:["",""]})},this.replace=function(e,t){e instanceof o||(e=o.fromPoints(e.start,e.end));if(t.length===0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);var n;return t?n=this.insert(e.start,t):n=e.start,n},this.applyDeltas=function(e){for(var t=0;t=0;t--)this.revertDelta(e[t])},this.applyDelta=function(e,t){var n=e.action=="insert";if(n?e.lines.length<=1&&!e.lines[0]:!o.comparePoints(e.start,e.end))return;n&&e.lines.length>2e4?this.$splitAndapplyLargeDelta(e,2e4):(i(this.$lines,e,t),this._signal("change",e))},this.$splitAndapplyLargeDelta=function(e,t){var n=e.lines,r=n.length-t+1,i=e.start.row,s=e.start.column;for(var o=0,u=0;o20){n.running=setTimeout(n.$worker,20);break}}n.currentLine=t,r==-1&&(r=t),s<=r&&n.fireUpdateEvent(s,r)}};(function(){r.implement(this,i),this.setTokenizer=function(e){this.tokenizer=e,this.lines=[],this.states=[],this.start(0)},this.setDocument=function(e){this.doc=e,this.lines=[],this.states=[],this.stop()},this.fireUpdateEvent=function(e,t){var n={first:e,last:t};this._signal("update",{data:n})},this.start=function(e){this.currentLine=Math.min(e||0,this.currentLine,this.doc.getLength()),this.lines.splice(this.currentLine,this.lines.length),this.states.splice(this.currentLine,this.states.length),this.stop(),this.running=setTimeout(this.$worker,700)},this.scheduleStart=function(){this.running||(this.running=setTimeout(this.$worker,700))},this.$updateOnChange=function(e){var t=e.start.row,n=e.end.row-t;if(n===0)this.lines[t]=null;else if(e.action=="remove")this.lines.splice(t,n+1,null),this.states.splice(t,n+1,null);else{var r=Array(n+1);r.unshift(t,1),this.lines.splice.apply(this.lines,r),this.states.splice.apply(this.states,r)}this.currentLine=Math.min(t,this.currentLine,this.doc.getLength()),this.stop()},this.stop=function(){this.running&&clearTimeout(this.running),this.running=!1},this.getTokens=function(e){return this.lines[e]||this.$tokenizeRow(e)},this.getState=function(e){return this.currentLine==e&&this.$tokenizeRow(e),this.states[e]||"start"},this.$tokenizeRow=function(e){var t=this.doc.getLine(e),n=this.states[e-1],r=this.tokenizer.getLineTokens(t,n,e);return this.states[e]+""!=r.state+""?(this.states[e]=r.state,this.lines[e+1]=null,this.currentLine>e+1&&(this.currentLine=e+1)):this.currentLine==e&&(this.currentLine=e+1),this.lines[e]=r.tokens}}).call(s.prototype),t.BackgroundTokenizer=s}),define("ace/search_highlight",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(e,t,n){"use strict";var r=e("./lib/lang"),i=e("./lib/oop"),s=e("./range").Range,o=function(e,t,n){this.setRegexp(e),this.clazz=t,this.type=n||"text"};(function(){this.MAX_RANGES=500,this.setRegexp=function(e){if(this.regExp+""==e+"")return;this.regExp=e,this.cache=[]},this.update=function(e,t,n,i){if(!this.regExp)return;var o=i.firstRow,u=i.lastRow;for(var a=o;a<=u;a++){var f=this.cache[a];f==null&&(f=r.getMatchOffsets(n.getLine(a),this.regExp),f.length>this.MAX_RANGES&&(f=f.slice(0,this.MAX_RANGES)),f=f.map(function(e){return new s(a,e.offset,a,e.offset+e.length)}),this.cache[a]=f.length?f:"");for(var l=f.length;l--;)t.drawSingleLineMarker(e,f[l].toScreenRange(n),this.clazz,i)}}}).call(o.prototype),t.SearchHighlight=o}),define("ace/edit_session/fold_line",["require","exports","module","ace/range"],function(e,t,n){"use strict";function i(e,t){this.foldData=e,Array.isArray(t)?this.folds=t:t=this.folds=[t];var n=t[t.length-1];this.range=new r(t[0].start.row,t[0].start.column,n.end.row,n.end.column),this.start=this.range.start,this.end=this.range.end,this.folds.forEach(function(e){e.setFoldLine(this)},this)}var r=e("../range").Range;(function(){this.shiftRow=function(e){this.start.row+=e,this.end.row+=e,this.folds.forEach(function(t){t.start.row+=e,t.end.row+=e})},this.addFold=function(e){if(e.sameRow){if(e.start.rowthis.endRow)throw new Error("Can't add a fold to this FoldLine as it has no connection");this.folds.push(e),this.folds.sort(function(e,t){return-e.range.compareEnd(t.start.row,t.start.column)}),this.range.compareEnd(e.start.row,e.start.column)>0?(this.end.row=e.end.row,this.end.column=e.end.column):this.range.compareStart(e.end.row,e.end.column)<0&&(this.start.row=e.start.row,this.start.column=e.start.column)}else if(e.start.row==this.end.row)this.folds.push(e),this.end.row=e.end.row,this.end.column=e.end.column;else{if(e.end.row!=this.start.row)throw new Error("Trying to add fold to FoldRow that doesn't have a matching row");this.folds.unshift(e),this.start.row=e.start.row,this.start.column=e.start.column}e.foldLine=this},this.containsRow=function(e){return e>=this.start.row&&e<=this.end.row},this.walk=function(e,t,n){var r=0,i=this.folds,s,o,u,a=!0;t==null&&(t=this.end.row,n=this.end.column);for(var f=0;f0)continue;var a=i(e,o.start);return u===0?t&&a!==0?-s-2:s:a>0||a===0&&!t?s:-s-1}return-s-1},this.add=function(e){var t=!e.isEmpty(),n=this.pointIndex(e.start,t);n<0&&(n=-n-1);var r=this.pointIndex(e.end,t,n);return r<0?r=-r-1:r++,this.ranges.splice(n,r-n,e)},this.addList=function(e){var t=[];for(var n=e.length;n--;)t.push.apply(t,this.add(e[n]));return t},this.substractPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges.splice(t,1)},this.merge=function(){var e=[],t=this.ranges;t=t.sort(function(e,t){return i(e.start,t.start)});var n=t[0],r;for(var s=1;s=0},this.containsPoint=function(e){return this.pointIndex(e)>=0},this.rangeAtPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges[t]},this.clipRows=function(e,t){var n=this.ranges;if(n[0].start.row>t||n[n.length-1].start.row=r)break}if(e.action=="insert"){var f=i-r,l=-t.column+n.column;for(;or)break;a.start.row==r&&a.start.column>=t.column&&(a.start.column!=t.column||!this.$insertRight)&&(a.start.column+=l,a.start.row+=f);if(a.end.row==r&&a.end.column>=t.column){if(a.end.column==t.column&&this.$insertRight)continue;a.end.column==t.column&&l>0&&oa.start.column&&a.end.column==s[o+1].start.column&&(a.end.column-=l),a.end.column+=l,a.end.row+=f}}}else{var f=r-i,l=t.column-n.column;for(;oi)break;a.end.rowt.column)a.end.column=t.column,a.end.row=t.row}else a.end.column+=l,a.end.row+=f;if(a.start.row==i)if(a.start.column<=n.column){if(f||a.start.column>t.column)a.start.column=t.column,a.start.row=t.row}else a.start.column+=l,a.start.row+=f}}if(f!=0&&o=e)return i;if(i.end.row>e)return null}return null},this.getNextFoldLine=function(e,t){var n=this.$foldData,r=0;t&&(r=n.indexOf(t)),r==-1&&(r=0);for(r;r=e)return i}return null},this.getFoldedRowCount=function(e,t){var n=this.$foldData,r=t-e+1;for(var i=0;i=t){u=e?r-=t-u:r=0);break}o>=e&&(u>=e?r-=o-u:r-=o-e+1)}return r},this.$addFoldLine=function(e){return this.$foldData.push(e),this.$foldData.sort(function(e,t){return e.start.row-t.start.row}),e},this.addFold=function(e,t){var n=this.$foldData,r=!1,o;e instanceof s?o=e:(o=new s(t,e),o.collapseChildren=t.collapseChildren),this.$clipRangeToDocument(o.range);var u=o.start.row,a=o.start.column,f=o.end.row,l=o.end.column;if(u0&&(this.removeFolds(p),p.forEach(function(e){o.addSubFold(e)}));for(var d=0;d0&&this.foldAll(e.start.row+1,e.end.row,e.collapseChildren-1),e.subFolds=[]},this.expandFolds=function(e){e.forEach(function(e){this.expandFold(e)},this)},this.unfold=function(e,t){var n,i;e==null?(n=new r(0,0,this.getLength(),0),t=!0):typeof e=="number"?n=new r(e,0,e,this.getLine(e).length):"row"in e?n=r.fromPoints(e,e):n=e,i=this.getFoldsInRangeList(n);if(t)this.removeFolds(i);else{var s=i;while(s.length)this.expandFolds(s),s=this.getFoldsInRangeList(n)}if(i.length)return i},this.isRowFolded=function(e,t){return!!this.getFoldLine(e,t)},this.getRowFoldEnd=function(e,t){var n=this.getFoldLine(e,t);return n?n.end.row:e},this.getRowFoldStart=function(e,t){var n=this.getFoldLine(e,t);return n?n.start.row:e},this.getFoldDisplayLine=function(e,t,n,r,i){r==null&&(r=e.start.row),i==null&&(i=0),t==null&&(t=e.end.row),n==null&&(n=this.getLine(t).length);var s=this.doc,o="";return e.walk(function(e,t,n,u){if(tl)break}while(s&&a.test(s.type));s=i.stepBackward()}else s=i.getCurrentToken();return f.end.row=i.getCurrentTokenRow(),f.end.column=i.getCurrentTokenColumn()+s.value.length-2,f}},this.foldAll=function(e,t,n){n==undefined&&(n=1e5);var r=this.foldWidgets;if(!r)return;t=t||this.getLength(),e=e||0;for(var i=e;i=e){i=s.end.row;try{var o=this.addFold("...",s);o&&(o.collapseChildren=n)}catch(u){}}}},this.$foldStyles={manual:1,markbegin:1,markbeginend:1},this.$foldStyle="markbegin",this.setFoldStyle=function(e){if(!this.$foldStyles[e])throw new Error("invalid fold style: "+e+"["+Object.keys(this.$foldStyles).join(", ")+"]");if(this.$foldStyle==e)return;this.$foldStyle=e,e=="manual"&&this.unfold();var t=this.$foldMode;this.$setFolding(null),this.$setFolding(t)},this.$setFolding=function(e){if(this.$foldMode==e)return;this.$foldMode=e,this.off("change",this.$updateFoldWidgets),this.off("tokenizerUpdate",this.$tokenizerUpdateFoldWidgets),this._signal("changeAnnotation");if(!e||this.$foldStyle=="manual"){this.foldWidgets=null;return}this.foldWidgets=[],this.getFoldWidget=e.getFoldWidget.bind(e,this,this.$foldStyle),this.getFoldWidgetRange=e.getFoldWidgetRange.bind(e,this,this.$foldStyle),this.$updateFoldWidgets=this.updateFoldWidgets.bind(this),this.$tokenizerUpdateFoldWidgets=this.tokenizerUpdateFoldWidgets.bind(this),this.on("change",this.$updateFoldWidgets),this.on("tokenizerUpdate",this.$tokenizerUpdateFoldWidgets)},this.getParentFoldRangeData=function(e,t){var n=this.foldWidgets;if(!n||t&&n[e])return{};var r=e-1,i;while(r>=0){var s=n[r];s==null&&(s=n[r]=this.getFoldWidget(r));if(s=="start"){var o=this.getFoldWidgetRange(r);i||(i=o);if(o&&o.end.row>=e)break}r--}return{range:r!==-1&&o,firstRange:i}},this.onFoldWidgetClick=function(e,t){t=t.domEvent;var n={children:t.shiftKey,all:t.ctrlKey||t.metaKey,siblings:t.altKey},r=this.$toggleFoldWidget(e,n);if(!r){var i=t.target||t.srcElement;i&&/ace_fold-widget/.test(i.className)&&(i.className+=" ace_invalid")}},this.$toggleFoldWidget=function(e,t){if(!this.getFoldWidget)return;var n=this.getFoldWidget(e),r=this.getLine(e),i=n==="end"?-1:1,s=this.getFoldAt(e,i===-1?0:r.length,i);if(s)return t.children||t.all?this.removeFold(s):this.expandFold(s),s;var o=this.getFoldWidgetRange(e,!0);if(o&&!o.isMultiLine()){s=this.getFoldAt(o.start.row,o.start.column,1);if(s&&o.isEqual(s.range))return this.removeFold(s),s}if(t.siblings){var u=this.getParentFoldRangeData(e);if(u.range)var a=u.range.start.row+1,f=u.range.end.row;this.foldAll(a,f,t.all?1e4:0)}else t.children?(f=o?o.end.row:this.getLength(),this.foldAll(e+1,f,t.all?1e4:0)):o&&(t.all&&(o.collapseChildren=1e4),this.addFold("...",o));return o},this.toggleFoldWidget=function(e){var t=this.selection.getCursor().row;t=this.getRowFoldStart(t);var n=this.$toggleFoldWidget(t,{});if(n)return;var r=this.getParentFoldRangeData(t,!0);n=r.range||r.firstRange;if(n){t=n.start.row;var i=this.getFoldAt(t,this.getLine(t).length,1);i?this.removeFold(i):this.addFold("...",n)}},this.updateFoldWidgets=function(e){var t=e.start.row,n=e.end.row-t;if(n===0)this.foldWidgets[t]=null;else if(e.action=="remove")this.foldWidgets.splice(t,n+1,null);else{var r=Array(n+1);r.unshift(t,1),this.foldWidgets.splice.apply(this.foldWidgets,r)}},this.tokenizerUpdateFoldWidgets=function(e){var t=e.data;t.first!=t.last&&this.foldWidgets.length>t.first&&this.foldWidgets.splice(t.first,this.foldWidgets.length)}}var r=e("../range").Range,i=e("./fold_line").FoldLine,s=e("./fold").Fold,o=e("../token_iterator").TokenIterator;t.Folding=u}),define("ace/edit_session/bracket_match",["require","exports","module","ace/token_iterator","ace/range"],function(e,t,n){"use strict";function s(){this.findMatchingBracket=function(e,t){if(e.column==0)return null;var n=t||this.getLine(e.row).charAt(e.column-1);if(n=="")return null;var r=n.match(/([\(\[\{])|([\)\]\}])/);return r?r[1]?this.$findClosingBracket(r[1],e):this.$findOpeningBracket(r[2],e):null},this.getBracketRange=function(e){var t=this.getLine(e.row),n=!0,r,s=t.charAt(e.column-1),o=s&&s.match(/([\(\[\{])|([\)\]\}])/);o||(s=t.charAt(e.column),e={row:e.row,column:e.column+1},o=s&&s.match(/([\(\[\{])|([\)\]\}])/),n=!1);if(!o)return null;if(o[1]){var u=this.$findClosingBracket(o[1],e);if(!u)return null;r=i.fromPoints(e,u),n||(r.end.column++,r.start.column--),r.cursor=r.end}else{var u=this.$findOpeningBracket(o[2],e);if(!u)return null;r=i.fromPoints(u,e),n||(r.start.column++,r.end.column--),r.cursor=r.start}return r},this.$brackets={")":"(","(":")","]":"[","[":"]","{":"}","}":"{"},this.$findOpeningBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp("(\\.?"+u.type.replace(".","\\.").replace("rparen",".paren").replace(/\b(?:end)\b/,"(?:start|begin|end)")+")+"));var a=t.column-o.getCurrentTokenColumn()-2,f=u.value;for(;;){while(a>=0){var l=f.charAt(a);if(l==i){s-=1;if(s==0)return{row:o.getCurrentTokenRow(),column:a+o.getCurrentTokenColumn()}}else l==e&&(s+=1);a-=1}do u=o.stepBackward();while(u&&!n.test(u.type));if(u==null)break;f=u.value,a=f.length-1}return null},this.$findClosingBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp("(\\.?"+u.type.replace(".","\\.").replace("lparen",".paren").replace(/\b(?:start|begin)\b/,"(?:start|begin|end)")+")+"));var a=t.column-o.getCurrentTokenColumn();for(;;){var f=u.value,l=f.length;while(a=4352&&e<=4447||e>=4515&&e<=4519||e>=4602&&e<=4607||e>=9001&&e<=9002||e>=11904&&e<=11929||e>=11931&&e<=12019||e>=12032&&e<=12245||e>=12272&&e<=12283||e>=12288&&e<=12350||e>=12353&&e<=12438||e>=12441&&e<=12543||e>=12549&&e<=12589||e>=12593&&e<=12686||e>=12688&&e<=12730||e>=12736&&e<=12771||e>=12784&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=13054||e>=13056&&e<=19903||e>=19968&&e<=42124||e>=42128&&e<=42182||e>=43360&&e<=43388||e>=44032&&e<=55203||e>=55216&&e<=55238||e>=55243&&e<=55291||e>=63744&&e<=64255||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=65281&&e<=65376||e>=65504&&e<=65510}r.implement(this,u),this.setDocument=function(e){this.doc&&this.doc.removeListener("change",this.$onChange),this.doc=e,e.on("change",this.$onChange),this.bgTokenizer&&this.bgTokenizer.setDocument(this.getDocument()),this.resetCaches()},this.getDocument=function(){return this.doc},this.$resetRowCache=function(e){if(!e){this.$docRowCache=[],this.$screenRowCache=[];return}var t=this.$docRowCache.length,n=this.$getRowCacheIndex(this.$docRowCache,e)+1;t>n&&(this.$docRowCache.splice(n,t),this.$screenRowCache.splice(n,t))},this.$getRowCacheIndex=function(e,t){var n=0,r=e.length-1;while(n<=r){var i=n+r>>1,s=e[i];if(t>s)n=i+1;else{if(!(t=t)break}return r=n[s],r?(r.index=s,r.start=i-r.value.length,r):null},this.setUndoManager=function(e){this.$undoManager=e,this.$informUndoManager&&this.$informUndoManager.cancel();if(e){var t=this;e.addSession(this),this.$syncInformUndoManager=function(){t.$informUndoManager.cancel(),t.mergeUndoDeltas=!1},this.$informUndoManager=i.delayedCall(this.$syncInformUndoManager)}else this.$syncInformUndoManager=function(){}},this.markUndoGroup=function(){this.$syncInformUndoManager&&this.$syncInformUndoManager()},this.$defaultUndoManager={undo:function(){},redo:function(){},reset:function(){},add:function(){},addSelection:function(){},startNewGroup:function(){},addSession:function(){}},this.getUndoManager=function(){return this.$undoManager||this.$defaultUndoManager},this.getTabString=function(){return this.getUseSoftTabs()?i.stringRepeat(" ",this.getTabSize()):" "},this.setUseSoftTabs=function(e){this.setOption("useSoftTabs",e)},this.getUseSoftTabs=function(){return this.$useSoftTabs&&!this.$mode.$indentWithTabs},this.setTabSize=function(e){this.setOption("tabSize",e)},this.getTabSize=function(){return this.$tabSize},this.isTabStop=function(e){return this.$useSoftTabs&&e.column%this.$tabSize===0},this.setNavigateWithinSoftTabs=function(e){this.setOption("navigateWithinSoftTabs",e)},this.getNavigateWithinSoftTabs=function(){return this.$navigateWithinSoftTabs},this.$overwrite=!1,this.setOverwrite=function(e){this.setOption("overwrite",e)},this.getOverwrite=function(){return this.$overwrite},this.toggleOverwrite=function(){this.setOverwrite(!this.$overwrite)},this.addGutterDecoration=function(e,t){this.$decorations[e]||(this.$decorations[e]=""),this.$decorations[e]+=" "+t,this._signal("changeBreakpoint",{})},this.removeGutterDecoration=function(e,t){this.$decorations[e]=(this.$decorations[e]||"").replace(" "+t,""),this._signal("changeBreakpoint",{})},this.getBreakpoints=function(){return this.$breakpoints},this.setBreakpoints=function(e){this.$breakpoints=[];for(var t=0;t0&&(r=!!n.charAt(t-1).match(this.tokenRe)),r||(r=!!n.charAt(t).match(this.tokenRe));if(r)var i=this.tokenRe;else if(/^\s+$/.test(n.slice(t-1,t+1)))var i=/\s/;else var i=this.nonTokenRe;var s=t;if(s>0){do s--;while(s>=0&&n.charAt(s).match(i));s++}var o=t;while(oe&&(e=t.screenWidth)}),this.lineWidgetWidth=e},this.$computeWidth=function(e){if(this.$modified||e){this.$modified=!1;if(this.$useWrapMode)return this.screenWidth=this.$wrapLimit;var t=this.doc.getAllLines(),n=this.$rowLengthCache,r=0,i=0,s=this.$foldData[i],o=s?s.start.row:Infinity,u=t.length;for(var a=0;ao){a=s.end.row+1;if(a>=u)break;s=this.$foldData[i++],o=s?s.start.row:Infinity}n[a]==null&&(n[a]=this.$getStringScreenWidth(t[a])[0]),n[a]>r&&(r=n[a])}this.screenWidth=r}},this.getLine=function(e){return this.doc.getLine(e)},this.getLines=function(e,t){return this.doc.getLines(e,t)},this.getLength=function(){return this.doc.getLength()},this.getTextRange=function(e){return this.doc.getTextRange(e||this.selection.getRange())},this.insert=function(e,t){return this.doc.insert(e,t)},this.remove=function(e){return this.doc.remove(e)},this.removeFullLines=function(e,t){return this.doc.removeFullLines(e,t)},this.undoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;for(var n=e.length-1;n!=-1;n--){var r=e[n];r.action=="insert"||r.action=="remove"?this.doc.revertDelta(r):r.folds&&this.addFolds(r.folds)}!t&&this.$undoSelect&&(e.selectionBefore?this.selection.fromJSON(e.selectionBefore):this.selection.setRange(this.$getUndoSelection(e,!0))),this.$fromUndo=!1},this.redoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;for(var n=0;ne.end.column&&(s.start.column+=u),s.end.row==e.end.row&&s.end.column>e.end.column&&(s.end.column+=u)),o&&s.start.row>=e.end.row&&(s.start.row+=o,s.end.row+=o)}s.end=this.insert(s.start,r);if(i.length){var a=e.start,f=s.start,o=f.row-a.row,u=f.column-a.column;this.addFolds(i.map(function(e){return e=e.clone(),e.start.row==a.row&&(e.start.column+=u),e.end.row==a.row&&(e.end.column+=u),e.start.row+=o,e.end.row+=o,e}))}return s},this.indentRows=function(e,t,n){n=n.replace(/\t/g,this.getTabString());for(var r=e;r<=t;r++)this.doc.insertInLine({row:r,column:0},n)},this.outdentRows=function(e){var t=e.collapseRows(),n=new l(0,0,0,0),r=this.getTabSize();for(var i=t.start.row;i<=t.end.row;++i){var s=this.getLine(i);n.start.row=i,n.end.row=i;for(var o=0;o0){var r=this.getRowFoldEnd(t+n);if(r>this.doc.getLength()-1)return 0;var i=r-t}else{e=this.$clipRowToDocument(e),t=this.$clipRowToDocument(t);var i=t-e+1}var s=new l(e,0,t,Number.MAX_VALUE),o=this.getFoldsInRange(s).map(function(e){return e=e.clone(),e.start.row+=i,e.end.row+=i,e}),u=n==0?this.doc.getLines(e,t):this.doc.removeFullLines(e,t);return this.doc.insertFullLines(e+i,u),o.length&&this.addFolds(o),i},this.moveLinesUp=function(e,t){return this.$moveLines(e,t,-1)},this.moveLinesDown=function(e,t){return this.$moveLines(e,t,1)},this.duplicateLines=function(e,t){return this.$moveLines(e,t,0)},this.$clipRowToDocument=function(e){return Math.max(0,Math.min(e,this.doc.getLength()-1))},this.$clipColumnToRow=function(e,t){return t<0?0:Math.min(this.doc.getLine(e).length,t)},this.$clipPositionToDocument=function(e,t){t=Math.max(0,t);if(e<0)e=0,t=0;else{var n=this.doc.getLength();e>=n?(e=n-1,t=this.doc.getLine(n-1).length):t=Math.min(this.doc.getLine(e).length,t)}return{row:e,column:t}},this.$clipRangeToDocument=function(e){e.start.row<0?(e.start.row=0,e.start.column=0):e.start.column=this.$clipColumnToRow(e.start.row,e.start.column);var t=this.doc.getLength()-1;return e.end.row>t?(e.end.row=t,e.end.column=this.doc.getLine(t).length):e.end.column=this.$clipColumnToRow(e.end.row,e.end.column),e},this.$wrapLimit=80,this.$useWrapMode=!1,this.$wrapLimitRange={min:null,max:null},this.setUseWrapMode=function(e){if(e!=this.$useWrapMode){this.$useWrapMode=e,this.$modified=!0,this.$resetRowCache(0);if(e){var t=this.getLength();this.$wrapData=Array(t),this.$updateWrapData(0,t-1)}this._signal("changeWrapMode")}},this.getUseWrapMode=function(){return this.$useWrapMode},this.setWrapLimitRange=function(e,t){if(this.$wrapLimitRange.min!==e||this.$wrapLimitRange.max!==t)this.$wrapLimitRange={min:e,max:t},this.$modified=!0,this.$bidiHandler.markAsDirty(),this.$useWrapMode&&this._signal("changeWrapMode")},this.adjustWrapLimit=function(e,t){var n=this.$wrapLimitRange;n.max<0&&(n={min:t,max:t});var r=this.$constrainWrapLimit(e,n.min,n.max);return r!=this.$wrapLimit&&r>1?(this.$wrapLimit=r,this.$modified=!0,this.$useWrapMode&&(this.$updateWrapData(0,this.getLength()-1),this.$resetRowCache(0),this._signal("changeWrapLimit")),!0):!1},this.$constrainWrapLimit=function(e,t,n){return t&&(e=Math.max(t,e)),n&&(e=Math.min(n,e)),e},this.getWrapLimit=function(){return this.$wrapLimit},this.setWrapLimit=function(e){this.setWrapLimitRange(e,e)},this.getWrapLimitRange=function(){return{min:this.$wrapLimitRange.min,max:this.$wrapLimitRange.max}},this.$updateInternalDataOnChange=function(e){var t=this.$useWrapMode,n=e.action,r=e.start,i=e.end,s=r.row,o=i.row,u=o-s,a=null;this.$updating=!0;if(u!=0)if(n==="remove"){this[t?"$wrapData":"$rowLengthCache"].splice(s,u);var f=this.$foldData;a=this.getFoldsInRange(e),this.removeFolds(a);var l=this.getFoldLine(i.row),c=0;if(l){l.addRemoveChars(i.row,i.column,r.column-i.column),l.shiftRow(-u);var h=this.getFoldLine(s);h&&h!==l&&(h.merge(l),l=h),c=f.indexOf(l)+1}for(c;c=i.row&&l.shiftRow(-u)}o=s}else{var p=Array(u);p.unshift(s,0);var d=t?this.$wrapData:this.$rowLengthCache;d.splice.apply(d,p);var f=this.$foldData,l=this.getFoldLine(s),c=0;if(l){var v=l.range.compareInside(r.row,r.column);v==0?(l=l.split(r.row,r.column),l&&(l.shiftRow(u),l.addRemoveChars(o,0,i.column-r.column))):v==-1&&(l.addRemoveChars(s,0,i.column-r.column),l.shiftRow(u)),c=f.indexOf(l)+1}for(c;c=s&&l.shiftRow(u)}}else{u=Math.abs(e.start.column-e.end.column),n==="remove"&&(a=this.getFoldsInRange(e),this.removeFolds(a),u=-u);var l=this.getFoldLine(s);l&&l.addRemoveChars(s,r.column,u)}return t&&this.$wrapData.length!=this.doc.getLength()&&console.error("doc.getLength() and $wrapData.length have to be the same!"),this.$updating=!1,t?this.$updateWrapData(s,o):this.$updateRowLengthCache(s,o),a},this.$updateRowLengthCache=function(e,t,n){this.$rowLengthCache[e]=null,this.$rowLengthCache[t]=null},this.$updateWrapData=function(e,t){var r=this.doc.getAllLines(),i=this.getTabSize(),o=this.$wrapData,u=this.$wrapLimit,a,f,l=e;t=Math.min(t,r.length-1);while(l<=t)f=this.getFoldLine(l,f),f?(a=[],f.walk(function(e,t,i,o){var u;if(e!=null){u=this.$getDisplayTokens(e,a.length),u[0]=n;for(var f=1;fr-b){var w=f+r-b;if(e[w-1]>=c&&e[w]>=c){y(w);continue}if(e[w]==n||e[w]==s){for(w;w!=f-1;w--)if(e[w]==n)break;if(w>f){y(w);continue}w=f+r;for(w;w>2)),f-1);while(w>E&&e[w]E&&e[w]E&&e[w]==a)w--}else while(w>E&&e[w]E){y(++w);continue}w=f+r,e[w]==t&&w--,y(w-b)}return o},this.$getDisplayTokens=function(n,r){var i=[],s;r=r||0;for(var o=0;o39&&u<48||u>57&&u<64?i.push(a):u>=4352&&m(u)?i.push(e,t):i.push(e)}return i},this.$getStringScreenWidth=function(e,t,n){if(t==0)return[0,0];t==null&&(t=Infinity),n=n||0;var r,i;for(i=0;i=4352&&m(r)?n+=2:n+=1;if(n>t)break}return[n,i]},this.lineWidgets=null,this.getRowLength=function(e){if(this.lineWidgets)var t=this.lineWidgets[e]&&this.lineWidgets[e].rowCount||0;else t=0;return!this.$useWrapMode||!this.$wrapData[e]?1+t:this.$wrapData[e].length+1+t},this.getRowLineCount=function(e){return!this.$useWrapMode||!this.$wrapData[e]?1:this.$wrapData[e].length+1},this.getRowWrapIndent=function(e){if(this.$useWrapMode){var t=this.screenToDocumentPosition(e,Number.MAX_VALUE),n=this.$wrapData[t.row];return n.length&&n[0]=0)var u=f[l],i=this.$docRowCache[l],h=e>f[c-1];else var h=!c;var p=this.getLength()-1,d=this.getNextFoldLine(i),v=d?d.start.row:Infinity;while(u<=e){a=this.getRowLength(i);if(u+a>e||i>=p)break;u+=a,i++,i>v&&(i=d.end.row+1,d=this.getNextFoldLine(i,d),v=d?d.start.row:Infinity),h&&(this.$docRowCache.push(i),this.$screenRowCache.push(u))}if(d&&d.start.row<=i)r=this.getFoldDisplayLine(d),i=d.start.row;else{if(u+a<=e||i>p)return{row:p,column:this.getLine(p).length};r=this.getLine(i),d=null}var m=0,g=Math.floor(e-u);if(this.$useWrapMode){var y=this.$wrapData[i];y&&(o=y[g],g>0&&y.length&&(m=y.indent,s=y[g-1]||y[y.length-1],r=r.substring(s)))}return n!==undefined&&this.$bidiHandler.isBidiRow(u+g,i,g)&&(t=this.$bidiHandler.offsetToCol(n)),s+=this.$getStringScreenWidth(r,t-m)[1],this.$useWrapMode&&s>=o&&(s=o-1),d?d.idxToPosition(s):{row:i,column:s}},this.documentToScreenPosition=function(e,t){if(typeof t=="undefined")var n=this.$clipPositionToDocument(e.row,e.column);else n=this.$clipPositionToDocument(e,t);e=n.row,t=n.column;var r=0,i=null,s=null;s=this.getFoldAt(e,t,1),s&&(e=s.start.row,t=s.start.column);var o,u=0,a=this.$docRowCache,f=this.$getRowCacheIndex(a,e),l=a.length;if(l&&f>=0)var u=a[f],r=this.$screenRowCache[f],c=e>a[l-1];else var c=!l;var h=this.getNextFoldLine(u),p=h?h.start.row:Infinity;while(u=p){o=h.end.row+1;if(o>e)break;h=this.getNextFoldLine(o,h),p=h?h.start.row:Infinity}else o=u+1;r+=this.getRowLength(u),u=o,c&&(this.$docRowCache.push(u),this.$screenRowCache.push(r))}var d="";h&&u>=p?(d=this.getFoldDisplayLine(h,e,t),i=h.start.row):(d=this.getLine(e).substring(0,t),i=e);var v=0;if(this.$useWrapMode){var m=this.$wrapData[i];if(m){var g=0;while(d.length>=m[g])r++,g++;d=d.substring(m[g-1]||0,d.length),v=g>0?m.indent:0}}return{row:r,column:v+this.$getStringScreenWidth(d)[0]}},this.documentToScreenColumn=function(e,t){return this.documentToScreenPosition(e,t).column},this.documentToScreenRow=function(e,t){return this.documentToScreenPosition(e,t).row},this.getScreenLength=function(){var e=0,t=null;if(!this.$useWrapMode){e=this.getLength();var n=this.$foldData;for(var r=0;ro&&(s=t.end.row+1,t=this.$foldData[r++],o=t?t.start.row:Infinity)}}return this.lineWidgets&&(e+=this.$getWidgetScreenLength()),e},this.$setFontMetrics=function(e){if(!this.$enableVarChar)return;this.$getStringScreenWidth=function(t,n,r){if(n===0)return[0,0];n||(n=Infinity),r=r||0;var i,s;for(s=0;sn)break}return[r,s]}},this.destroy=function(){this.bgTokenizer&&(this.bgTokenizer.setDocument(null),this.bgTokenizer=null),this.$stopWorker()},this.isFullWidth=m}.call(d.prototype),e("./edit_session/folding").Folding.call(d.prototype),e("./edit_session/bracket_match").BracketMatch.call(d.prototype),o.defineOptions(d.prototype,"session",{wrap:{set:function(e){!e||e=="off"?e=!1:e=="free"?e=!0:e=="printMargin"?e=-1:typeof e=="string"&&(e=parseInt(e,10)||!1);if(this.$wrap==e)return;this.$wrap=e;if(!e)this.setUseWrapMode(!1);else{var t=typeof e=="number"?e:null;this.setWrapLimitRange(t,t),this.setUseWrapMode(!0)}},get:function(){return this.getUseWrapMode()?this.$wrap==-1?"printMargin":this.getWrapLimitRange().min?this.$wrap:"free":"off"},handlesSet:!0},wrapMethod:{set:function(e){e=e=="auto"?this.$mode.type!="text":e!="text",e!=this.$wrapAsCode&&(this.$wrapAsCode=e,this.$useWrapMode&&(this.$useWrapMode=!1,this.setUseWrapMode(!0)))},initialValue:"auto"},indentedSoftWrap:{set:function(){this.$useWrapMode&&(this.$useWrapMode=!1,this.setUseWrapMode(!0))},initialValue:!0},firstLineNumber:{set:function(){this._signal("changeBreakpoint")},initialValue:1},useWorker:{set:function(e){this.$useWorker=e,this.$stopWorker(),e&&this.$startWorker()},initialValue:!0},useSoftTabs:{initialValue:!0},tabSize:{set:function(e){if(isNaN(e)||this.$tabSize===e)return;this.$modified=!0,this.$rowLengthCache=[],this.$tabSize=e,this._signal("changeTabSize")},initialValue:4,handlesSet:!0},navigateWithinSoftTabs:{initialValue:!1},foldStyle:{set:function(e){this.setFoldStyle(e)},handlesSet:!0},overwrite:{set:function(e){this._signal("changeOverwrite")},initialValue:!1},newLineMode:{set:function(e){this.doc.setNewLineMode(e)},get:function(){return this.doc.getNewLineMode()},handlesSet:!0},mode:{set:function(e){this.setMode(e)},get:function(){return this.$modeId},handlesSet:!0}}),t.EditSession=d}),define("ace/search",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(e,t,n){"use strict";function u(e,t){function n(e){return/\w/.test(e)||t.regExp?"\\b":""}return n(e[0])+e+n(e[e.length-1])}var r=e("./lib/lang"),i=e("./lib/oop"),s=e("./range").Range,o=function(){this.$options={}};(function(){this.set=function(e){return i.mixin(this.$options,e),this},this.getOptions=function(){return r.copyObject(this.$options)},this.setOptions=function(e){this.$options=e},this.find=function(e){var t=this.$options,n=this.$matchIterator(e,t);if(!n)return!1;var r=null;return n.forEach(function(e,n,i,o){return r=new s(e,n,i,o),n==o&&t.start&&t.start.start&&t.skipCurrent!=0&&r.isEqual(t.start)?(r=null,!1):!0}),r},this.findAll=function(e){var t=this.$options;if(!t.needle)return[];this.$assembleRegExp(t);var n=t.range,i=n?e.getLines(n.start.row,n.end.row):e.doc.getAllLines(),o=[],u=t.re;if(t.$isMultiLine){var a=u.length,f=i.length-a,l;e:for(var c=u.offset||0;c<=f;c++){for(var h=0;hv)continue;o.push(l=new s(c,v,c+a-1,m)),a>2&&(c=c+a-2)}}else for(var g=0;gE&&o[h].end.row==n.end.row)h--;o=o.slice(g,h+1);for(g=0,h=o.length;g=u;n--)if(c(n,Number.MAX_VALUE,e))return;if(t.wrap==0)return;for(n=a,u=o.row;n>=u;n--)if(c(n,Number.MAX_VALUE,e))return};else var f=function(e){var n=o.row;if(c(n,o.column,e))return;for(n+=1;n<=a;n++)if(c(n,0,e))return;if(t.wrap==0)return;for(n=u,a=o.row;n<=a;n++)if(c(n,0,e))return};if(t.$isMultiLine)var l=n.length,c=function(t,i,s){var o=r?t-l+1:t;if(o<0)return;var u=e.getLine(o),a=u.search(n[0]);if(!r&&ai)return;if(s(o,a,o+l-1,c))return!0};else if(r)var c=function(t,r,i){var s=e.getLine(t),o=[],u,a=0;n.lastIndex=0;while(u=n.exec(s)){var f=u[0].length;a=u.index;if(!f){if(a>=s.length)break;n.lastIndex=a+=1}if(u.index+f>r)break;o.push(u.index,f)}for(var l=o.length-1;l>=0;l-=2){var c=o[l-1],f=o[l];if(i(t,c,t,c+f))return!0}};else var c=function(t,r,i){var s=e.getLine(t),o,u;n.lastIndex=r;while(u=n.exec(s)){var a=u[0].length;o=u.index;if(i(t,o,t,o+a))return!0;if(!a){n.lastIndex=o+=1;if(o>=s.length)return!1}}};return{forEach:f}}}).call(o.prototype),t.Search=o}),define("ace/keyboard/hash_handler",["require","exports","module","ace/lib/keys","ace/lib/useragent"],function(e,t,n){"use strict";function o(e,t){this.platform=t||(i.isMac?"mac":"win"),this.commands={},this.commandKeyBinding={},this.addCommands(e),this.$singleCommand=!0}function u(e,t){o.call(this,e,t),this.$singleCommand=!1}var r=e("../lib/keys"),i=e("../lib/useragent"),s=r.KEY_MODS;u.prototype=o.prototype,function(){function e(e){return typeof e=="object"&&e.bindKey&&e.bindKey.position||(e.isDefault?-100:0)}this.addCommand=function(e){this.commands[e.name]&&this.removeCommand(e),this.commands[e.name]=e,e.bindKey&&this._buildKeyHash(e)},this.removeCommand=function(e,t){var n=e&&(typeof e=="string"?e:e.name);e=this.commands[n],t||delete this.commands[n];var r=this.commandKeyBinding;for(var i in r){var s=r[i];if(s==e)delete r[i];else if(Array.isArray(s)){var o=s.indexOf(e);o!=-1&&(s.splice(o,1),s.length==1&&(r[i]=s[0]))}}},this.bindKey=function(e,t,n){typeof e=="object"&&e&&(n==undefined&&(n=e.position),e=e[this.platform]);if(!e)return;if(typeof t=="function")return this.addCommand({exec:t,bindKey:e,name:t.name||e});e.split("|").forEach(function(e){var r="";if(e.indexOf(" ")!=-1){var i=e.split(/\s+/);e=i.pop(),i.forEach(function(e){var t=this.parseKeys(e),n=s[t.hashId]+t.key;r+=(r?" ":"")+n,this._addCommandToBinding(r,"chainKeys")},this),r+=" "}var o=this.parseKeys(e),u=s[o.hashId]+o.key;this._addCommandToBinding(r+u,t,n)},this)},this._addCommandToBinding=function(t,n,r){var i=this.commandKeyBinding,s;if(!n)delete i[t];else if(!i[t]||this.$singleCommand)i[t]=n;else{Array.isArray(i[t])?(s=i[t].indexOf(n))!=-1&&i[t].splice(s,1):i[t]=[i[t]],typeof r!="number"&&(r=e(n));var o=i[t];for(s=0;sr)break}o.splice(s,0,n)}},this.addCommands=function(e){e&&Object.keys(e).forEach(function(t){var n=e[t];if(!n)return;if(typeof n=="string")return this.bindKey(n,t);typeof n=="function"&&(n={exec:n});if(typeof n!="object")return;n.name||(n.name=t),this.addCommand(n)},this)},this.removeCommands=function(e){Object.keys(e).forEach(function(t){this.removeCommand(e[t])},this)},this.bindKeys=function(e){Object.keys(e).forEach(function(t){this.bindKey(t,e[t])},this)},this._buildKeyHash=function(e){this.bindKey(e.bindKey,e)},this.parseKeys=function(e){var t=e.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(e){return e}),n=t.pop(),i=r[n];if(r.FUNCTION_KEYS[i])n=r.FUNCTION_KEYS[i].toLowerCase();else{if(!t.length)return{key:n,hashId:-1};if(t.length==1&&t[0]=="shift")return{key:n.toUpperCase(),hashId:-1}}var s=0;for(var o=t.length;o--;){var u=r.KEY_MODS[t[o]];if(u==null)return typeof console!="undefined"&&console.error("invalid modifier "+t[o]+" in "+e),!1;s|=u}return{key:n,hashId:s}},this.findKeyCommand=function(t,n){var r=s[t]+n;return this.commandKeyBinding[r]},this.handleKeyboard=function(e,t,n,r){if(r<0)return;var i=s[t]+n,o=this.commandKeyBinding[i];e.$keyChain&&(e.$keyChain+=" "+i,o=this.commandKeyBinding[e.$keyChain]||o);if(o)if(o=="chainKeys"||o[o.length-1]=="chainKeys")return e.$keyChain=e.$keyChain||i,{command:"null"};if(e.$keyChain)if(!!t&&t!=4||n.length!=1){if(t==-1||r>0)e.$keyChain=""}else e.$keyChain=e.$keyChain.slice(0,-i.length-1);return{command:o}},this.getStatusText=function(e,t){return t.$keyChain||""}}.call(o.prototype),t.HashHandler=o,t.MultiHashHandler=u}),define("ace/commands/command_manager",["require","exports","module","ace/lib/oop","ace/keyboard/hash_handler","ace/lib/event_emitter"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("../keyboard/hash_handler").MultiHashHandler,s=e("../lib/event_emitter").EventEmitter,o=function(e,t){i.call(this,t,e),this.byName=this.commands,this.setDefaultHandler("exec",function(e){return e.command.exec(e.editor,e.args||{})})};r.inherits(o,i),function(){r.implement(this,s),this.exec=function(e,t,n){if(Array.isArray(e)){for(var r=e.length;r--;)if(this.exec(e[r],t,n))return!0;return!1}typeof e=="string"&&(e=this.commands[e]);if(!e)return!1;if(t&&t.$readOnly&&!e.readOnly)return!1;if(this.$checkCommandState!=0&&e.isAvailable&&!e.isAvailable(t))return!1;var i={editor:t,command:e,args:n};return i.returnValue=this._emit("exec",i),this._signal("afterExec",i),i.returnValue===!1?!1:!0},this.toggleRecording=function(e){if(this.$inReplay)return;return e&&e._emit("changeStatus"),this.recording?(this.macro.pop(),this.removeEventListener("exec",this.$addCommandToMacro),this.macro.length||(this.macro=this.oldMacro),this.recording=!1):(this.$addCommandToMacro||(this.$addCommandToMacro=function(e){this.macro.push([e.command,e.args])}.bind(this)),this.oldMacro=this.macro,this.macro=[],this.on("exec",this.$addCommandToMacro),this.recording=!0)},this.replay=function(e){if(this.$inReplay||!this.macro)return;if(this.recording)return this.toggleRecording(e);try{this.$inReplay=!0,this.macro.forEach(function(t){typeof t=="string"?this.exec(t,e):this.exec(t[0],e,t[1])},this)}finally{this.$inReplay=!1}},this.trimMacro=function(e){return e.map(function(e){return typeof e[0]!="string"&&(e[0]=e[0].name),e[1]||(e=e[0]),e})}}.call(o.prototype),t.CommandManager=o}),define("ace/commands/default_commands",["require","exports","module","ace/lib/lang","ace/config","ace/range"],function(e,t,n){"use strict";function o(e,t){return{win:e,mac:t}}var r=e("../lib/lang"),i=e("../config"),s=e("../range").Range;t.commands=[{name:"showSettingsMenu",bindKey:o("Ctrl-,","Command-,"),exec:function(e){i.loadModule("ace/ext/settings_menu",function(t){t.init(e),e.showSettingsMenu()})},readOnly:!0},{name:"goToNextError",bindKey:o("Alt-E","F4"),exec:function(e){i.loadModule("./ext/error_marker",function(t){t.showErrorMarker(e,1)})},scrollIntoView:"animate",readOnly:!0},{name:"goToPreviousError",bindKey:o("Alt-Shift-E","Shift-F4"),exec:function(e){i.loadModule("./ext/error_marker",function(t){t.showErrorMarker(e,-1)})},scrollIntoView:"animate",readOnly:!0},{name:"selectall",bindKey:o("Ctrl-A","Command-A"),exec:function(e){e.selectAll()},readOnly:!0},{name:"centerselection",bindKey:o(null,"Ctrl-L"),exec:function(e){e.centerSelection()},readOnly:!0},{name:"gotoline",bindKey:o("Ctrl-L","Command-L"),exec:function(e,t){typeof t!="number"&&(t=parseInt(prompt("Enter line number:"),10)),isNaN(t)||e.gotoLine(t)},readOnly:!0},{name:"fold",bindKey:o("Alt-L|Ctrl-F1","Command-Alt-L|Command-F1"),exec:function(e){e.session.toggleFold(!1)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"unfold",bindKey:o("Alt-Shift-L|Ctrl-Shift-F1","Command-Alt-Shift-L|Command-Shift-F1"),exec:function(e){e.session.toggleFold(!0)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"toggleFoldWidget",bindKey:o("F2","F2"),exec:function(e){e.session.toggleFoldWidget()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"toggleParentFoldWidget",bindKey:o("Alt-F2","Alt-F2"),exec:function(e){e.session.toggleFoldWidget(!0)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"foldall",bindKey:o(null,"Ctrl-Command-Option-0"),exec:function(e){e.session.foldAll()},scrollIntoView:"center",readOnly:!0},{name:"foldOther",bindKey:o("Alt-0","Command-Option-0"),exec:function(e){e.session.foldAll(),e.session.unfold(e.selection.getAllRanges())},scrollIntoView:"center",readOnly:!0},{name:"unfoldall",bindKey:o("Alt-Shift-0","Command-Option-Shift-0"),exec:function(e){e.session.unfold()},scrollIntoView:"center",readOnly:!0},{name:"findnext",bindKey:o("Ctrl-K","Command-G"),exec:function(e){e.findNext()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"findprevious",bindKey:o("Ctrl-Shift-K","Command-Shift-G"),exec:function(e){e.findPrevious()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"selectOrFindNext",bindKey:o("Alt-K","Ctrl-G"),exec:function(e){e.selection.isEmpty()?e.selection.selectWord():e.findNext()},readOnly:!0},{name:"selectOrFindPrevious",bindKey:o("Alt-Shift-K","Ctrl-Shift-G"),exec:function(e){e.selection.isEmpty()?e.selection.selectWord():e.findPrevious()},readOnly:!0},{name:"find",bindKey:o("Ctrl-F","Command-F"),exec:function(e){i.loadModule("ace/ext/searchbox",function(t){t.Search(e)})},readOnly:!0},{name:"overwrite",bindKey:"Insert",exec:function(e){e.toggleOverwrite()},readOnly:!0},{name:"selecttostart",bindKey:o("Ctrl-Shift-Home","Command-Shift-Home|Command-Shift-Up"),exec:function(e){e.getSelection().selectFileStart()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"gotostart",bindKey:o("Ctrl-Home","Command-Home|Command-Up"),exec:function(e){e.navigateFileStart()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"selectup",bindKey:o("Shift-Up","Shift-Up|Ctrl-Shift-P"),exec:function(e){e.getSelection().selectUp()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"golineup",bindKey:o("Up","Up|Ctrl-P"),exec:function(e,t){e.navigateUp(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttoend",bindKey:o("Ctrl-Shift-End","Command-Shift-End|Command-Shift-Down"),exec:function(e){e.getSelection().selectFileEnd()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"gotoend",bindKey:o("Ctrl-End","Command-End|Command-Down"),exec:function(e){e.navigateFileEnd()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"selectdown",bindKey:o("Shift-Down","Shift-Down|Ctrl-Shift-N"),exec:function(e){e.getSelection().selectDown()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"golinedown",bindKey:o("Down","Down|Ctrl-N"),exec:function(e,t){e.navigateDown(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectwordleft",bindKey:o("Ctrl-Shift-Left","Option-Shift-Left"),exec:function(e){e.getSelection().selectWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotowordleft",bindKey:o("Ctrl-Left","Option-Left"),exec:function(e){e.navigateWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttolinestart",bindKey:o("Alt-Shift-Left","Command-Shift-Left|Ctrl-Shift-A"),exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotolinestart",bindKey:o("Alt-Left|Home","Command-Left|Home|Ctrl-A"),exec:function(e){e.navigateLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectleft",bindKey:o("Shift-Left","Shift-Left|Ctrl-Shift-B"),exec:function(e){e.getSelection().selectLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotoleft",bindKey:o("Left","Left|Ctrl-B"),exec:function(e,t){e.navigateLeft(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectwordright",bindKey:o("Ctrl-Shift-Right","Option-Shift-Right"),exec:function(e){e.getSelection().selectWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotowordright",bindKey:o("Ctrl-Right","Option-Right"),exec:function(e){e.navigateWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttolineend",bindKey:o("Alt-Shift-Right","Command-Shift-Right|Shift-End|Ctrl-Shift-E"),exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotolineend",bindKey:o("Alt-Right|End","Command-Right|End|Ctrl-E"),exec:function(e){e.navigateLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectright",bindKey:o("Shift-Right","Shift-Right"),exec:function(e){e.getSelection().selectRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotoright",bindKey:o("Right","Right|Ctrl-F"),exec:function(e,t){e.navigateRight(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectpagedown",bindKey:"Shift-PageDown",exec:function(e){e.selectPageDown()},readOnly:!0},{name:"pagedown",bindKey:o(null,"Option-PageDown"),exec:function(e){e.scrollPageDown()},readOnly:!0},{name:"gotopagedown",bindKey:o("PageDown","PageDown|Ctrl-V"),exec:function(e){e.gotoPageDown()},readOnly:!0},{name:"selectpageup",bindKey:"Shift-PageUp",exec:function(e){e.selectPageUp()},readOnly:!0},{name:"pageup",bindKey:o(null,"Option-PageUp"),exec:function(e){e.scrollPageUp()},readOnly:!0},{name:"gotopageup",bindKey:"PageUp",exec:function(e){e.gotoPageUp()},readOnly:!0},{name:"scrollup",bindKey:o("Ctrl-Up",null),exec:function(e){e.renderer.scrollBy(0,-2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"scrolldown",bindKey:o("Ctrl-Down",null),exec:function(e){e.renderer.scrollBy(0,2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"selectlinestart",bindKey:"Shift-Home",exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectlineend",bindKey:"Shift-End",exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"togglerecording",bindKey:o("Ctrl-Alt-E","Command-Option-E"),exec:function(e){e.commands.toggleRecording(e)},readOnly:!0},{name:"replaymacro",bindKey:o("Ctrl-Shift-E","Command-Shift-E"),exec:function(e){e.commands.replay(e)},readOnly:!0},{name:"jumptomatching",bindKey:o("Ctrl-P","Ctrl-P"),exec:function(e){e.jumpToMatching()},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"selecttomatching",bindKey:o("Ctrl-Shift-P","Ctrl-Shift-P"),exec:function(e){e.jumpToMatching(!0)},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"expandToMatching",bindKey:o("Ctrl-Shift-M","Ctrl-Shift-M"),exec:function(e){e.jumpToMatching(!0,!0)},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"passKeysToBrowser",bindKey:o(null,null),exec:function(){},passEvent:!0,readOnly:!0},{name:"copy",exec:function(e){},readOnly:!0},{name:"cut",exec:function(e){var t=e.$copyWithEmptySelection&&e.selection.isEmpty(),n=t?e.selection.getLineRange():e.selection.getRange();e._emit("cut",n),n.isEmpty()||e.session.remove(n),e.clearSelection()},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"paste",exec:function(e,t){e.$handlePaste(t)},scrollIntoView:"cursor"},{name:"removeline",bindKey:o("Ctrl-D","Command-D"),exec:function(e){e.removeLines()},scrollIntoView:"cursor",multiSelectAction:"forEachLine"},{name:"duplicateSelection",bindKey:o("Ctrl-Shift-D","Command-Shift-D"),exec:function(e){e.duplicateSelection()},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"sortlines",bindKey:o("Ctrl-Alt-S","Command-Alt-S"),exec:function(e){e.sortLines()},scrollIntoView:"selection",multiSelectAction:"forEachLine"},{name:"togglecomment",bindKey:o("Ctrl-/","Command-/"),exec:function(e){e.toggleCommentLines()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"toggleBlockComment",bindKey:o("Ctrl-Shift-/","Command-Shift-/"),exec:function(e){e.toggleBlockComment()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"modifyNumberUp",bindKey:o("Ctrl-Shift-Up","Alt-Shift-Up"),exec:function(e){e.modifyNumber(1)},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"modifyNumberDown",bindKey:o("Ctrl-Shift-Down","Alt-Shift-Down"),exec:function(e){e.modifyNumber(-1)},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"replace",bindKey:o("Ctrl-H","Command-Option-F"),exec:function(e){i.loadModule("ace/ext/searchbox",function(t){t.Search(e,!0)})}},{name:"undo",bindKey:o("Ctrl-Z","Command-Z"),exec:function(e){e.undo()}},{name:"redo",bindKey:o("Ctrl-Shift-Z|Ctrl-Y","Command-Shift-Z|Command-Y"),exec:function(e){e.redo()}},{name:"copylinesup",bindKey:o("Alt-Shift-Up","Command-Option-Up"),exec:function(e){e.copyLinesUp()},scrollIntoView:"cursor"},{name:"movelinesup",bindKey:o("Alt-Up","Option-Up"),exec:function(e){e.moveLinesUp()},scrollIntoView:"cursor"},{name:"copylinesdown",bindKey:o("Alt-Shift-Down","Command-Option-Down"),exec:function(e){e.copyLinesDown()},scrollIntoView:"cursor"},{name:"movelinesdown",bindKey:o("Alt-Down","Option-Down"),exec:function(e){e.moveLinesDown()},scrollIntoView:"cursor"},{name:"del",bindKey:o("Delete","Delete|Ctrl-D|Shift-Delete"),exec:function(e){e.remove("right")},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"backspace",bindKey:o("Shift-Backspace|Backspace","Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H"),exec:function(e){e.remove("left")},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"cut_or_delete",bindKey:o("Shift-Delete",null),exec:function(e){if(!e.selection.isEmpty())return!1;e.remove("left")},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolinestart",bindKey:o("Alt-Backspace","Command-Backspace"),exec:function(e){e.removeToLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolineend",bindKey:o("Alt-Delete","Ctrl-K|Command-Delete"),exec:function(e){e.removeToLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolinestarthard",bindKey:o("Ctrl-Shift-Backspace",null),exec:function(e){var t=e.selection.getRange();t.start.column=0,e.session.remove(t)},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolineendhard",bindKey:o("Ctrl-Shift-Delete",null),exec:function(e){var t=e.selection.getRange();t.end.column=Number.MAX_VALUE,e.session.remove(t)},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removewordleft",bindKey:o("Ctrl-Backspace","Alt-Backspace|Ctrl-Alt-Backspace"),exec:function(e){e.removeWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removewordright",bindKey:o("Ctrl-Delete","Alt-Delete"),exec:function(e){e.removeWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"outdent",bindKey:o("Shift-Tab","Shift-Tab"),exec:function(e){e.blockOutdent()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"indent",bindKey:o("Tab","Tab"),exec:function(e){e.indent()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"blockoutdent",bindKey:o("Ctrl-[","Ctrl-["),exec:function(e){e.blockOutdent()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"blockindent",bindKey:o("Ctrl-]","Ctrl-]"),exec:function(e){e.blockIndent()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"insertstring",exec:function(e,t){e.insert(t)},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"inserttext",exec:function(e,t){e.insert(r.stringRepeat(t.text||"",t.times||1))},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"splitline",bindKey:o(null,"Ctrl-O"),exec:function(e){e.splitLine()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"transposeletters",bindKey:o("Alt-Shift-X","Ctrl-T"),exec:function(e){e.transposeLetters()},multiSelectAction:function(e){e.transposeSelections(1)},scrollIntoView:"cursor"},{name:"touppercase",bindKey:o("Ctrl-U","Ctrl-U"),exec:function(e){e.toUpperCase()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"tolowercase",bindKey:o("Ctrl-Shift-U","Ctrl-Shift-U"),exec:function(e){e.toLowerCase()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"expandtoline",bindKey:o("Ctrl-Shift-L","Command-Shift-L"),exec:function(e){var t=e.selection.getRange();t.start.column=t.end.column=0,t.end.row++,e.selection.setRange(t,!1)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"joinlines",bindKey:o(null,null),exec:function(e){var t=e.selection.isBackwards(),n=t?e.selection.getSelectionLead():e.selection.getSelectionAnchor(),i=t?e.selection.getSelectionAnchor():e.selection.getSelectionLead(),o=e.session.doc.getLine(n.row).length,u=e.session.doc.getTextRange(e.selection.getRange()),a=u.replace(/\n\s*/," ").length,f=e.session.doc.getLine(n.row);for(var l=n.row+1;l<=i.row+1;l++){var c=r.stringTrimLeft(r.stringTrimRight(e.session.doc.getLine(l)));c.length!==0&&(c=" "+c),f+=c}i.row+10?(e.selection.moveCursorTo(n.row,n.column),e.selection.selectTo(n.row,n.column+a)):(o=e.session.doc.getLine(n.row).length>o?o+1:o,e.selection.moveCursorTo(n.row,o))},multiSelectAction:"forEach",readOnly:!0},{name:"invertSelection",bindKey:o(null,null),exec:function(e){var t=e.session.doc.getLength()-1,n=e.session.doc.getLine(t).length,r=e.selection.rangeList.ranges,i=[];r.length<1&&(r=[e.selection.getRange()]);for(var o=0;o=i.lastRow||r.end.row<=i.firstRow)&&this.renderer.scrollSelectionIntoView(this.selection.anchor,this.selection.lead);break;default:}n=="animate"&&this.renderer.animateScrolling(this.curOp.scrollTop)}var s=this.selection.toJSON();this.curOp.selectionAfter=s,this.$lastSel=this.selection.toJSON(),this.session.getUndoManager().addSelection(s),this.prevOp=this.curOp,this.curOp=null}},this.$mergeableCommands=["backspace","del","insertstring"],this.$historyTracker=function(e){if(!this.$mergeUndoDeltas)return;var t=this.prevOp,n=this.$mergeableCommands,r=t.command&&e.command.name==t.command.name;if(e.command.name=="insertstring"){var i=e.args;this.mergeNextCommand===undefined&&(this.mergeNextCommand=!0),r=r&&this.mergeNextCommand&&(!/\s/.test(i)||/\s/.test(t.args)),this.mergeNextCommand=!0}else r=r&&n.indexOf(e.command.name)!==-1;this.$mergeUndoDeltas!="always"&&Date.now()-this.sequenceStartTime>2e3&&(r=!1),r?this.session.mergeUndoDeltas=!0:n.indexOf(e.command.name)!==-1&&(this.sequenceStartTime=Date.now())},this.setKeyboardHandler=function(e,t){if(e&&typeof e=="string"&&e!="ace"){this.$keybindingId=e;var n=this;g.loadModule(["keybinding",e],function(r){n.$keybindingId==e&&n.keyBinding.setKeyboardHandler(r&&r.handler),t&&t()})}else this.$keybindingId=null,this.keyBinding.setKeyboardHandler(e),t&&t()},this.getKeyboardHandler=function(){return this.keyBinding.getKeyboardHandler()},this.setSession=function(e){if(this.session==e)return;this.curOp&&this.endOperation(),this.curOp={};var t=this.session;if(t){this.session.off("change",this.$onDocumentChange),this.session.off("changeMode",this.$onChangeMode),this.session.off("tokenizerUpdate",this.$onTokenizerUpdate),this.session.off("changeTabSize",this.$onChangeTabSize),this.session.off("changeWrapLimit",this.$onChangeWrapLimit),this.session.off("changeWrapMode",this.$onChangeWrapMode),this.session.off("changeFold",this.$onChangeFold),this.session.off("changeFrontMarker",this.$onChangeFrontMarker),this.session.off("changeBackMarker",this.$onChangeBackMarker),this.session.off("changeBreakpoint",this.$onChangeBreakpoint),this.session.off("changeAnnotation",this.$onChangeAnnotation),this.session.off("changeOverwrite",this.$onCursorChange),this.session.off("changeScrollTop",this.$onScrollTopChange),this.session.off("changeScrollLeft",this.$onScrollLeftChange);var n=this.session.getSelection();n.off("changeCursor",this.$onCursorChange),n.off("changeSelection",this.$onSelectionChange)}this.session=e,e?(this.$onDocumentChange=this.onDocumentChange.bind(this),e.on("change",this.$onDocumentChange),this.renderer.setSession(e),this.$onChangeMode=this.onChangeMode.bind(this),e.on("changeMode",this.$onChangeMode),this.$onTokenizerUpdate=this.onTokenizerUpdate.bind(this),e.on("tokenizerUpdate",this.$onTokenizerUpdate),this.$onChangeTabSize=this.renderer.onChangeTabSize.bind(this.renderer),e.on("changeTabSize",this.$onChangeTabSize),this.$onChangeWrapLimit=this.onChangeWrapLimit.bind(this),e.on("changeWrapLimit",this.$onChangeWrapLimit),this.$onChangeWrapMode=this.onChangeWrapMode.bind(this),e.on("changeWrapMode",this.$onChangeWrapMode),this.$onChangeFold=this.onChangeFold.bind(this),e.on("changeFold",this.$onChangeFold),this.$onChangeFrontMarker=this.onChangeFrontMarker.bind(this),this.session.on("changeFrontMarker",this.$onChangeFrontMarker),this.$onChangeBackMarker=this.onChangeBackMarker.bind(this),this.session.on("changeBackMarker",this.$onChangeBackMarker),this.$onChangeBreakpoint=this.onChangeBreakpoint.bind(this),this.session.on("changeBreakpoint",this.$onChangeBreakpoint),this.$onChangeAnnotation=this.onChangeAnnotation.bind(this),this.session.on("changeAnnotation",this.$onChangeAnnotation),this.$onCursorChange=this.onCursorChange.bind(this),this.session.on("changeOverwrite",this.$onCursorChange),this.$onScrollTopChange=this.onScrollTopChange.bind(this),this.session.on("changeScrollTop",this.$onScrollTopChange),this.$onScrollLeftChange=this.onScrollLeftChange.bind(this),this.session.on("changeScrollLeft",this.$onScrollLeftChange),this.selection=e.getSelection(),this.selection.on("changeCursor",this.$onCursorChange),this.$onSelectionChange=this.onSelectionChange.bind(this),this.selection.on("changeSelection",this.$onSelectionChange),this.onChangeMode(),this.onCursorChange(),this.onScrollTopChange(),this.onScrollLeftChange(),this.onSelectionChange(),this.onChangeFrontMarker(),this.onChangeBackMarker(),this.onChangeBreakpoint(),this.onChangeAnnotation(),this.session.getUseWrapMode()&&this.renderer.adjustWrapLimit(),this.renderer.updateFull()):(this.selection=null,this.renderer.setSession(e)),this._signal("changeSession",{session:e,oldSession:t}),this.curOp=null,t&&t._signal("changeEditor",{oldEditor:this}),e&&e._signal("changeEditor",{editor:this}),e&&e.bgTokenizer&&e.bgTokenizer.scheduleStart()},this.getSession=function(){return this.session},this.setValue=function(e,t){return this.session.doc.setValue(e),t?t==1?this.navigateFileEnd():t==-1&&this.navigateFileStart():this.selectAll(),e},this.getValue=function(){return this.session.getValue()},this.getSelection=function(){return this.selection},this.resize=function(e){this.renderer.onResize(e)},this.setTheme=function(e,t){this.renderer.setTheme(e,t)},this.getTheme=function(){return this.renderer.getTheme()},this.setStyle=function(e){this.renderer.setStyle(e)},this.unsetStyle=function(e){this.renderer.unsetStyle(e)},this.getFontSize=function(){return this.getOption("fontSize")||i.computedStyle(this.container).fontSize},this.setFontSize=function(e){this.setOption("fontSize",e)},this.$highlightBrackets=function(){this.session.$bracketHighlight&&(this.session.removeMarker(this.session.$bracketHighlight),this.session.$bracketHighlight=null);if(this.$highlightPending)return;var e=this;this.$highlightPending=!0,setTimeout(function(){e.$highlightPending=!1;var t=e.session;if(!t||!t.bgTokenizer)return;var n=t.findMatchingBracket(e.getCursorPosition());if(n)var r=new p(n.row,n.column,n.row,n.column+1);else if(t.$mode.getMatching)var r=t.$mode.getMatching(e.session);r&&(t.$bracketHighlight=t.addMarker(r,"ace_bracket","text"))},50)},this.$highlightTags=function(){if(this.$highlightTagPending)return;var e=this;this.$highlightTagPending=!0,setTimeout(function(){e.$highlightTagPending=!1;var t=e.session;if(!t||!t.bgTokenizer)return;var n=e.getCursorPosition(),r=new y(e.session,n.row,n.column),i=r.getCurrentToken();if(!i||!/\b(?:tag-open|tag-name)/.test(i.type)){t.removeMarker(t.$tagHighlight),t.$tagHighlight=null;return}if(i.type.indexOf("tag-open")!=-1){i=r.stepForward();if(!i)return}var s=i.value,o=0,u=r.stepBackward();if(u.value=="<"){do u=i,i=r.stepForward(),i&&i.value===s&&i.type.indexOf("tag-name")!==-1&&(u.value==="<"?o++:u.value==="=0)}else{do i=u,u=r.stepBackward(),i&&i.value===s&&i.type.indexOf("tag-name")!==-1&&(u.value==="<"?o++:u.value==="1)&&(t=!1)}if(e.$highlightLineMarker&&!t)e.removeMarker(e.$highlightLineMarker.id),e.$highlightLineMarker=null;else if(!e.$highlightLineMarker&&t){var n=new p(t.row,t.column,t.row,Infinity);n.id=e.addMarker(n,"ace_active-line","screenLine"),e.$highlightLineMarker=n}else t&&(e.$highlightLineMarker.start.row=t.row,e.$highlightLineMarker.end.row=t.row,e.$highlightLineMarker.start.column=t.column,e._signal("changeBackMarker"))},this.onSelectionChange=function(e){var t=this.session;t.$selectionMarker&&t.removeMarker(t.$selectionMarker),t.$selectionMarker=null;if(!this.selection.isEmpty()){var n=this.selection.getRange(),r=this.getSelectionStyle();t.$selectionMarker=t.addMarker(n,"ace_selection",r)}else this.$updateHighlightActiveLine();var i=this.$highlightSelectedWord&&this.$getSelectionHighLightRegexp();this.session.highlight(i),this._signal("changeSelection")},this.$getSelectionHighLightRegexp=function(){var e=this.session,t=this.getSelectionRange();if(t.isEmpty()||t.isMultiLine())return;var n=t.start.column,r=t.end.column,i=e.getLine(t.start.row),s=i.substring(n,r);if(s.length>5e3||!/[\w\d]/.test(s))return;var o=this.$search.$assembleRegExp({wholeWord:!0,caseSensitive:!0,needle:s}),u=i.substring(n-1,r+1);if(!o.test(u))return;return o},this.onChangeFrontMarker=function(){this.renderer.updateFrontMarkers()},this.onChangeBackMarker=function(){this.renderer.updateBackMarkers()},this.onChangeBreakpoint=function(){this.renderer.updateBreakpoints()},this.onChangeAnnotation=function(){this.renderer.setAnnotations(this.session.getAnnotations())},this.onChangeMode=function(e){this.renderer.updateText(),this._emit("changeMode",e)},this.onChangeWrapLimit=function(){this.renderer.updateFull()},this.onChangeWrapMode=function(){this.renderer.onResize(!0)},this.onChangeFold=function(){this.$updateHighlightActiveLine(),this.renderer.updateFull()},this.getSelectedText=function(){return this.session.getTextRange(this.getSelectionRange())},this.getCopyText=function(){var e=this.getSelectedText(),t=this.session.doc.getNewLineCharacter(),n=!1;if(!e&&this.$copyWithEmptySelection){n=!0;var r=this.selection.getAllRanges();for(var i=0;is.length||i.length<2||!i[1])return this.commands.exec("insertstring",this,t);for(var o=s.length;o--;){var u=s[o];u.isEmpty()||r.remove(u),r.insert(u.start,i[o])}}},this.execCommand=function(e,t){return this.commands.exec(e,this,t)},this.insert=function(e,t){var n=this.session,r=n.getMode(),i=this.getCursorPosition();if(this.getBehavioursEnabled()&&!t){var s=r.transformAction(n.getState(i.row),"insertion",this,n,e);s&&(e!==s.text&&(this.inVirtualSelectionMode||(this.session.mergeUndoDeltas=!1,this.mergeNextCommand=!1)),e=s.text)}e==" "&&(e=this.session.getTabString());if(!this.selection.isEmpty()){var o=this.getSelectionRange();i=this.session.remove(o),this.clearSelection()}else if(this.session.getOverwrite()&&e.indexOf("\n")==-1){var o=new p.fromPoints(i,i);o.end.column+=e.length,this.session.remove(o)}if(e=="\n"||e=="\r\n"){var u=n.getLine(i.row);if(i.column>u.search(/\S|$/)){var a=u.substr(i.column).search(/\S|$/);n.doc.removeInLine(i.row,i.column,i.column+a)}}this.clearSelection();var f=i.column,l=n.getState(i.row),u=n.getLine(i.row),c=r.checkOutdent(l,u,e),h=n.insert(i,e);s&&s.selection&&(s.selection.length==2?this.selection.setSelectionRange(new p(i.row,f+s.selection[0],i.row,f+s.selection[1])):this.selection.setSelectionRange(new p(i.row+s.selection[0],s.selection[1],i.row+s.selection[2],s.selection[3])));if(n.getDocument().isNewLine(e)){var d=r.getNextLineIndent(l,u.slice(0,i.column),n.getTabString());n.insert({row:i.row+1,column:0},d)}c&&r.autoOutdent(l,n,i.row)},this.onTextInput=function(e,t){if(!t)return this.keyBinding.onTextInput(e);this.startOperation({command:{name:"insertstring"}});var n=this.applyComposition.bind(this,e,t);this.selection.rangeCount?this.forEachSelection(n):n(),this.endOperation()},this.applyComposition=function(e,t){if(t.extendLeft||t.extendRight){var n=this.selection.getRange();n.start.column-=t.extendLeft,n.end.column+=t.extendRight,this.selection.setRange(n),!e&&!n.isEmpty()&&this.remove()}(e||!this.selection.isEmpty())&&this.insert(e,!0);if(t.restoreStart||t.restoreEnd){var n=this.selection.getRange();n.start.column-=t.restoreStart,n.end.column-=t.restoreEnd,this.selection.setRange(n)}},this.onCommandKey=function(e,t,n){this.keyBinding.onCommandKey(e,t,n)},this.setOverwrite=function(e){this.session.setOverwrite(e)},this.getOverwrite=function(){return this.session.getOverwrite()},this.toggleOverwrite=function(){this.session.toggleOverwrite()},this.setScrollSpeed=function(e){this.setOption("scrollSpeed",e)},this.getScrollSpeed=function(){return this.getOption("scrollSpeed")},this.setDragDelay=function(e){this.setOption("dragDelay",e)},this.getDragDelay=function(){return this.getOption("dragDelay")},this.setSelectionStyle=function(e){this.setOption("selectionStyle",e)},this.getSelectionStyle=function(){return this.getOption("selectionStyle")},this.setHighlightActiveLine=function(e){this.setOption("highlightActiveLine",e)},this.getHighlightActiveLine=function(){return this.getOption("highlightActiveLine")},this.setHighlightGutterLine=function(e){this.setOption("highlightGutterLine",e)},this.getHighlightGutterLine=function(){return this.getOption("highlightGutterLine")},this.setHighlightSelectedWord=function(e){this.setOption("highlightSelectedWord",e)},this.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},this.setAnimatedScroll=function(e){this.renderer.setAnimatedScroll(e)},this.getAnimatedScroll=function(){return this.renderer.getAnimatedScroll()},this.setShowInvisibles=function(e){this.renderer.setShowInvisibles(e)},this.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},this.setDisplayIndentGuides=function(e){this.renderer.setDisplayIndentGuides(e)},this.getDisplayIndentGuides=function(){return this.renderer.getDisplayIndentGuides()},this.setShowPrintMargin=function(e){this.renderer.setShowPrintMargin(e)},this.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},this.setPrintMarginColumn=function(e){this.renderer.setPrintMarginColumn(e)},this.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},this.setReadOnly=function(e){this.setOption("readOnly",e)},this.getReadOnly=function(){return this.getOption("readOnly")},this.setBehavioursEnabled=function(e){this.setOption("behavioursEnabled",e)},this.getBehavioursEnabled=function(){return this.getOption("behavioursEnabled")},this.setWrapBehavioursEnabled=function(e){this.setOption("wrapBehavioursEnabled",e)},this.getWrapBehavioursEnabled=function(){return this.getOption("wrapBehavioursEnabled")},this.setShowFoldWidgets=function(e){this.setOption("showFoldWidgets",e)},this.getShowFoldWidgets=function(){return this.getOption("showFoldWidgets")},this.setFadeFoldWidgets=function(e){this.setOption("fadeFoldWidgets",e)},this.getFadeFoldWidgets=function(){return this.getOption("fadeFoldWidgets")},this.remove=function(e){this.selection.isEmpty()&&(e=="left"?this.selection.selectLeft():this.selection.selectRight());var t=this.getSelectionRange();if(this.getBehavioursEnabled()){var n=this.session,r=n.getState(t.start.row),i=n.getMode().transformAction(r,"deletion",this,n,t);if(t.end.column===0){var s=n.getTextRange(t);if(s[s.length-1]=="\n"){var o=n.getLine(t.end.row);/^\s+$/.test(o)&&(t.end.column=o.length)}}i&&(t=i)}this.session.remove(t),this.clearSelection()},this.removeWordRight=function(){this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeWordLeft=function(){this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineStart=function(){this.selection.isEmpty()&&this.selection.selectLineStart(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineEnd=function(){this.selection.isEmpty()&&this.selection.selectLineEnd();var e=this.getSelectionRange();e.start.column==e.end.column&&e.start.row==e.end.row&&(e.end.column=0,e.end.row++),this.session.remove(e),this.clearSelection()},this.splitLine=function(){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var e=this.getCursorPosition();this.insert("\n"),this.moveCursorToPosition(e)},this.transposeLetters=function(){if(!this.selection.isEmpty())return;var e=this.getCursorPosition(),t=e.column;if(t===0)return;var n=this.session.getLine(e.row),r,i;tt.toLowerCase()?1:0});var i=new p(0,0,0,0);for(var r=e.first;r<=e.last;r++){var s=t.getLine(r);i.start.row=r,i.end.row=r,i.end.column=s.length,t.replace(i,n[r-e.first])}},this.toggleCommentLines=function(){var e=this.session.getState(this.getCursorPosition().row),t=this.$getSelectedRows();this.session.getMode().toggleCommentLines(e,this.session,t.first,t.last)},this.toggleBlockComment=function(){var e=this.getCursorPosition(),t=this.session.getState(e.row),n=this.getSelectionRange();this.session.getMode().toggleBlockComment(t,this.session,n,e)},this.getNumberAt=function(e,t){var n=/[\-]?[0-9]+(?:\.[0-9]+)?/g;n.lastIndex=0;var r=this.session.getLine(e);while(n.lastIndex=t){var s={value:i[0],start:i.index,end:i.index+i[0].length};return s}}return null},this.modifyNumber=function(e){var t=this.selection.getCursor().row,n=this.selection.getCursor().column,r=new p(t,n-1,t,n),i=this.session.getTextRange(r);if(!isNaN(parseFloat(i))&&isFinite(i)){var s=this.getNumberAt(t,n);if(s){var o=s.value.indexOf(".")>=0?s.start+s.value.indexOf(".")+1:s.end,u=s.start+s.value.length-o,a=parseFloat(s.value);a*=Math.pow(10,u),o!==s.end&&n=u&&o<=a&&(n=t,f.selection.clearSelection(),f.moveCursorTo(e,u+r),f.selection.selectTo(e,a+r)),u=a});var l=this.$toggleWordPairs,c;for(var h=0;hp+1)break;p=d.last}l--,u=this.session.$moveLines(h,p,t?0:e),t&&e==-1&&(c=l+1);while(c<=l)o[c].moveBy(u,0),c++;t||(u=0),a+=u}i.fromOrientedRange(i.ranges[0]),i.rangeList.attach(this.session),this.inVirtualSelectionMode=!1}},this.$getSelectedRows=function(e){return e=(e||this.getSelectionRange()).collapseRows(),{first:this.session.getRowFoldStart(e.start.row),last:this.session.getRowFoldEnd(e.end.row)}},this.onCompositionStart=function(e){this.renderer.showComposition(e)},this.onCompositionUpdate=function(e){this.renderer.setCompositionText(e)},this.onCompositionEnd=function(){this.renderer.hideComposition()},this.getFirstVisibleRow=function(){return this.renderer.getFirstVisibleRow()},this.getLastVisibleRow=function(){return this.renderer.getLastVisibleRow()},this.isRowVisible=function(e){return e>=this.getFirstVisibleRow()&&e<=this.getLastVisibleRow()},this.isRowFullyVisible=function(e){return e>=this.renderer.getFirstFullyVisibleRow()&&e<=this.renderer.getLastFullyVisibleRow()},this.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},this.$moveByPage=function(e,t){var n=this.renderer,r=this.renderer.layerConfig,i=e*Math.floor(r.height/r.lineHeight);t===!0?this.selection.$moveSelection(function(){this.moveCursorBy(i,0)}):t===!1&&(this.selection.moveCursorBy(i,0),this.selection.clearSelection());var s=n.scrollTop;n.scrollBy(0,i*r.lineHeight),t!=null&&n.scrollCursorIntoView(null,.5),n.animateScrolling(s)},this.selectPageDown=function(){this.$moveByPage(1,!0)},this.selectPageUp=function(){this.$moveByPage(-1,!0)},this.gotoPageDown=function(){this.$moveByPage(1,!1)},this.gotoPageUp=function(){this.$moveByPage(-1,!1)},this.scrollPageDown=function(){this.$moveByPage(1)},this.scrollPageUp=function(){this.$moveByPage(-1)},this.scrollToRow=function(e){this.renderer.scrollToRow(e)},this.scrollToLine=function(e,t,n,r){this.renderer.scrollToLine(e,t,n,r)},this.centerSelection=function(){var e=this.getSelectionRange(),t={row:Math.floor(e.start.row+(e.end.row-e.start.row)/2),column:Math.floor(e.start.column+(e.end.column-e.start.column)/2)};this.renderer.alignCursor(t,.5)},this.getCursorPosition=function(){return this.selection.getCursor()},this.getCursorPositionScreen=function(){return this.session.documentToScreenPosition(this.getCursorPosition())},this.getSelectionRange=function(){return this.selection.getRange()},this.selectAll=function(){this.selection.selectAll()},this.clearSelection=function(){this.selection.clearSelection()},this.moveCursorTo=function(e,t){this.selection.moveCursorTo(e,t)},this.moveCursorToPosition=function(e){this.selection.moveCursorToPosition(e)},this.jumpToMatching=function(e,t){var n=this.getCursorPosition(),r=new y(this.session,n.row,n.column),i=r.getCurrentToken(),s=i||r.stepForward();if(!s)return;var o,u=!1,a={},f=n.column-s.start,l,c={")":"(","(":"(","]":"[","[":"[","{":"{","}":"{"};do{if(s.value.match(/[{}()\[\]]/g))for(;f=0;--s)this.$tryReplace(n[s],e)&&r++;return this.selection.setSelectionRange(i),r},this.$tryReplace=function(e,t){var n=this.session.getTextRange(e);return t=this.$search.replace(n,t),t!==null?(e.end=this.session.replace(e,t),e):null},this.getLastSearchOptions=function(){return this.$search.getOptions()},this.find=function(e,t,n){t||(t={}),typeof e=="string"||e instanceof RegExp?t.needle=e:typeof e=="object"&&r.mixin(t,e);var i=this.selection.getRange();t.needle==null&&(e=this.session.getTextRange(i)||this.$search.$options.needle,e||(i=this.session.getWordRange(i.start.row,i.start.column),e=this.session.getTextRange(i)),this.$search.set({needle:e})),this.$search.set(t),t.start||this.$search.set({start:i});var s=this.$search.find(this.session);if(t.preventScroll)return s;if(s)return this.revealRange(s,n),s;t.backwards?i.start=i.end:i.end=i.start,this.selection.setRange(i)},this.findNext=function(e,t){this.find({skipCurrent:!0,backwards:!1},e,t)},this.findPrevious=function(e,t){this.find(e,{skipCurrent:!0,backwards:!0},t)},this.revealRange=function(e,t){this.session.unfold(e),this.selection.setSelectionRange(e);var n=this.renderer.scrollTop;this.renderer.scrollSelectionIntoView(e.start,e.end,.5),t!==!1&&this.renderer.animateScrolling(n)},this.undo=function(){this.session.getUndoManager().undo(this.session),this.renderer.scrollCursorIntoView(null,.5)},this.redo=function(){this.session.getUndoManager().redo(this.session),this.renderer.scrollCursorIntoView(null,.5)},this.destroy=function(){this.renderer.destroy(),this._signal("destroy",this),this.session&&this.session.destroy()},this.setAutoScrollEditorIntoView=function(e){if(!e)return;var t,n=this,r=!1;this.$scrollAnchor||(this.$scrollAnchor=document.createElement("div"));var i=this.$scrollAnchor;i.style.cssText="position:absolute",this.container.insertBefore(i,this.container.firstChild);var s=this.on("changeSelection",function(){r=!0}),o=this.renderer.on("beforeRender",function(){r&&(t=n.renderer.container.getBoundingClientRect())}),u=this.renderer.on("afterRender",function(){if(r&&t&&(n.isFocused()||n.searchBox&&n.searchBox.isFocused())){var e=n.renderer,s=e.$cursorLayer.$pixelPos,o=e.layerConfig,u=s.top-o.offset;s.top>=0&&u+t.top<0?r=!0:s.topwindow.innerHeight?r=!1:r=null,r!=null&&(i.style.top=u+"px",i.style.left=s.left+"px",i.style.height=o.lineHeight+"px",i.scrollIntoView(r)),r=t=null}});this.setAutoScrollEditorIntoView=function(e){if(e)return;delete this.setAutoScrollEditorIntoView,this.off("changeSelection",s),this.renderer.off("afterRender",u),this.renderer.off("beforeRender",o)}},this.$resetCursorStyle=function(){var e=this.$cursorStyle||"ace",t=this.renderer.$cursorLayer;if(!t)return;t.setSmoothBlinking(/smooth/.test(e)),t.isBlinking=!this.$readOnly&&e!="wide",i.setCssClass(t.element,"ace_slim-cursors",/slim/.test(e))}}.call(w.prototype),g.defineOptions(w.prototype,"editor",{selectionStyle:{set:function(e){this.onSelectionChange(),this._signal("changeSelectionStyle",{data:e})},initialValue:"line"},highlightActiveLine:{set:function(){this.$updateHighlightActiveLine()},initialValue:!0},highlightSelectedWord:{set:function(e){this.$onSelectionChange()},initialValue:!0},readOnly:{set:function(e){this.textInput.setReadOnly(e),this.$resetCursorStyle()},initialValue:!1},copyWithEmptySelection:{set:function(e){this.textInput.setCopyWithEmptySelection(e)},initialValue:!1},cursorStyle:{set:function(e){this.$resetCursorStyle()},values:["ace","slim","smooth","wide"],initialValue:"ace"},mergeUndoDeltas:{values:[!1,!0,"always"],initialValue:!0},behavioursEnabled:{initialValue:!0},wrapBehavioursEnabled:{initialValue:!0},autoScrollEditorIntoView:{set:function(e){this.setAutoScrollEditorIntoView(e)}},keyboardHandler:{set:function(e){this.setKeyboardHandler(e)},get:function(){return this.$keybindingId},handlesSet:!0},value:{set:function(e){this.session.setValue(e)},get:function(){return this.getValue()},handlesSet:!0,hidden:!0},session:{set:function(e){this.setSession(e)},get:function(){return this.session},handlesSet:!0,hidden:!0},showLineNumbers:{set:function(e){this.renderer.$gutterLayer.setShowLineNumbers(e),this.renderer.$loop.schedule(this.renderer.CHANGE_GUTTER),e&&this.$relativeLineNumbers?E.attach(this):E.detach(this)},initialValue:!0},relativeLineNumbers:{set:function(e){this.$showLineNumbers&&e?E.attach(this):E.detach(this)}},hScrollBarAlwaysVisible:"renderer",vScrollBarAlwaysVisible:"renderer",highlightGutterLine:"renderer",animatedScroll:"renderer",showInvisibles:"renderer",showPrintMargin:"renderer",printMarginColumn:"renderer",printMargin:"renderer",fadeFoldWidgets:"renderer",showFoldWidgets:"renderer",displayIndentGuides:"renderer",showGutter:"renderer",fontSize:"renderer",fontFamily:"renderer",maxLines:"renderer",minLines:"renderer",scrollPastEnd:"renderer",fixedWidthGutter:"renderer",theme:"renderer",hasCssTransforms:"renderer",maxPixelHeight:"renderer",useTextareaForIME:"renderer",scrollSpeed:"$mouseHandler",dragDelay:"$mouseHandler",dragEnabled:"$mouseHandler",focusTimeout:"$mouseHandler",tooltipFollowsMouse:"$mouseHandler",firstLineNumber:"session",overwrite:"session",newLineMode:"session",useWorker:"session",useSoftTabs:"session",navigateWithinSoftTabs:"session",tabSize:"session",wrap:"session",indentedSoftWrap:"session",foldStyle:"session",mode:"session"});var E={getText:function(e,t){return(Math.abs(e.selection.lead.row-t)||t+1+(t<9?"\u00b7":""))+""},getWidth:function(e,t,n){return Math.max(t.toString().length,(n.lastRow+1).toString().length,2)*n.characterWidth},update:function(e,t){t.renderer.$loop.schedule(t.renderer.CHANGE_GUTTER)},attach:function(e){e.renderer.$gutterLayer.$renderer=this,e.on("changeSelection",this.update),this.update(null,e)},detach:function(e){e.renderer.$gutterLayer.$renderer==this&&(e.renderer.$gutterLayer.$renderer=null),e.off("changeSelection",this.update),this.update(null,e)}};t.Editor=w}),define("ace/undomanager",["require","exports","module","ace/range"],function(e,t,n){"use strict";function i(e,t){for(var n=t;n--;){var r=e[n];if(r&&!r[0].ignore){while(n0){a.row+=i,a.column+=a.row==r.row?s:0;continue}!t&&l<=0&&(a.row=n.row,a.column=n.column,l===0&&(a.bias=1))}}function f(e){return{row:e.row,column:e.column}}function l(e){return{start:f(e.start),end:f(e.end),action:e.action,lines:e.lines.slice()}}function c(e){e=e||this;if(Array.isArray(e))return e.map(c).join("\n");var t="";e.action?(t=e.action=="insert"?"+":"-",t+="["+e.lines+"]"):e.value&&(Array.isArray(e.value)?t=e.value.map(h).join("\n"):t=h(e.value)),e.start&&(t+=h(e));if(e.id||e.rev)t+=" ("+(e.id||e.rev)+")";return t}function h(e){return e.start.row+":"+e.start.column+"=>"+e.end.row+":"+e.end.column}function p(e,t){var n=e.action=="insert",r=t.action=="insert";if(n&&r)if(o(t.start,e.end)>=0)m(t,e,-1);else{if(!(o(t.start,e.start)<=0))return null;m(e,t,1)}else if(n&&!r)if(o(t.start,e.end)>=0)m(t,e,-1);else{if(!(o(t.end,e.start)<=0))return null;m(e,t,-1)}else if(!n&&r)if(o(t.start,e.start)>=0)m(t,e,1);else{if(!(o(t.start,e.start)<=0))return null;m(e,t,1)}else if(!n&&!r)if(o(t.start,e.start)>=0)m(t,e,1);else{if(!(o(t.end,e.start)<=0))return null;m(e,t,-1)}return[t,e]}function d(e,t){for(var n=e.length;n--;)for(var r=0;r=0?m(e,t,-1):o(e.start,t.start)<=0?m(t,e,1):(m(e,s.fromPoints(t.start,e.start),-1),m(t,e,1));else if(!n&&r)o(t.start,e.end)>=0?m(t,e,-1):o(t.start,e.start)<=0?m(e,t,1):(m(t,s.fromPoints(e.start,t.start),-1),m(e,t,1));else if(!n&&!r)if(o(t.start,e.end)>=0)m(t,e,-1);else{if(!(o(t.end,e.start)<=0)){var i,u;return o(e.start,t.start)<0&&(i=e,e=y(e,t.start)),o(e.end,t.end)>0&&(u=y(e,t.end)),g(t.end,e.start,e.end,-1),u&&!i&&(e.lines=u.lines,e.start=u.start,e.end=u.end,u=e),[t,i,u].filter(Boolean)}m(e,t,-1)}return[t,e]}function m(e,t,n){g(e.start,t.start,t.end,n),g(e.end,t.start,t.end,n)}function g(e,t,n,r){e.row==(r==1?t:n).row&&(e.column+=r*(n.column-t.column)),e.row+=r*(n.row-t.row)}function y(e,t){var n=e.lines,r=e.end;e.end=f(t);var i=e.end.row-e.start.row,s=n.splice(i,n.length),o=i?t.column:t.column-e.start.column;n.push(s[0].substring(0,o)),s[0]=s[0].substr(o);var u={start:f(t),end:r,lines:s,action:e.action};return u}function b(e,t){t=l(t);for(var n=e.length;n--;){var r=e[n];for(var i=0;i0},this.canRedo=function(){return this.$redoStack.length>0},this.bookmark=function(e){e==undefined&&(e=this.$rev),this.mark=e},this.isAtBookmark=function(){return this.$rev===this.mark},this.toJSON=function(){},this.fromJSON=function(){},this.hasUndo=this.canUndo,this.hasRedo=this.canRedo,this.isClean=this.isAtBookmark,this.markClean=this.bookmark,this.$prettyPrint=function(e){return e?c(e):c(this.$undoStack)+"\n---\n"+c(this.$redoStack)}}).call(r.prototype);var s=e("./range").Range,o=s.comparePoints,u=s.comparePoints;t.UndoManager=r}),define("ace/layer/lines",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";var r=e("../lib/dom"),i=function(e,t){this.element=e,this.canvasHeight=t||5e5,this.element.style.height=this.canvasHeight*2+"px",this.cells=[],this.cellCache=[],this.$offsetCoefficient=0};(function(){this.moveContainer=function(e){r.translate(this.element,0,-(e.firstRowScreen*e.lineHeight%this.canvasHeight)-e.offset*this.$offsetCoefficient)},this.pageChanged=function(e,t){return Math.floor(e.firstRowScreen*e.lineHeight/this.canvasHeight)!==Math.floor(t.firstRowScreen*t.lineHeight/this.canvasHeight)},this.computeLineTop=function(e,t,n){var r=t.firstRowScreen*t.lineHeight,i=Math.floor(r/this.canvasHeight),s=n.documentToScreenRow(e,0)*t.lineHeight;return s-i*this.canvasHeight},this.computeLineHeight=function(e,t,n){return t.lineHeight*n.getRowLength(e)},this.getLength=function(){return this.cells.length},this.get=function(e){return this.cells[e]},this.shift=function(){this.$cacheCell(this.cells.shift())},this.pop=function(){this.$cacheCell(this.cells.pop())},this.push=function(e){if(Array.isArray(e)){this.cells.push.apply(this.cells,e);var t=r.createFragment(this.element);for(var n=0;ns&&(a=i.end.row+1,i=t.getNextFoldLine(a,i),s=i?i.start.row:Infinity);if(a>r){while(this.$lines.getLength()>u+1)this.$lines.pop();break}o=this.$lines.get(++u),o?o.row=a:(o=this.$lines.createCell(a,e,this.session,f),this.$lines.push(o)),this.$renderCell(o,e,i,a),a++}this._signal("afterRender"),this.$updateGutterWidth(e)},this.$updateGutterWidth=function(e){var t=this.session,n=t.gutterRenderer||this.$renderer,r=t.$firstLineNumber,i=this.$lines.last()?this.$lines.last().text:"";if(this.$fixedWidth||t.$useWrapMode)i=t.getLength()+r;var s=n?n.getWidth(t,i,e):i.toString().length*e.characterWidth,o=this.$padding||this.$computePadding();s+=o.left+o.right,s!==this.gutterWidth&&!isNaN(s)&&(this.gutterWidth=s,this.element.parentNode.style.width=this.element.style.width=Math.ceil(this.gutterWidth)+"px",this._signal("changeGutterWidth",s))},this.$updateCursorRow=function(){if(!this.$highlightGutterLine)return;var e=this.session.selection.getCursor();if(this.$cursorRow===e.row)return;this.$cursorRow=e.row},this.updateLineHighlight=function(){if(!this.$highlightGutterLine)return;var e=this.session.selection.cursor.row;this.$cursorRow=e;if(this.$cursorCell&&this.$cursorCell.row==e)return;this.$cursorCell&&(this.$cursorCell.element.className=this.$cursorCell.element.className.replace("ace_gutter-active-line ",""));var t=this.$lines.cells;this.$cursorCell=null;for(var n=0;n=this.$cursorRow){if(r.row>this.$cursorRow){var i=this.session.getFoldLine(this.$cursorRow);if(!(n>0&&i&&i.start.row==t[n-1].row))break;r=t[n-1]}r.element.className="ace_gutter-active-line "+r.element.className,this.$cursorCell=r;break}}},this.scrollLines=function(e){var t=this.config;this.config=e,this.$updateCursorRow();if(this.$lines.pageChanged(t,e))return this.update(e);this.$lines.moveContainer(e);var n=Math.min(e.lastRow+e.gutterOffset,this.session.getLength()-1),r=this.oldLastRow;this.oldLastRow=n;if(!t||r0;i--)this.$lines.shift();if(r>n)for(var i=this.session.getFoldedRowCount(n+1,r);i>0;i--)this.$lines.pop();e.firstRowr&&this.$lines.push(this.$renderLines(e,r+1,n)),this.updateLineHighlight(),this._signal("afterRender"),this.$updateGutterWidth(e)},this.$renderLines=function(e,t,n){var r=[],i=t,s=this.session.getNextFoldLine(i),o=s?s.start.row:Infinity;for(;;){i>o&&(i=s.end.row+1,s=this.session.getNextFoldLine(i,s),o=s?s.start.row:Infinity);if(i>n)break;var u=this.$lines.createCell(i,e,this.session,f);this.$renderCell(u,e,s,i),r.push(u),i++}return r},this.$renderCell=function(e,t,n,i){var s=e.element,o=this.session,u=s.childNodes[0],a=s.childNodes[1],f=o.$firstLineNumber,l=o.$breakpoints,c=o.$decorations,h=o.gutterRenderer||this.$renderer,p=this.$showFoldWidgets&&o.foldWidgets,d=n?n.start.row:Number.MAX_VALUE,v="ace_gutter-cell ";this.$highlightGutterLine&&(i==this.$cursorRow||n&&i=d&&this.$cursorRow<=n.end.row)&&(v+="ace_gutter-active-line ",this.$cursorCell!=e&&(this.$cursorCell&&(this.$cursorCell.element.className=this.$cursorCell.element.className.replace("ace_gutter-active-line ","")),this.$cursorCell=e)),l[i]&&(v+=l[i]),c[i]&&(v+=c[i]),this.$annotations[i]&&(v+=this.$annotations[i].className),s.className!=v&&(s.className=v);if(p){var m=p[i];m==null&&(m=p[i]=o.getFoldWidget(i))}if(m){var v="ace_fold-widget ace_"+m;m=="start"&&i==d&&in.right-t.right)return"foldWidgets"}}).call(a.prototype),t.Gutter=a}),define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"],function(e,t,n){"use strict";var r=e("../range").Range,i=e("../lib/dom"),s=function(e){this.element=i.createElement("div"),this.element.className="ace_layer ace_marker-layer",e.appendChild(this.element)};(function(){function e(e,t,n,r){return(e?1:0)|(t?2:0)|(n?4:0)|(r?8:0)}this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setMarkers=function(e){this.markers=e},this.elt=function(e,t){var n=this.i!=-1&&this.element.childNodes[this.i];n?this.i++:(n=document.createElement("div"),this.element.appendChild(n),this.i=-1),n.style.cssText=t,n.className=e},this.update=function(e){if(!e)return;this.config=e,this.i=0;var t;for(var n in this.markers){var r=this.markers[n];if(!r.range){r.update(t,this,this.session,e);continue}var i=r.range.clipRows(e.firstRow,e.lastRow);if(i.isEmpty())continue;i=i.toScreenRange(this.session);if(r.renderer){var s=this.$getTop(i.start.row,e),o=this.$padding+i.start.column*e.characterWidth;r.renderer(t,i,o,s,e)}else r.type=="fullLine"?this.drawFullLineMarker(t,i,r.clazz,e):r.type=="screenLine"?this.drawScreenLineMarker(t,i,r.clazz,e):i.isMultiLine()?r.type=="text"?this.drawTextMarker(t,i,r.clazz,e):this.drawMultiLineMarker(t,i,r.clazz,e):this.drawSingleLineMarker(t,i,r.clazz+" ace_start"+" ace_br15",e)}if(this.i!=-1)while(this.ip,l==f),s,l==f?0:1,o)},this.drawMultiLineMarker=function(e,t,n,r,i){var s=this.$padding,o=r.lineHeight,u=this.$getTop(t.start.row,r),a=s+t.start.column*r.characterWidth;i=i||"";if(this.session.$bidiHandler.isBidiRow(t.start.row)){var f=t.clone();f.end.row=f.start.row,f.end.column=this.session.getLine(f.start.row).length,this.drawBidiSingleLineMarker(e,f,n+" ace_br1 ace_start",r,null,i)}else this.elt(n+" ace_br1 ace_start","height:"+o+"px;"+"right:0;"+"top:"+u+"px;left:"+a+"px;"+(i||""));if(this.session.$bidiHandler.isBidiRow(t.end.row)){var f=t.clone();f.start.row=f.end.row,f.start.column=0,this.drawBidiSingleLineMarker(e,f,n+" ace_br12",r,null,i)}else{u=this.$getTop(t.end.row,r);var l=t.end.column*r.characterWidth;this.elt(n+" ace_br12","height:"+o+"px;"+"width:"+l+"px;"+"top:"+u+"px;"+"left:"+s+"px;"+(i||""))}o=(t.end.row-t.start.row-1)*r.lineHeight;if(o<=0)return;u=this.$getTop(t.start.row+1,r);var c=(t.start.column?1:0)|(t.end.column?0:8);this.elt(n+(c?" ace_br"+c:""),"height:"+o+"px;"+"right:0;"+"top:"+u+"px;"+"left:"+s+"px;"+(i||""))},this.drawSingleLineMarker=function(e,t,n,r,i,s){if(this.session.$bidiHandler.isBidiRow(t.start.row))return this.drawBidiSingleLineMarker(e,t,n,r,i,s);var o=r.lineHeight,u=(t.end.column+(i||0)-t.start.column)*r.characterWidth,a=this.$getTop(t.start.row,r),f=this.$padding+t.start.column*r.characterWidth;this.elt(n,"height:"+o+"px;"+"width:"+u+"px;"+"top:"+a+"px;"+"left:"+f+"px;"+(s||""))},this.drawBidiSingleLineMarker=function(e,t,n,r,i,s){var o=r.lineHeight,u=this.$getTop(t.start.row,r),a=this.$padding,f=this.session.$bidiHandler.getSelections(t.start.column,t.end.column);f.forEach(function(e){this.elt(n,"height:"+o+"px;"+"width:"+e.width+(i||0)+"px;"+"top:"+u+"px;"+"left:"+(a+e.left)+"px;"+(s||""))},this)},this.drawFullLineMarker=function(e,t,n,r,i){var s=this.$getTop(t.start.row,r),o=r.lineHeight;t.start.row!=t.end.row&&(o+=this.$getTop(t.end.row,r)-s),this.elt(n,"height:"+o+"px;"+"top:"+s+"px;"+"left:0;right:0;"+(i||""))},this.drawScreenLineMarker=function(e,t,n,r,i){var s=this.$getTop(t.start.row,r),o=r.lineHeight;this.elt(n,"height:"+o+"px;"+"top:"+s+"px;"+"left:0;right:0;"+(i||""))}}).call(s.prototype),t.Marker=s}),define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/layer/lines","ace/lib/event_emitter"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("../lib/dom"),s=e("../lib/lang"),o=e("./lines").Lines,u=e("../lib/event_emitter").EventEmitter,a=function(e){this.dom=i,this.element=this.dom.createElement("div"),this.element.className="ace_layer ace_text-layer",e.appendChild(this.element),this.$updateEolChar=this.$updateEolChar.bind(this),this.$lines=new o(this.element)};(function(){r.implement(this,u),this.EOF_CHAR="\u00b6",this.EOL_CHAR_LF="\u00ac",this.EOL_CHAR_CRLF="\u00a4",this.EOL_CHAR=this.EOL_CHAR_LF,this.TAB_CHAR="\u2014",this.SPACE_CHAR="\u00b7",this.$padding=0,this.MAX_LINE_LENGTH=1e4,this.$updateEolChar=function(){var e=this.session.doc,t=e.getNewLineCharacter()=="\n"&&e.getNewLineMode()!="windows",n=t?this.EOL_CHAR_LF:this.EOL_CHAR_CRLF;if(this.EOL_CHAR!=n)return this.EOL_CHAR=n,!0},this.setPadding=function(e){this.$padding=e,this.element.style.margin="0 "+e+"px"},this.getLineHeight=function(){return this.$fontMetrics.$characterSize.height||0},this.getCharacterWidth=function(){return this.$fontMetrics.$characterSize.width||0},this.$setFontMetrics=function(e){this.$fontMetrics=e,this.$fontMetrics.on("changeCharacterSize",function(e){this._signal("changeCharacterSize",e)}.bind(this)),this.$pollSizeChanges()},this.checkForSizeChanges=function(){this.$fontMetrics.checkForSizeChanges()},this.$pollSizeChanges=function(){return this.$pollSizeChangesTimer=this.$fontMetrics.$pollSizeChanges()},this.setSession=function(e){this.session=e,e&&this.$computeTabString()},this.showInvisibles=!1,this.setShowInvisibles=function(e){return this.showInvisibles==e?!1:(this.showInvisibles=e,this.$computeTabString(),!0)},this.displayIndentGuides=!0,this.setDisplayIndentGuides=function(e){return this.displayIndentGuides==e?!1:(this.displayIndentGuides=e,this.$computeTabString(),!0)},this.$tabStrings=[],this.onChangeTabSize=this.$computeTabString=function(){var e=this.session.getTabSize();this.tabSize=e;var t=this.$tabStrings=[0];for(var n=1;nl&&(u=a.end.row+1,a=this.session.getNextFoldLine(u,a),l=a?a.start.row:Infinity);if(u>i)break;var c=s[o++];if(c){this.dom.removeChildren(c),this.$renderLine(c,u,u==l?a:!1);var h=e.lineHeight*this.session.getRowLength(u)+"px";c.style.height!=h&&(f=!0,c.style.height=h)}u++}if(f)while(o0;i--)this.$lines.shift();if(t.lastRow>e.lastRow)for(var i=this.session.getFoldedRowCount(e.lastRow+1,t.lastRow);i>0;i--)this.$lines.pop();e.firstRowt.lastRow&&this.$lines.push(this.$renderLinesFragment(e,t.lastRow+1,e.lastRow))},this.$renderLinesFragment=function(e,t,n){var r=[],s=t,o=this.session.getNextFoldLine(s),u=o?o.start.row:Infinity;for(;;){s>u&&(s=o.end.row+1,o=this.session.getNextFoldLine(s,o),u=o?o.start.row:Infinity);if(s>n)break;var a=this.$lines.createCell(s,e,this.session),f=a.element;this.dom.removeChildren(f),i.setStyle(f.style,"height",this.$lines.computeLineHeight(s,e,this.session)+"px"),i.setStyle(f.style,"top",this.$lines.computeLineTop(s,e,this.session)+"px"),this.$renderLine(f,s,s==u?o:!1),this.$useLineGroups()?f.className="ace_line_group":f.className="ace_line",r.push(a),s++}return r},this.update=function(e){this.$lines.moveContainer(e),this.config=e;var t=e.firstRow,n=e.lastRow,r=this.$lines;while(r.getLength())r.pop();r.push(this.$renderLinesFragment(e,t,n))},this.$textToken={text:!0,rparen:!0,lparen:!0},this.$renderToken=function(e,t,n,r){var o=this,u=/(\t)|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\uFEFF\uFFF9-\uFFFC]+)|(\u3000)|([\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3001-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]|[\uD800-\uDBFF][\uDC00-\uDFFF])/g,a=this.dom.createFragment(this.element),f,l=0;while(f=u.exec(r)){var c=f[1],h=f[2],p=f[3],d=f[4],v=f[5];if(!o.showInvisibles&&h)continue;var m=l!=f.index?r.slice(l,f.index):"";l=f.index+f[0].length,m&&a.appendChild(this.dom.createTextNode(m,this.element));if(c){var g=o.session.getScreenTabSize(t+f.index);a.appendChild(o.$tabStrings[g].cloneNode(!0)),t+=g-1}else if(h)if(o.showInvisibles){var y=this.dom.createElement("span");y.className="ace_invisible ace_invisible_space",y.textContent=s.stringRepeat(o.SPACE_CHAR,h.length),a.appendChild(y)}else a.appendChild(this.com.createTextNode(h,this.element));else if(p){var y=this.dom.createElement("span");y.className="ace_invisible ace_invisible_space ace_invalid",y.textContent=s.stringRepeat(o.SPACE_CHAR,p.length),a.appendChild(y)}else if(d){var b=o.showInvisibles?o.SPACE_CHAR:"";t+=1;var y=this.dom.createElement("span");y.style.width=o.config.characterWidth*2+"px",y.className=o.showInvisibles?"ace_cjk ace_invisible ace_invisible_space":"ace_cjk",y.textContent=o.showInvisibles?o.SPACE_CHAR:"",a.appendChild(y)}else if(v){t+=1;var y=i.createElement("span");y.style.width=o.config.characterWidth*2+"px",y.className="ace_cjk",y.textContent=v,a.appendChild(y)}}a.appendChild(this.dom.createTextNode(l?r.slice(l):r,this.element));if(!this.$textToken[n.type]){var w="ace_"+n.type.replace(/\./g," ace_"),y=this.dom.createElement("span");n.type=="fold"&&(y.style.width=n.value.length*this.config.characterWidth+"px"),y.className=w,y.appendChild(a),e.appendChild(y)}else e.appendChild(a);return t+r.length},this.renderIndentGuide=function(e,t,n){var r=t.search(this.$indentGuideRe);if(r<=0||r>=n)return t;if(t[0]==" "){r-=r%this.tabSize;var i=r/this.tabSize;for(var s=0;s=o)u=this.$renderToken(a,u,l,c.substring(0,o-r)),c=c.substring(o-r),r=o,a=this.$createLineElement(),e.appendChild(a),a.appendChild(this.dom.createTextNode(s.stringRepeat("\u00a0",n.indent),this.element)),i++,u=0,o=n[i]||Number.MAX_VALUE;c.length!=0&&(r+=c.length,u=this.$renderToken(a,u,l,c))}}},this.$renderSimpleLine=function(e,t){var n=0,r=t[0],i=r.value;this.displayIndentGuides&&(i=this.renderIndentGuide(e,i)),i&&(n=this.$renderToken(e,n,r,i));for(var s=1;sthis.MAX_LINE_LENGTH)return this.$renderOverflowMessage(e,n,r,i);n=this.$renderToken(e,n,r,i)}},this.$renderOverflowMessage=function(e,t,n,r){this.$renderToken(e,t,n,r.slice(0,this.MAX_LINE_LENGTH-t));var i=this.dom.createElement("span");i.className="ace_inline_button ace_keyword ace_toggle_wrap",i.style.position="absolute",i.style.right="0",i.textContent="",e.appendChild(i)},this.$renderLine=function(e,t,n){!n&&n!=0&&(n=this.session.getFoldLine(t));if(n)var r=this.$getFoldLineTokens(t,n);else var r=this.session.getTokens(t);var i=e;if(r.length){var s=this.session.getRowSplitData(t);if(s&&s.length){this.$renderWrappedLine(e,r,s);var i=e.lastChild}else{var i=e;this.$useLineGroups()&&(i=this.$createLineElement(),e.appendChild(i)),this.$renderSimpleLine(i,r)}}else this.$useLineGroups()&&(i=this.$createLineElement(),e.appendChild(i));if(this.showInvisibles&&i){n&&(t=n.end.row);var o=this.dom.createElement("span");o.className="ace_invisible ace_invisible_eol",o.textContent=t==this.session.getLength()-1?this.EOF_CHAR:this.EOL_CHAR,i.appendChild(o)}},this.$getFoldLineTokens=function(e,t){function i(e,t,n){var i=0,s=0;while(s+e[i].value.lengthn-t&&(o=o.substring(0,n-t)),r.push({type:e[i].type,value:o}),s=t+o.length,i+=1}while(sn?r.push({type:e[i].type,value:o.substring(0,n-s)}):r.push(e[i]),s+=o.length,i+=1}}var n=this.session,r=[],s=n.getTokens(e);return t.walk(function(e,t,o,u,a){e!=null?r.push({type:"fold",value:e}):(a&&(s=n.getTokens(t)),s.length&&i(s,u,o))},t.end.row,this.session.getLine(t.end.row).length),r},this.$useLineGroups=function(){return this.session.getUseWrapMode()},this.destroy=function(){}}).call(a.prototype),t.Text=a}),define("ace/layer/cursor",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";var r=e("../lib/dom"),i=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_cursor-layer",e.appendChild(this.element),this.isVisible=!1,this.isBlinking=!0,this.blinkInterval=1e3,this.smoothBlinking=!1,this.cursors=[],this.cursor=this.addCursor(),r.addCssClass(this.element,"ace_hidden-cursors"),this.$updateCursors=this.$updateOpacity.bind(this)};(function(){this.$updateOpacity=function(e){var t=this.cursors;for(var n=t.length;n--;)r.setStyle(t[n].style,"opacity",e?"":"0")},this.$startCssAnimation=function(){var e=this.cursors;for(var t=e.length;t--;)e[t].style.animationDuration=this.blinkInterval+"ms";setTimeout(function(){r.addCssClass(this.element,"ace_animate-blinking")}.bind(this))},this.$stopCssAnimation=function(){r.removeCssClass(this.element,"ace_animate-blinking")},this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setBlinking=function(e){e!=this.isBlinking&&(this.isBlinking=e,this.restartTimer())},this.setBlinkInterval=function(e){e!=this.blinkInterval&&(this.blinkInterval=e,this.restartTimer())},this.setSmoothBlinking=function(e){e!=this.smoothBlinking&&(this.smoothBlinking=e,r.setCssClass(this.element,"ace_smooth-blinking",e),this.$updateCursors(!0),this.restartTimer())},this.addCursor=function(){var e=r.createElement("div");return e.className="ace_cursor",this.element.appendChild(e),this.cursors.push(e),e},this.removeCursor=function(){if(this.cursors.length>1){var e=this.cursors.pop();return e.parentNode.removeChild(e),e}},this.hideCursor=function(){this.isVisible=!1,r.addCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},this.showCursor=function(){this.isVisible=!0,r.removeCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},this.restartTimer=function(){var e=this.$updateCursors;clearInterval(this.intervalId),clearTimeout(this.timeoutId),this.$stopCssAnimation(),this.smoothBlinking&&r.removeCssClass(this.element,"ace_smooth-blinking"),e(!0);if(!this.isBlinking||!this.blinkInterval||!this.isVisible){this.$stopCssAnimation();return}this.smoothBlinking&&setTimeout(function(){r.addCssClass(this.element,"ace_smooth-blinking")}.bind(this));if(r.HAS_CSS_ANIMATION)this.$startCssAnimation();else{var t=function(){this.timeoutId=setTimeout(function(){e(!1)},.6*this.blinkInterval)}.bind(this);this.intervalId=setInterval(function(){e(!0),t()},this.blinkInterval),t()}},this.getPixelPosition=function(e,t){if(!this.config||!this.session)return{left:0,top:0};e||(e=this.session.selection.getCursor());var n=this.session.documentToScreenPosition(e),r=this.$padding+(this.session.$bidiHandler.isBidiRow(n.row,e.row)?this.session.$bidiHandler.getPosLeft(n.column):n.column*this.config.characterWidth),i=(n.row-(t?this.config.firstRowScreen:0))*this.config.lineHeight;return{left:r,top:i}},this.isCursorInView=function(e,t){return e.top>=0&&e.tope.height+e.offset||o.top<0)&&n>1)continue;var u=this.cursors[i++]||this.addCursor(),a=u.style;this.drawCursor?this.drawCursor(u,o,e,t[n],this.session):this.isCursorInView(o,e)?(r.setStyle(a,"display","block"),r.translate(u,o.left,o.top),r.setStyle(a,"width",Math.round(e.characterWidth)+"px"),r.setStyle(a,"height",e.lineHeight+"px")):r.setStyle(a,"display","none")}while(this.cursors.length>i)this.removeCursor();var f=this.session.getOverwrite();this.$setOverwrite(f),this.$pixelPos=o,this.restartTimer()},this.drawCursor=null,this.$setOverwrite=function(e){e!=this.overwrite&&(this.overwrite=e,e?r.addCssClass(this.element,"ace_overwrite-cursors"):r.removeCssClass(this.element,"ace_overwrite-cursors"))},this.destroy=function(){clearInterval(this.intervalId),clearTimeout(this.timeoutId)}}).call(i.prototype),t.Cursor=i}),define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./lib/dom"),s=e("./lib/event"),o=e("./lib/event_emitter").EventEmitter,u=32768,a=function(e){this.element=i.createElement("div"),this.element.className="ace_scrollbar ace_scrollbar"+this.classSuffix,this.inner=i.createElement("div"),this.inner.className="ace_scrollbar-inner",this.element.appendChild(this.inner),e.appendChild(this.element),this.setVisible(!1),this.skipEvent=!1,s.addListener(this.element,"scroll",this.onScroll.bind(this)),s.addListener(this.element,"mousedown",s.preventDefault)};(function(){r.implement(this,o),this.setVisible=function(e){this.element.style.display=e?"":"none",this.isVisible=e,this.coeff=1}}).call(a.prototype);var f=function(e,t){a.call(this,e),this.scrollTop=0,this.scrollHeight=0,t.$scrollbarWidth=this.width=i.scrollbarWidth(e.ownerDocument),this.inner.style.width=this.element.style.width=(this.width||15)+5+"px",this.$minWidth=0};r.inherits(f,a),function(){this.classSuffix="-v",this.onScroll=function(){if(!this.skipEvent){this.scrollTop=this.element.scrollTop;if(this.coeff!=1){var e=this.element.clientHeight/this.scrollHeight;this.scrollTop=this.scrollTop*(1-e)/(this.coeff-e)}this._emit("scroll",{data:this.scrollTop})}this.skipEvent=!1},this.getWidth=function(){return Math.max(this.isVisible?this.width:0,this.$minWidth||0)},this.setHeight=function(e){this.element.style.height=e+"px"},this.setInnerHeight=this.setScrollHeight=function(e){this.scrollHeight=e,e>u?(this.coeff=u/e,e=u):this.coeff!=1&&(this.coeff=1),this.inner.style.height=e+"px"},this.setScrollTop=function(e){this.scrollTop!=e&&(this.skipEvent=!0,this.scrollTop=e,this.element.scrollTop=e*this.coeff)}}.call(f.prototype);var l=function(e,t){a.call(this,e),this.scrollLeft=0,this.height=t.$scrollbarWidth,this.inner.style.height=this.element.style.height=(this.height||15)+5+"px"};r.inherits(l,a),function(){this.classSuffix="-h",this.onScroll=function(){this.skipEvent||(this.scrollLeft=this.element.scrollLeft,this._emit("scroll",{data:this.scrollLeft})),this.skipEvent=!1},this.getHeight=function(){return this.isVisible?this.height:0},this.setWidth=function(e){this.element.style.width=e+"px"},this.setInnerWidth=function(e){this.inner.style.width=e+"px"},this.setScrollWidth=function(e){this.inner.style.width=e+"px"},this.setScrollLeft=function(e){this.scrollLeft!=e&&(this.skipEvent=!0,this.scrollLeft=this.element.scrollLeft=e)}}.call(l.prototype),t.ScrollBar=f,t.ScrollBarV=f,t.ScrollBarH=l,t.VScrollBar=f,t.HScrollBar=l}),define("ace/renderloop",["require","exports","module","ace/lib/event"],function(e,t,n){"use strict";var r=e("./lib/event"),i=function(e,t){this.onRender=e,this.pending=!1,this.changes=0,this.window=t||window;var n=this;this._flush=function(e){var t=n.changes;t&&(r.blockIdle(100),n.changes=0,n.onRender(t)),n.changes&&n.schedule()}};(function(){this.schedule=function(e){this.changes=this.changes|e,this.changes&&r.nextFrame(this._flush)}}).call(i.prototype),t.RenderLoop=i}),define("ace/layer/font_metrics",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/lib/useragent","ace/lib/event_emitter"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/dom"),s=e("../lib/lang"),o=e("../lib/event"),u=e("../lib/useragent"),a=e("../lib/event_emitter").EventEmitter,f=256,l=typeof ResizeObserver=="function",c=200,h=t.FontMetrics=function(e){this.el=i.createElement("div"),this.$setMeasureNodeStyles(this.el.style,!0),this.$main=i.createElement("div"),this.$setMeasureNodeStyles(this.$main.style),this.$measureNode=i.createElement("div"),this.$setMeasureNodeStyles(this.$measureNode.style),this.el.appendChild(this.$main),this.el.appendChild(this.$measureNode),e.appendChild(this.el),this.$measureNode.innerHTML=s.stringRepeat("X",f),this.$characterSize={width:0,height:0},l?this.$addObserver():this.checkForSizeChanges()};(function(){r.implement(this,a),this.$characterSize={width:0,height:0},this.$setMeasureNodeStyles=function(e,t){e.width=e.height="auto",e.left=e.top="0px",e.visibility="hidden",e.position="absolute",e.whiteSpace="pre",u.isIE<8?e["font-family"]="inherit":e.font="inherit",e.overflow=t?"hidden":"visible"},this.checkForSizeChanges=function(e){e===undefined&&(e=this.$measureSizes());if(e&&(this.$characterSize.width!==e.width||this.$characterSize.height!==e.height)){this.$measureNode.style.fontWeight="bold";var t=this.$measureSizes();this.$measureNode.style.fontWeight="",this.$characterSize=e,this.charSizes=Object.create(null),this.allowBoldFonts=t&&t.width===e.width&&t.height===e.height,this._emit("changeCharacterSize",{data:e})}},this.$addObserver=function(){var e=this;this.$observer=new window.ResizeObserver(function(t){var n=t[0].contentRect;e.checkForSizeChanges({height:n.height,width:n.width/f})}),this.$observer.observe(this.$measureNode)},this.$pollSizeChanges=function(){if(this.$pollSizeChangesTimer||this.$observer)return this.$pollSizeChangesTimer;var e=this;return this.$pollSizeChangesTimer=o.onIdle(function t(){e.checkForSizeChanges(),o.onIdle(t,500)},500)},this.setPolling=function(e){e?this.$pollSizeChanges():this.$pollSizeChangesTimer&&(clearInterval(this.$pollSizeChangesTimer),this.$pollSizeChangesTimer=0)},this.$measureSizes=function(e){var t={height:(e||this.$measureNode).clientHeight,width:(e||this.$measureNode).clientWidth/f};return t.width===0||t.height===0?null:t},this.$measureCharWidth=function(e){this.$main.innerHTML=s.stringRepeat(e,f);var t=this.$main.getBoundingClientRect();return t.width/f},this.getCharacterWidth=function(e){var t=this.charSizes[e];return t===undefined&&(t=this.charSizes[e]=this.$measureCharWidth(e)/this.$characterSize.width),t},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.$observer&&this.$observer.disconnect(),this.el&&this.el.parentNode&&this.el.parentNode.removeChild(this.el)},this.$getZoom=function e(t){return t?(window.getComputedStyle(t).zoom||1)*e(t.parentElement):1},this.$initTransformMeasureNodes=function(){var e=function(e,t){return["div",{style:"position: absolute;top:"+e+"px;left:"+t+"px;"}]};this.els=i.buildDom([e(0,0),e(c,0),e(0,c),e(c,c)],this.el)},this.transformCoordinates=function(e,t){function r(e,t,n){var r=e[1]*t[0]-e[0]*t[1];return[(-t[1]*n[0]+t[0]*n[1])/r,(+e[1]*n[0]-e[0]*n[1])/r]}function i(e,t){return[e[0]-t[0],e[1]-t[1]]}function s(e,t){return[e[0]+t[0],e[1]+t[1]]}function o(e,t){return[e*t[0],e*t[1]]}function u(e){var t=e.getBoundingClientRect();return[t.left,t.top]}if(e){var n=this.$getZoom(this.el);e=o(1/n,e)}this.els||this.$initTransformMeasureNodes();var a=u(this.els[0]),f=u(this.els[1]),l=u(this.els[2]),h=u(this.els[3]),p=r(i(h,f),i(h,l),i(s(f,l),s(h,a))),d=o(1+p[0],i(f,a)),v=o(1+p[1],i(l,a));if(t){var m=t,g=p[0]*m[0]/c+p[1]*m[1]/c+1,y=s(o(m[0],d),o(m[1],v));return s(o(1/g/c,y),a)}var b=i(e,a),w=r(i(d,o(p[0],b)),i(v,o(p[1],b)),b);return o(c,w)}}).call(h.prototype)}),define("ace/virtual_renderer",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/config","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/scrollbar","ace/renderloop","ace/layer/font_metrics","ace/lib/event_emitter","ace/lib/useragent"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./lib/dom"),s=e("./config"),o=e("./layer/gutter").Gutter,u=e("./layer/marker").Marker,a=e("./layer/text").Text,f=e("./layer/cursor").Cursor,l=e("./scrollbar").HScrollBar,c=e("./scrollbar").VScrollBar,h=e("./renderloop").RenderLoop,p=e("./layer/font_metrics").FontMetrics,d=e("./lib/event_emitter").EventEmitter,v='.ace_br1 {border-top-left-radius : 3px;}.ace_br2 {border-top-right-radius : 3px;}.ace_br3 {border-top-left-radius : 3px; border-top-right-radius: 3px;}.ace_br4 {border-bottom-right-radius: 3px;}.ace_br5 {border-top-left-radius : 3px; border-bottom-right-radius: 3px;}.ace_br6 {border-top-right-radius : 3px; border-bottom-right-radius: 3px;}.ace_br7 {border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px;}.ace_br8 {border-bottom-left-radius : 3px;}.ace_br9 {border-top-left-radius : 3px; border-bottom-left-radius: 3px;}.ace_br10{border-top-right-radius : 3px; border-bottom-left-radius: 3px;}.ace_br11{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_br13{border-top-left-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_br14{border-top-right-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_br15{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_editor {position: relative;overflow: hidden;font: 12px/normal \'Monaco\', \'Menlo\', \'Ubuntu Mono\', \'Consolas\', \'source-code-pro\', monospace;direction: ltr;text-align: left;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}.ace_scroller {position: absolute;overflow: hidden;top: 0;bottom: 0;background-color: inherit;-ms-user-select: none;-moz-user-select: none;-webkit-user-select: none;user-select: none;cursor: text;}.ace_content {position: absolute;box-sizing: border-box;min-width: 100%;contain: style size layout;}.ace_dragging .ace_scroller:before{position: absolute;top: 0;left: 0;right: 0;bottom: 0;content: \'\';background: rgba(250, 250, 250, 0.01);z-index: 1000;}.ace_dragging.ace_dark .ace_scroller:before{background: rgba(0, 0, 0, 0.01);}.ace_selecting, .ace_selecting * {cursor: text !important;}.ace_gutter {position: absolute;overflow : hidden;width: auto;top: 0;bottom: 0;left: 0;cursor: default;z-index: 4;-ms-user-select: none;-moz-user-select: none;-webkit-user-select: none;user-select: none;contain: style size layout;}.ace_gutter-active-line {position: absolute;left: 0;right: 0;}.ace_scroller.ace_scroll-left {box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;}.ace_gutter-cell {position: absolute;top: 0;left: 0;right: 0;padding-left: 19px;padding-right: 6px;background-repeat: no-repeat;}.ace_gutter-cell.ace_error {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg==");background-repeat: no-repeat;background-position: 2px center;}.ace_gutter-cell.ace_warning {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg==");background-position: 2px center;}.ace_gutter-cell.ace_info {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII=");background-position: 2px center;}.ace_dark .ace_gutter-cell.ace_info {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC");}.ace_scrollbar {contain: strict;position: absolute;right: 0;bottom: 0;z-index: 6;}.ace_scrollbar-inner {position: absolute;cursor: text;left: 0;top: 0;}.ace_scrollbar-v{overflow-x: hidden;overflow-y: scroll;top: 0;}.ace_scrollbar-h {overflow-x: scroll;overflow-y: hidden;left: 0;}.ace_print-margin {position: absolute;height: 100%;}.ace_text-input {position: absolute;z-index: 0;width: 0.5em;height: 1em;opacity: 0;background: transparent;-moz-appearance: none;appearance: none;border: none;resize: none;outline: none;overflow: hidden;font: inherit;padding: 0 1px;margin: 0 -1px;contain: strict;-ms-user-select: text;-moz-user-select: text;-webkit-user-select: text;user-select: text;white-space: pre!important;}.ace_text-input.ace_composition {background: transparent;color: inherit;z-index: 1000;opacity: 1;}.ace_composition_placeholder { color: transparent }.ace_composition_marker { border-bottom: 1px solid;position: absolute;border-radius: 0;margin-top: 1px;}[ace_nocontext=true] {transform: none!important;filter: none!important;perspective: none!important;clip-path: none!important;mask : none!important;contain: none!important;perspective: none!important;mix-blend-mode: initial!important;z-index: auto;}.ace_layer {z-index: 1;position: absolute;overflow: hidden;word-wrap: normal;white-space: pre;height: 100%;width: 100%;box-sizing: border-box;pointer-events: none;}.ace_gutter-layer {position: relative;width: auto;text-align: right;pointer-events: auto;height: 1000000px;contain: style size layout;}.ace_text-layer {font: inherit !important;position: absolute;height: 1000000px;width: 1000000px;contain: style size layout;}.ace_text-layer > .ace_line, .ace_text-layer > .ace_line_group {contain: style size layout;position: absolute;top: 0;left: 0;right: 0;}.ace_hidpi .ace_text-layer,.ace_hidpi .ace_gutter-layer,.ace_hidpi .ace_content,.ace_hidpi .ace_gutter {contain: strict;will-change: transform;}.ace_hidpi .ace_text-layer > .ace_line, .ace_hidpi .ace_text-layer > .ace_line_group {contain: strict;}.ace_cjk {display: inline-block;text-align: center;}.ace_cursor-layer {z-index: 4;}.ace_cursor {z-index: 4;position: absolute;box-sizing: border-box;border-left: 2px solid;transform: translatez(0);}.ace_multiselect .ace_cursor {border-left-width: 1px;}.ace_slim-cursors .ace_cursor {border-left-width: 1px;}.ace_overwrite-cursors .ace_cursor {border-left-width: 0;border-bottom: 1px solid;}.ace_hidden-cursors .ace_cursor {opacity: 0.2;}.ace_smooth-blinking .ace_cursor {transition: opacity 0.18s;}.ace_animate-blinking .ace_cursor {animation-duration: 1000ms;animation-timing-function: step-end;animation-name: blink-ace-animate;animation-iteration-count: infinite;}.ace_animate-blinking.ace_smooth-blinking .ace_cursor {animation-duration: 1000ms;animation-timing-function: ease-in-out;animation-name: blink-ace-animate-smooth;}@keyframes blink-ace-animate {from, to { opacity: 1; }60% { opacity: 0; }}@keyframes blink-ace-animate-smooth {from, to { opacity: 1; }45% { opacity: 1; }60% { opacity: 0; }85% { opacity: 0; }}.ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {position: absolute;z-index: 3;}.ace_marker-layer .ace_selection {position: absolute;z-index: 5;}.ace_marker-layer .ace_bracket {position: absolute;z-index: 6;}.ace_marker-layer .ace_active-line {position: absolute;z-index: 2;}.ace_marker-layer .ace_selected-word {position: absolute;z-index: 4;box-sizing: border-box;}.ace_line .ace_fold {box-sizing: border-box;display: inline-block;height: 11px;margin-top: -2px;vertical-align: middle;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="),url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII=");background-repeat: no-repeat, repeat-x;background-position: center center, top left;color: transparent;border: 1px solid black;border-radius: 2px;cursor: pointer;pointer-events: auto;}.ace_dark .ace_fold {}.ace_fold:hover{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="),url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC");}.ace_tooltip {background-color: #FFF;background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));border: 1px solid gray;border-radius: 1px;box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);color: black;max-width: 100%;padding: 3px 4px;position: fixed;z-index: 999999;box-sizing: border-box;cursor: default;white-space: pre;word-wrap: break-word;line-height: normal;font-style: normal;font-weight: normal;letter-spacing: normal;pointer-events: none;}.ace_folding-enabled > .ace_gutter-cell {padding-right: 13px;}.ace_fold-widget {box-sizing: border-box;margin: 0 -12px 0 1px;display: none;width: 11px;vertical-align: top;background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==");background-repeat: no-repeat;background-position: center;border-radius: 3px;border: 1px solid transparent;cursor: pointer;}.ace_folding-enabled .ace_fold-widget {display: inline-block; }.ace_fold-widget.ace_end {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg==");}.ace_fold-widget.ace_closed {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA==");}.ace_fold-widget:hover {border: 1px solid rgba(0, 0, 0, 0.3);background-color: rgba(255, 255, 255, 0.2);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);}.ace_fold-widget:active {border: 1px solid rgba(0, 0, 0, 0.4);background-color: rgba(0, 0, 0, 0.05);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);}.ace_dark .ace_fold-widget {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC");}.ace_dark .ace_fold-widget.ace_end {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==");}.ace_dark .ace_fold-widget.ace_closed {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==");}.ace_dark .ace_fold-widget:hover {box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);background-color: rgba(255, 255, 255, 0.1);}.ace_dark .ace_fold-widget:active {box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);}.ace_inline_button {border: 1px solid lightgray;display: inline-block;margin: -1px 8px;padding: 0 5px;pointer-events: auto;cursor: pointer;}.ace_inline_button:hover {border-color: gray;background: rgba(200,200,200,0.2);display: inline-block;pointer-events: auto;}.ace_fold-widget.ace_invalid {background-color: #FFB4B4;border-color: #DE5555;}.ace_fade-fold-widgets .ace_fold-widget {transition: opacity 0.4s ease 0.05s;opacity: 0;}.ace_fade-fold-widgets:hover .ace_fold-widget {transition: opacity 0.05s ease 0.05s;opacity:1;}.ace_underline {text-decoration: underline;}.ace_bold {font-weight: bold;}.ace_nobold .ace_bold {font-weight: normal;}.ace_italic {font-style: italic;}.ace_error-marker {background-color: rgba(255, 0, 0,0.2);position: absolute;z-index: 9;}.ace_highlight-marker {background-color: rgba(255, 255, 0,0.2);position: absolute;z-index: 8;}.ace_text-input-ios {position: absolute !important;top: -100000px !important;left: -100000px !important;}',m=e("./lib/useragent"),g=m.isIE;i.importCssString(v,"ace_editor.css");var y=function(e,t){var n=this;this.container=e||i.createElement("div"),i.addCssClass(this.container,"ace_editor"),i.HI_DPI&&i.addCssClass(this.container,"ace_hidpi"),this.setTheme(t),this.$gutter=i.createElement("div"),this.$gutter.className="ace_gutter",this.container.appendChild(this.$gutter),this.$gutter.setAttribute("aria-hidden",!0),this.scroller=i.createElement("div"),this.scroller.className="ace_scroller",this.container.appendChild(this.scroller),this.content=i.createElement("div"),this.content.className="ace_content",this.scroller.appendChild(this.content),this.$gutterLayer=new o(this.$gutter),this.$gutterLayer.on("changeGutterWidth",this.onGutterResize.bind(this)),this.$markerBack=new u(this.content);var r=this.$textLayer=new a(this.content);this.canvas=r.element,this.$markerFront=new u(this.content),this.$cursorLayer=new f(this.content),this.$horizScroll=!1,this.$vScroll=!1,this.scrollBar=this.scrollBarV=new c(this.container,this),this.scrollBarH=new l(this.container,this),this.scrollBarV.addEventListener("scroll",function(e){n.$scrollAnimation||n.session.setScrollTop(e.data-n.scrollMargin.top)}),this.scrollBarH.addEventListener("scroll",function(e){n.$scrollAnimation||n.session.setScrollLeft(e.data-n.scrollMargin.left)}),this.scrollTop=0,this.scrollLeft=0,this.cursorPos={row:0,column:0},this.$fontMetrics=new p(this.container),this.$textLayer.$setFontMetrics(this.$fontMetrics),this.$textLayer.addEventListener("changeCharacterSize",function(e){n.updateCharacterSize(),n.onResize(!0,n.gutterWidth,n.$size.width,n.$size.height),n._signal("changeCharacterSize",e)}),this.$size={width:0,height:0,scrollerHeight:0,scrollerWidth:0,$dirty:!0},this.layerConfig={width:1,padding:0,firstRow:0,firstRowScreen:0,lastRow:0,lineHeight:0,characterWidth:0,minHeight:1,maxHeight:1,offset:0,height:1,gutterOffset:1},this.scrollMargin={left:0,right:0,top:0,bottom:0,v:0,h:0},this.margin={left:0,right:0,top:0,bottom:0,v:0,h:0},this.$keepTextAreaAtCursor=!0,this.$loop=new h(this.$renderChanges.bind(this),this.container.ownerDocument.defaultView),this.$loop.schedule(this.CHANGE_FULL),this.updateCharacterSize(),this.setPadding(4),s.resetOptions(this),s._emit("renderer",this)};(function(){this.CHANGE_CURSOR=1,this.CHANGE_MARKER=2,this.CHANGE_GUTTER=4,this.CHANGE_SCROLL=8,this.CHANGE_LINES=16,this.CHANGE_TEXT=32,this.CHANGE_SIZE=64,this.CHANGE_MARKER_BACK=128,this.CHANGE_MARKER_FRONT=256,this.CHANGE_FULL=512,this.CHANGE_H_SCROLL=1024,r.implement(this,d),this.updateCharacterSize=function(){this.$textLayer.allowBoldFonts!=this.$allowBoldFonts&&(this.$allowBoldFonts=this.$textLayer.allowBoldFonts,this.setStyle("ace_nobold",!this.$allowBoldFonts)),this.layerConfig.characterWidth=this.characterWidth=this.$textLayer.getCharacterWidth(),this.layerConfig.lineHeight=this.lineHeight=this.$textLayer.getLineHeight(),this.$updatePrintMargin()},this.setSession=function(e){this.session&&this.session.doc.off("changeNewLineMode",this.onChangeNewLineMode),this.session=e,e&&this.scrollMargin.top&&e.getScrollTop()<=0&&e.setScrollTop(-this.scrollMargin.top),this.$cursorLayer.setSession(e),this.$markerBack.setSession(e),this.$markerFront.setSession(e),this.$gutterLayer.setSession(e),this.$textLayer.setSession(e);if(!e)return;this.$loop.schedule(this.CHANGE_FULL),this.session.$setFontMetrics(this.$fontMetrics),this.scrollBarH.scrollLeft=this.scrollBarV.scrollTop=null,this.onChangeNewLineMode=this.onChangeNewLineMode.bind(this),this.onChangeNewLineMode(),this.session.doc.on("changeNewLineMode",this.onChangeNewLineMode)},this.updateLines=function(e,t,n){t===undefined&&(t=Infinity),this.$changedLines?(this.$changedLines.firstRow>e&&(this.$changedLines.firstRow=e),this.$changedLines.lastRowthis.layerConfig.lastRow)return;this.$loop.schedule(this.CHANGE_LINES)},this.onChangeNewLineMode=function(){this.$loop.schedule(this.CHANGE_TEXT),this.$textLayer.$updateEolChar(),this.session.$bidiHandler.setEolChar(this.$textLayer.EOL_CHAR)},this.onChangeTabSize=function(){this.$loop.schedule(this.CHANGE_TEXT|this.CHANGE_MARKER),this.$textLayer.onChangeTabSize()},this.updateText=function(){this.$loop.schedule(this.CHANGE_TEXT)},this.updateFull=function(e){e?this.$renderChanges(this.CHANGE_FULL,!0):this.$loop.schedule(this.CHANGE_FULL)},this.updateFontSize=function(){this.$textLayer.checkForSizeChanges()},this.$changes=0,this.$updateSizeAsync=function(){this.$loop.pending?this.$size.$dirty=!0:this.onResize()},this.onResize=function(e,t,n,r){if(this.resizing>2)return;this.resizing>0?this.resizing++:this.resizing=e?1:0;var i=this.container;r||(r=i.clientHeight||i.scrollHeight),n||(n=i.clientWidth||i.scrollWidth);var s=this.$updateCachedSize(e,t,n,r);if(!this.$size.scrollerHeight||!n&&!r)return this.resizing=0;e&&(this.$gutterLayer.$padding=null),e?this.$renderChanges(s|this.$changes,!0):this.$loop.schedule(s|this.$changes),this.resizing&&(this.resizing=0),this.scrollBarV.scrollLeft=this.scrollBarV.scrollTop=null},this.$updateCachedSize=function(e,t,n,r){r-=this.$extraHeight||0;var s=0,o=this.$size,u={width:o.width,height:o.height,scrollerHeight:o.scrollerHeight,scrollerWidth:o.scrollerWidth};r&&(e||o.height!=r)&&(o.height=r,s|=this.CHANGE_SIZE,o.scrollerHeight=o.height,this.$horizScroll&&(o.scrollerHeight-=this.scrollBarH.getHeight()),this.scrollBarV.element.style.bottom=this.scrollBarH.getHeight()+"px",s|=this.CHANGE_SCROLL);if(n&&(e||o.width!=n)){s|=this.CHANGE_SIZE,o.width=n,t==null&&(t=this.$showGutter?this.$gutter.offsetWidth:0),this.gutterWidth=t,i.setStyle(this.scrollBarH.element.style,"left",t+"px"),i.setStyle(this.scroller.style,"left",t+this.margin.left+"px"),o.scrollerWidth=Math.max(0,n-t-this.scrollBarV.getWidth()-this.margin.h),i.setStyle(this.$gutter.style,"left",this.margin.left+"px");var a=this.scrollBarV.getWidth()+"px";i.setStyle(this.scrollBarH.element.style,"right",a),i.setStyle(this.scroller.style,"right",a),i.setStyle(this.scroller.style,"bottom",this.scrollBarH.getHeight());if(this.session&&this.session.getUseWrapMode()&&this.adjustWrapLimit()||e)s|=this.CHANGE_FULL}return o.$dirty=!n||!r,s&&this._signal("resize",u),s},this.onGutterResize=function(e){var t=this.$showGutter?e:0;t!=this.gutterWidth&&(this.$changes|=this.$updateCachedSize(!0,t,this.$size.width,this.$size.height)),this.session.getUseWrapMode()&&this.adjustWrapLimit()?this.$loop.schedule(this.CHANGE_FULL):this.$size.$dirty?this.$loop.schedule(this.CHANGE_FULL):this.$computeLayerConfig()},this.adjustWrapLimit=function(){var e=this.$size.scrollerWidth-this.$padding*2,t=Math.floor(e/this.characterWidth);return this.session.adjustWrapLimit(t,this.$showPrintMargin&&this.$printMarginColumn)},this.setAnimatedScroll=function(e){this.setOption("animatedScroll",e)},this.getAnimatedScroll=function(){return this.$animatedScroll},this.setShowInvisibles=function(e){this.setOption("showInvisibles",e),this.session.$bidiHandler.setShowInvisibles(e)},this.getShowInvisibles=function(){return this.getOption("showInvisibles")},this.getDisplayIndentGuides=function(){return this.getOption("displayIndentGuides")},this.setDisplayIndentGuides=function(e){this.setOption("displayIndentGuides",e)},this.setShowPrintMargin=function(e){this.setOption("showPrintMargin",e)},this.getShowPrintMargin=function(){return this.getOption("showPrintMargin")},this.setPrintMarginColumn=function(e){this.setOption("printMarginColumn",e)},this.getPrintMarginColumn=function(){return this.getOption("printMarginColumn")},this.getShowGutter=function(){return this.getOption("showGutter")},this.setShowGutter=function(e){return this.setOption("showGutter",e)},this.getFadeFoldWidgets=function(){return this.getOption("fadeFoldWidgets")},this.setFadeFoldWidgets=function(e){this.setOption("fadeFoldWidgets",e)},this.setHighlightGutterLine=function(e){this.setOption("highlightGutterLine",e)},this.getHighlightGutterLine=function(){return this.getOption("highlightGutterLine")},this.$updatePrintMargin=function(){if(!this.$showPrintMargin&&!this.$printMarginEl)return;if(!this.$printMarginEl){var e=i.createElement("div");e.className="ace_layer ace_print-margin-layer",this.$printMarginEl=i.createElement("div"),this.$printMarginEl.className="ace_print-margin",e.appendChild(this.$printMarginEl),this.content.insertBefore(e,this.content.firstChild)}var t=this.$printMarginEl.style;t.left=Math.round(this.characterWidth*this.$printMarginColumn+this.$padding)+"px",t.visibility=this.$showPrintMargin?"visible":"hidden",this.session&&this.session.$wrap==-1&&this.adjustWrapLimit()},this.getContainerElement=function(){return this.container},this.getMouseEventTarget=function(){return this.scroller},this.getTextAreaContainer=function(){return this.container},this.$moveTextAreaToCursor=function(){var e=this.textarea.style;if(!this.$keepTextAreaAtCursor){i.translate(this.textarea,-100,0);return}var t=this.$cursorLayer.$pixelPos;if(!t)return;var n=this.$composition;n&&n.markerRange&&(t=this.$cursorLayer.getPixelPosition(n.markerRange.start,!0));var r=this.layerConfig,s=t.top,o=t.left;s-=r.offset;var u=n&&n.useTextareaForIME?this.lineHeight:g?0:1;if(s<0||s>r.height-u){i.translate(this.textarea,0,0);return}var a=1;if(!n)s+=this.lineHeight;else if(n.useTextareaForIME){var f=this.textarea.value;a=this.characterWidth*this.session.$getStringScreenWidth(f)[0],u+=2}else s+=this.lineHeight+2;o-=this.scrollLeft,o>this.$size.scrollerWidth-a&&(o=this.$size.scrollerWidth-a),o+=this.gutterWidth+this.margin.left,i.setStyle(e,"height",u+"px"),i.setStyle(e,"width",a+"px"),i.translate(this.textarea,Math.min(o,this.$size.scrollerWidth-a),Math.min(s,this.$size.height-u))},this.getFirstVisibleRow=function(){return this.layerConfig.firstRow},this.getFirstFullyVisibleRow=function(){return this.layerConfig.firstRow+(this.layerConfig.offset===0?0:1)},this.getLastFullyVisibleRow=function(){var e=this.layerConfig,t=e.lastRow,n=this.session.documentToScreenRow(t,0)*e.lineHeight;return n-this.session.getScrollTop()>e.height-e.lineHeight?t-1:t},this.getLastVisibleRow=function(){return this.layerConfig.lastRow},this.$padding=null,this.setPadding=function(e){this.$padding=e,this.$textLayer.setPadding(e),this.$cursorLayer.setPadding(e),this.$markerFront.setPadding(e),this.$markerBack.setPadding(e),this.$loop.schedule(this.CHANGE_FULL),this.$updatePrintMargin()},this.setScrollMargin=function(e,t,n,r){var i=this.scrollMargin;i.top=e|0,i.bottom=t|0,i.right=r|0,i.left=n|0,i.v=i.top+i.bottom,i.h=i.left+i.right,i.top&&this.scrollTop<=0&&this.session&&this.session.setScrollTop(-i.top),this.updateFull()},this.setMargin=function(e,t,n,r){var i=this.margin;i.top=e|0,i.bottom=t|0,i.right=r|0,i.left=n|0,i.v=i.top+i.bottom,i.h=i.left+i.right,this.$updateCachedSize(!0,this.gutterWidth,this.$size.width,this.$size.height),this.updateFull()},this.getHScrollBarAlwaysVisible=function(){return this.$hScrollBarAlwaysVisible},this.setHScrollBarAlwaysVisible=function(e){this.setOption("hScrollBarAlwaysVisible",e)},this.getVScrollBarAlwaysVisible=function(){return this.$vScrollBarAlwaysVisible},this.setVScrollBarAlwaysVisible=function(e){this.setOption("vScrollBarAlwaysVisible",e)},this.$updateScrollBarV=function(){var e=this.layerConfig.maxHeight,t=this.$size.scrollerHeight;!this.$maxLines&&this.$scrollPastEnd&&(e-=(t-this.lineHeight)*this.$scrollPastEnd,this.scrollTop>e-t&&(e=this.scrollTop+t,this.scrollBarV.scrollTop=null)),this.scrollBarV.setScrollHeight(e+this.scrollMargin.v),this.scrollBarV.setScrollTop(this.scrollTop+this.scrollMargin.top)},this.$updateScrollBarH=function(){this.scrollBarH.setScrollWidth(this.layerConfig.width+2*this.$padding+this.scrollMargin.h),this.scrollBarH.setScrollLeft(this.scrollLeft+this.scrollMargin.left)},this.$frozen=!1,this.freeze=function(){this.$frozen=!0},this.unfreeze=function(){this.$frozen=!1},this.$renderChanges=function(e,t){this.$changes&&(e|=this.$changes,this.$changes=0);if(!this.session||!this.container.offsetWidth||this.$frozen||!e&&!t){this.$changes|=e;return}if(this.$size.$dirty)return this.$changes|=e,this.onResize(!0);this.lineHeight||this.$textLayer.checkForSizeChanges(),this._signal("beforeRender"),this.session&&this.session.$bidiHandler&&this.session.$bidiHandler.updateCharacterWidths(this.$fontMetrics);var n=this.layerConfig;if(e&this.CHANGE_FULL||e&this.CHANGE_SIZE||e&this.CHANGE_TEXT||e&this.CHANGE_LINES||e&this.CHANGE_SCROLL||e&this.CHANGE_H_SCROLL){e|=this.$computeLayerConfig();if(n.firstRow!=this.layerConfig.firstRow&&n.firstRowScreen==this.layerConfig.firstRowScreen){var r=this.scrollTop+(n.firstRow-this.layerConfig.firstRow)*this.lineHeight;r>0&&(this.scrollTop=r,e|=this.CHANGE_SCROLL,e|=this.$computeLayerConfig())}n=this.layerConfig,this.$updateScrollBarV(),e&this.CHANGE_H_SCROLL&&this.$updateScrollBarH(),i.translate(this.content,-this.scrollLeft,-n.offset);var s=n.width+2*this.$padding+"px",o=n.minHeight+"px";i.setStyle(this.content.style,"width",s),i.setStyle(this.content.style,"height",o)}e&this.CHANGE_H_SCROLL&&(i.translate(this.content,-this.scrollLeft,-n.offset),this.scroller.className=this.scrollLeft<=0?"ace_scroller":"ace_scroller ace_scroll-left");if(e&this.CHANGE_FULL){this.$textLayer.update(n),this.$showGutter&&this.$gutterLayer.update(n),this.$markerBack.update(n),this.$markerFront.update(n),this.$cursorLayer.update(n),this.$moveTextAreaToCursor(),this._signal("afterRender");return}if(e&this.CHANGE_SCROLL){e&this.CHANGE_TEXT||e&this.CHANGE_LINES?this.$textLayer.update(n):this.$textLayer.scrollLines(n),this.$showGutter&&(e&this.CHANGE_GUTTER||e&this.CHANGE_LINES?this.$gutterLayer.update(n):this.$gutterLayer.scrollLines(n)),this.$markerBack.update(n),this.$markerFront.update(n),this.$cursorLayer.update(n),this.$moveTextAreaToCursor(),this._signal("afterRender");return}e&this.CHANGE_TEXT?(this.$textLayer.update(n),this.$showGutter&&this.$gutterLayer.update(n)):e&this.CHANGE_LINES?(this.$updateLines()||e&this.CHANGE_GUTTER&&this.$showGutter)&&this.$gutterLayer.update(n):e&this.CHANGE_TEXT||e&this.CHANGE_GUTTER?this.$showGutter&&this.$gutterLayer.update(n):e&this.CHANGE_CURSOR&&this.$highlightGutterLine&&this.$gutterLayer.updateLineHighlight(n),e&this.CHANGE_CURSOR&&(this.$cursorLayer.update(n),this.$moveTextAreaToCursor()),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_FRONT)&&this.$markerFront.update(n),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_BACK)&&this.$markerBack.update(n),this._signal("afterRender")},this.$autosize=function(){var e=this.session.getScreenLength()*this.lineHeight,t=this.$maxLines*this.lineHeight,n=Math.min(t,Math.max((this.$minLines||1)*this.lineHeight,e))+this.scrollMargin.v+(this.$extraHeight||0);this.$horizScroll&&(n+=this.scrollBarH.getHeight()),this.$maxPixelHeight&&n>this.$maxPixelHeight&&(n=this.$maxPixelHeight);var r=n<=2*this.lineHeight,i=!r&&e>t;if(n!=this.desiredHeight||this.$size.height!=this.desiredHeight||i!=this.$vScroll){i!=this.$vScroll&&(this.$vScroll=i,this.scrollBarV.setVisible(i));var s=this.container.clientWidth;this.container.style.height=n+"px",this.$updateCachedSize(!0,this.$gutterWidth,s,n),this.desiredHeight=n,this._signal("autosize")}},this.$computeLayerConfig=function(){var e=this.session,t=this.$size,n=t.height<=2*this.lineHeight,r=this.session.getScreenLength(),i=r*this.lineHeight,s=this.$getLongestLine(),o=!n&&(this.$hScrollBarAlwaysVisible||t.scrollerWidth-s-2*this.$padding<0),u=this.$horizScroll!==o;u&&(this.$horizScroll=o,this.scrollBarH.setVisible(o));var a=this.$vScroll;this.$maxLines&&this.lineHeight>1&&this.$autosize();var f=this.scrollTop%this.lineHeight,l=t.scrollerHeight+this.lineHeight,c=!this.$maxLines&&this.$scrollPastEnd?(t.scrollerHeight-this.lineHeight)*this.$scrollPastEnd:0;i+=c;var h=this.scrollMargin;this.session.setScrollTop(Math.max(-h.top,Math.min(this.scrollTop,i-t.scrollerHeight+h.bottom))),this.session.setScrollLeft(Math.max(-h.left,Math.min(this.scrollLeft,s+2*this.$padding-t.scrollerWidth+h.right)));var p=!n&&(this.$vScrollBarAlwaysVisible||t.scrollerHeight-i+c<0||this.scrollTop>h.top),d=a!==p;d&&(this.$vScroll=p,this.scrollBarV.setVisible(p));var v=Math.ceil(l/this.lineHeight)-1,m=Math.max(0,Math.round((this.scrollTop-f)/this.lineHeight)),g=m+v,y,b,w=this.lineHeight;m=e.screenToDocumentRow(m,0);var E=e.getFoldLine(m);E&&(m=E.start.row),y=e.documentToScreenRow(m,0),b=e.getRowLength(m)*w,g=Math.min(e.screenToDocumentRow(g,0),e.getLength()-1),l=t.scrollerHeight+e.getRowLength(g)*w+b,f=this.scrollTop-y*w;var S=0;if(this.layerConfig.width!=s||u)S=this.CHANGE_H_SCROLL;if(u||d)S=this.$updateCachedSize(!0,this.gutterWidth,t.width,t.height),this._signal("scrollbarVisibilityChanged"),d&&(s=this.$getLongestLine());return this.layerConfig={width:s,padding:this.$padding,firstRow:m,firstRowScreen:y,lastRow:g,lineHeight:w,characterWidth:this.characterWidth,minHeight:l,maxHeight:i,offset:f,gutterOffset:w?Math.max(0,Math.ceil((f+t.height-t.scrollerHeight)/w)):0,height:this.$size.scrollerHeight},this.session.$bidiHandler&&this.session.$bidiHandler.setContentWidth(s-this.$padding),S},this.$updateLines=function(){if(!this.$changedLines)return;var e=this.$changedLines.firstRow,t=this.$changedLines.lastRow;this.$changedLines=null;var n=this.layerConfig;if(e>n.lastRow+1)return;if(tthis.$textLayer.MAX_LINE_LENGTH&&(e=this.$textLayer.MAX_LINE_LENGTH+30),Math.max(this.$size.scrollerWidth-2*this.$padding,Math.round(e*this.characterWidth))},this.updateFrontMarkers=function(){this.$markerFront.setMarkers(this.session.getMarkers(!0)),this.$loop.schedule(this.CHANGE_MARKER_FRONT)},this.updateBackMarkers=function(){this.$markerBack.setMarkers(this.session.getMarkers()),this.$loop.schedule(this.CHANGE_MARKER_BACK)},this.addGutterDecoration=function(e,t){this.$gutterLayer.addGutterDecoration(e,t)},this.removeGutterDecoration=function(e,t){this.$gutterLayer.removeGutterDecoration(e,t)},this.updateBreakpoints=function(e){this.$loop.schedule(this.CHANGE_GUTTER)},this.setAnnotations=function(e){this.$gutterLayer.setAnnotations(e),this.$loop.schedule(this.CHANGE_GUTTER)},this.updateCursor=function(){this.$loop.schedule(this.CHANGE_CURSOR)},this.hideCursor=function(){this.$cursorLayer.hideCursor()},this.showCursor=function(){this.$cursorLayer.showCursor()},this.scrollSelectionIntoView=function(e,t,n){this.scrollCursorIntoView(e,n),this.scrollCursorIntoView(t,n)},this.scrollCursorIntoView=function(e,t,n){if(this.$size.scrollerHeight===0)return;var r=this.$cursorLayer.getPixelPosition(e),i=r.left,s=r.top,o=n&&n.top||0,u=n&&n.bottom||0,a=this.$scrollAnimation?this.session.getScrollTop():this.scrollTop;a+o>s?(t&&a+o>s+this.lineHeight&&(s-=t*this.$size.scrollerHeight),s===0&&(s=-this.scrollMargin.top),this.session.setScrollTop(s)):a+this.$size.scrollerHeight-ui?(i=1-this.scrollMargin.top)return!0;if(t>0&&this.session.getScrollTop()+this.$size.scrollerHeight-this.layerConfig.maxHeight<-1+this.scrollMargin.bottom)return!0;if(e<0&&this.session.getScrollLeft()>=1-this.scrollMargin.left)return!0;if(e>0&&this.session.getScrollLeft()+this.$size.scrollerWidth-this.layerConfig.width<-1+this.scrollMargin.right)return!0},this.pixelToScreenCoordinates=function(e,t){var n;if(this.$hasCssTransforms){n={top:0,left:0};var r=this.$fontMetrics.transformCoordinates([e,t]);e=r[1]-this.gutterWidth-this.margin.left,t=r[0]}else n=this.scroller.getBoundingClientRect();var i=e+this.scrollLeft-n.left-this.$padding,s=i/this.characterWidth,o=Math.floor((t+this.scrollTop-n.top)/this.lineHeight),u=this.$blockCursor?Math.floor(s):Math.round(s);return{row:o,column:u,side:s-u>0?1:-1,offsetX:i}},this.screenToTextCoordinates=function(e,t){var n;if(this.$hasCssTransforms){n={top:0,left:0};var r=this.$fontMetrics.transformCoordinates([e,t]);e=r[1]-this.gutterWidth-this.margin.left,t=r[0]}else n=this.scroller.getBoundingClientRect();var i=e+this.scrollLeft-n.left-this.$padding,s=i/this.characterWidth,o=this.$blockCursor?Math.floor(s):Math.round(s),u=Math.floor((t+this.scrollTop-n.top)/this.lineHeight);return this.session.screenToDocumentPosition(u,Math.max(o,0),i)},this.textToScreenCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=this.session.documentToScreenPosition(e,t),i=this.$padding+(this.session.$bidiHandler.isBidiRow(r.row,e)?this.session.$bidiHandler.getPosLeft(r.column):Math.round(r.column*this.characterWidth)),s=r.row*this.lineHeight;return{pageX:n.left+i-this.scrollLeft,pageY:n.top+s-this.scrollTop}},this.visualizeFocus=function(){i.addCssClass(this.container,"ace_focus")},this.visualizeBlur=function(){i.removeCssClass(this.container,"ace_focus")},this.showComposition=function(e){this.$composition=e,e.cssText||(e.cssText=this.textarea.style.cssText,e.keepTextAreaAtCursor=this.$keepTextAreaAtCursor),e.useTextareaForIME=this.$useTextareaForIME,this.$useTextareaForIME?(this.$keepTextAreaAtCursor=!0,i.addCssClass(this.textarea,"ace_composition"),this.textarea.style.cssText="",this.$moveTextAreaToCursor(),this.$cursorLayer.element.style.display="none"):e.markerId=this.session.addMarker(e.markerRange,"ace_composition_marker","text")},this.setCompositionText=function(e){var t=this.session.selection.cursor;this.addToken(e,"composition_placeholder",t.row,t.column),this.$moveTextAreaToCursor()},this.hideComposition=function(){if(!this.$composition)return;this.$composition.markerId&&this.session.removeMarker(this.$composition.markerId),i.removeCssClass(this.textarea,"ace_composition"),this.$keepTextAreaAtCursor=this.$composition.keepTextAreaAtCursor,this.textarea.style.cssText=this.$composition.cssText,this.$composition=null,this.$cursorLayer.element.style.display=""},this.addToken=function(e,t,n,r){var i=this.session;i.bgTokenizer.lines[n]=null;var s={type:t,value:e},o=i.getTokens(n);if(r==null)o.push(s);else{var u=0;for(var a=0;a50&&e.length>this.$doc.getLength()>>1?this.call("setValue",[this.$doc.getValue()]):this.emit("change",{data:e})}}).call(f.prototype);var l=function(e,t,n){this.$sendDeltaQueue=this.$sendDeltaQueue.bind(this),this.changeListener=this.changeListener.bind(this),this.callbackId=1,this.callbacks={},this.messageBuffer=[];var r=null,i=!1,u=Object.create(s),a=this;this.$worker={},this.$worker.terminate=function(){},this.$worker.postMessage=function(e){a.messageBuffer.push(e),r&&(i?setTimeout(f):f())},this.setEmitSync=function(e){i=e};var f=function(){var e=a.messageBuffer.shift();e.command?r[e.command].apply(r,e.args):e.event&&u._signal(e.event,e.data)};u.postMessage=function(e){a.onMessage({data:e})},u.callback=function(e,t){this.postMessage({type:"call",id:t,data:e})},u.emit=function(e,t){this.postMessage({type:"event",name:e,data:t})},o.loadModule(["worker",t],function(e){r=new e[n](u);while(a.messageBuffer.length)f()})};l.prototype=f.prototype,t.UIWorkerClient=l,t.WorkerClient=f,t.createWorker=a}),define("ace/placeholder",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/oop"],function(e,t,n){"use strict";var r=e("./range").Range,i=e("./lib/event_emitter").EventEmitter,s=e("./lib/oop"),o=function(e,t,n,r,i,s){var o=this;this.length=t,this.session=e,this.doc=e.getDocument(),this.mainClass=i,this.othersClass=s,this.$onUpdate=this.onUpdate.bind(this),this.doc.on("change",this.$onUpdate),this.$others=r,this.$onCursorChange=function(){setTimeout(function(){o.onCursorChange()})},this.$pos=n;var u=e.getUndoManager().$undoStack||e.getUndoManager().$undostack||{length:-1};this.$undoStackDepth=u.length,this.setup(),e.selection.on("changeCursor",this.$onCursorChange)};(function(){s.implement(this,i),this.setup=function(){var e=this,t=this.doc,n=this.session;this.selectionBefore=n.selection.toJSON(),n.selection.inMultiSelectMode&&n.selection.toSingleRange(),this.pos=t.createAnchor(this.$pos.row,this.$pos.column);var i=this.pos;i.$insertRight=!0,i.detach(),i.markerId=n.addMarker(new r(i.row,i.column,i.row,i.column+this.length),this.mainClass,null,!1),this.others=[],this.$others.forEach(function(n){var r=t.createAnchor(n.row,n.column);r.$insertRight=!0,r.detach(),e.others.push(r)}),n.setUndoSelect(!1)},this.showOtherMarkers=function(){if(this.othersActive)return;var e=this.session,t=this;this.othersActive=!0,this.others.forEach(function(n){n.markerId=e.addMarker(new r(n.row,n.column,n.row,n.column+t.length),t.othersClass,null,!1)})},this.hideOtherMarkers=function(){if(!this.othersActive)return;this.othersActive=!1;for(var e=0;e=this.pos.column&&t.start.column<=this.pos.column+this.length+1,s=t.start.column-this.pos.column;this.updateAnchors(e),i&&(this.length+=n);if(i&&!this.session.$fromUndo)if(e.action==="insert")for(var o=this.others.length-1;o>=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};this.doc.insertMergedLines(a,e.lines)}else if(e.action==="remove")for(var o=this.others.length-1;o>=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};this.doc.remove(new r(a.row,a.column,a.row,a.column-n))}this.$updating=!1,this.updateMarkers()},this.updateAnchors=function(e){this.pos.onChange(e);for(var t=this.others.length;t--;)this.others[t].onChange(e);this.updateMarkers()},this.updateMarkers=function(){if(this.$updating)return;var e=this,t=this.session,n=function(n,i){t.removeMarker(n.markerId),n.markerId=t.addMarker(new r(n.row,n.column,n.row,n.column+e.length),i,null,!1)};n(this.pos,this.mainClass);for(var i=this.others.length;i--;)n(this.others[i],this.othersClass)},this.onCursorChange=function(e){if(this.$updating||!this.session)return;var t=this.session.selection.getCursor();t.row===this.pos.row&&t.column>=this.pos.column&&t.column<=this.pos.column+this.length?(this.showOtherMarkers(),this._emit("cursorEnter",e)):(this.hideOtherMarkers(),this._emit("cursorLeave",e))},this.detach=function(){this.session.removeMarker(this.pos&&this.pos.markerId),this.hideOtherMarkers(),this.doc.removeEventListener("change",this.$onUpdate),this.session.selection.removeEventListener("changeCursor",this.$onCursorChange),this.session.setUndoSelect(!0),this.session=null},this.cancel=function(){if(this.$undoStackDepth===-1)return;var e=this.session.getUndoManager(),t=(e.$undoStack||e.$undostack).length-this.$undoStackDepth;for(var n=0;n1&&!this.inMultiSelectMode&&(this._signal("multiSelect"),this.inMultiSelectMode=!0,this.session.$undoSelect=!1,this.rangeList.attach(this.session)),t||this.fromOrientedRange(e)},this.toSingleRange=function(e){e=e||this.ranges[0];var t=this.rangeList.removeAll();t.length&&this.$onRemoveRange(t),e&&this.fromOrientedRange(e)},this.substractPoint=function(e){var t=this.rangeList.substractPoint(e);if(t)return this.$onRemoveRange(t),t[0]},this.mergeOverlappingRanges=function(){var e=this.rangeList.merge();e.length&&this.$onRemoveRange(e)},this.$onAddRange=function(e){this.rangeCount=this.rangeList.ranges.length,this.ranges.unshift(e),this._signal("addRange",{range:e})},this.$onRemoveRange=function(e){this.rangeCount=this.rangeList.ranges.length;if(this.rangeCount==1&&this.inMultiSelectMode){var t=this.rangeList.ranges.pop();e.push(t),this.rangeCount=0}for(var n=e.length;n--;){var r=this.ranges.indexOf(e[n]);this.ranges.splice(r,1)}this._signal("removeRange",{ranges:e}),this.rangeCount===0&&this.inMultiSelectMode&&(this.inMultiSelectMode=!1,this._signal("singleSelect"),this.session.$undoSelect=!0,this.rangeList.detach(this.session)),t=t||this.ranges[0],t&&!t.isEqual(this.getRange())&&this.fromOrientedRange(t)},this.$initRangeList=function(){if(this.rangeList)return;this.rangeList=new r,this.ranges=[],this.rangeCount=0},this.getAllRanges=function(){return this.rangeCount?this.rangeList.ranges.concat():[this.getRange()]},this.splitIntoLines=function(){if(this.rangeCount>1){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)}else{var n=this.getRange(),r=this.isBackwards(),s=n.start.row,o=n.end.row;if(s==o){if(r)var u=n.end,a=n.start;else var u=n.start,a=n.end;this.addRange(i.fromPoints(a,a)),this.addRange(i.fromPoints(u,u));return}var f=[],l=this.getLineRange(s,!0);l.start.column=n.start.column,f.push(l);for(var c=s+1;c1){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)}else{var r=this.session.documentToScreenPosition(this.cursor),s=this.session.documentToScreenPosition(this.anchor),o=this.rectangularRangeBlock(r,s);o.forEach(this.addRange,this)}},this.rectangularRangeBlock=function(e,t,n){var r=[],s=e.column0)g--;if(g>0){var y=0;while(r[y].isEmpty())y++}for(var b=g;b>=y;b--)r[b].isEmpty()&&r.splice(b,1)}return r}}.call(s.prototype);var d=e("./editor").Editor;(function(){this.updateSelectionMarkers=function(){this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.addSelectionMarker=function(e){e.cursor||(e.cursor=e.end);var t=this.getSelectionStyle();return e.marker=this.session.addMarker(e,"ace_selection",t),this.session.$selectionMarkers.push(e),this.session.selectionMarkerCount=this.session.$selectionMarkers.length,e},this.removeSelectionMarker=function(e){if(!e.marker)return;this.session.removeMarker(e.marker);var t=this.session.$selectionMarkers.indexOf(e);t!=-1&&this.session.$selectionMarkers.splice(t,1),this.session.selectionMarkerCount=this.session.$selectionMarkers.length},this.removeSelectionMarkers=function(e){var t=this.session.$selectionMarkers;for(var n=e.length;n--;){var r=e[n];if(!r.marker)continue;this.session.removeMarker(r.marker);var i=t.indexOf(r);i!=-1&&t.splice(i,1)}this.session.selectionMarkerCount=t.length},this.$onAddRange=function(e){this.addSelectionMarker(e.range),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onRemoveRange=function(e){this.removeSelectionMarkers(e.ranges),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelect=function(e){if(this.inMultiSelectMode)return;this.inMultiSelectMode=!0,this.setStyle("ace_multiselect"),this.keyBinding.addKeyboardHandler(f.keyboardHandler),this.commands.setDefaultHandler("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onSingleSelect=function(e){if(this.session.multiSelect.inVirtualMode)return;this.inMultiSelectMode=!1,this.unsetStyle("ace_multiselect"),this.keyBinding.removeKeyboardHandler(f.keyboardHandler),this.commands.removeDefaultHandler("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers(),this._emit("changeSelection")},this.$onMultiSelectExec=function(e){var t=e.command,n=e.editor;if(!n.multiSelect)return;if(!t.multiSelectAction){var r=t.exec(n,e.args||{});n.multiSelect.addRange(n.multiSelect.toOrientedRange()),n.multiSelect.mergeOverlappingRanges()}else t.multiSelectAction=="forEach"?r=n.forEachSelection(t,e.args):t.multiSelectAction=="forEachLine"?r=n.forEachSelection(t,e.args,!0):t.multiSelectAction=="single"?(n.exitMultiSelectMode(),r=t.exec(n,e.args||{})):r=t.multiSelectAction(n,e.args||{});return r},this.forEachSelection=function(e,t,n){if(this.inVirtualSelectionMode)return;var r=n&&n.keepOrder,i=n==1||n&&n.$byLines,o=this.session,u=this.selection,a=u.rangeList,f=(r?u:a).ranges,l;if(!f.length)return e.exec?e.exec(this,t||{}):e(this,t||{});var c=u._eventRegistry;u._eventRegistry={};var h=new s(o);this.inVirtualSelectionMode=!0;for(var p=f.length;p--;){if(i)while(p>0&&f[p].start.row==f[p-1].end.row)p--;h.fromOrientedRange(f[p]),h.index=p,this.selection=o.selection=h;var d=e.exec?e.exec(this,t||{}):e(this,t||{});!l&&d!==undefined&&(l=d),h.toOrientedRange(f[p])}h.detach(),this.selection=o.selection=u,this.inVirtualSelectionMode=!1,u._eventRegistry=c,u.mergeOverlappingRanges(),u.ranges[0]&&u.fromOrientedRange(u.ranges[0]);var v=this.renderer.$scrollAnimation;return this.onCursorChange(),this.onSelectionChange(),v&&v.from==v.to&&this.renderer.animateScrolling(v.from),l},this.exitMultiSelectMode=function(){if(!this.inMultiSelectMode||this.inVirtualSelectionMode)return;this.multiSelect.toSingleRange()},this.getSelectedText=function(){var e="";if(this.inMultiSelectMode&&!this.inVirtualSelectionMode){var t=this.multiSelect.rangeList.ranges,n=[];for(var r=0;r0);u<0&&(u=0),f>=c&&(f=c-1)}var p=this.session.removeFullLines(u,f);p=this.$reAlignText(p,l),this.session.insert({row:u,column:0},p.join("\n")+"\n"),l||(o.start.column=0,o.end.column=p[p.length-1].length),this.selection.setRange(o)}else{s.forEach(function(e){t.substractPoint(e.cursor)});var d=0,v=Infinity,m=n.map(function(t){var n=t.cursor,r=e.getLine(n.row),i=r.substr(n.column).search(/\S/g);return i==-1&&(i=0),n.column>d&&(d=n.column),io?e.insert(r,a.stringRepeat(" ",s-o)):e.remove(new i(r.row,r.column,r.row,r.column-s+o)),t.start.column=t.end.column=d,t.start.row=t.end.row=r.row,t.cursor=t.end}),t.fromOrientedRange(n[0]),this.renderer.updateCursor(),this.renderer.updateBackMarkers()}},this.$reAlignText=function(e,t){function u(e){return a.stringRepeat(" ",e)}function f(e){return e[2]?u(i)+e[2]+u(s-e[2].length+o)+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}function l(e){return e[2]?u(i+s-e[2].length)+e[2]+u(o)+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}function c(e){return e[2]?u(i)+e[2]+u(o)+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}var n=!0,r=!0,i,s,o;return e.map(function(e){var t=e.match(/(\s*)(.*?)(\s*)([=:].*)/);return t?i==null?(i=t[1].length,s=t[2].length,o=t[3].length,t):(i+s+o!=t[1].length+t[2].length+t[3].length&&(r=!1),i!=t[1].length&&(n=!1),i>t[1].length&&(i=t[1].length),st[3].length&&(o=t[3].length),t):[e]}).map(t?f:n?r?l:f:c)}}).call(d.prototype),t.onSessionChange=function(e){var t=e.session;t&&!t.multiSelect&&(t.$selectionMarkers=[],t.selection.$initRangeList(),t.multiSelect=t.selection),this.multiSelect=t&&t.multiSelect;var n=e.oldSession;n&&(n.multiSelect.off("addRange",this.$onAddRange),n.multiSelect.off("removeRange",this.$onRemoveRange),n.multiSelect.off("multiSelect",this.$onMultiSelect),n.multiSelect.off("singleSelect",this.$onSingleSelect),n.multiSelect.lead.off("change",this.$checkMultiselectChange),n.multiSelect.anchor.off("change",this.$checkMultiselectChange)),t&&(t.multiSelect.on("addRange",this.$onAddRange),t.multiSelect.on("removeRange",this.$onRemoveRange),t.multiSelect.on("multiSelect",this.$onMultiSelect),t.multiSelect.on("singleSelect",this.$onSingleSelect),t.multiSelect.lead.on("change",this.$checkMultiselectChange),t.multiSelect.anchor.on("change",this.$checkMultiselectChange)),t&&this.inMultiSelectMode!=t.selection.inMultiSelectMode&&(t.selection.inMultiSelectMode?this.$onMultiSelect():this.$onSingleSelect())},t.MultiSelect=m,e("./config").defineOptions(d.prototype,"editor",{enableMultiselect:{set:function(e){m(this),e?(this.on("changeSession",this.$multiselectOnSessionChange),this.on("mousedown",o)):(this.off("changeSession",this.$multiselectOnSessionChange),this.off("mousedown",o))},value:!0},enableBlockSelect:{set:function(e){this.$blockSelectEnabled=e},value:!0}})}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../../range").Range,i=t.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(e,t,n){var r=e.getLine(n);return this.foldingStartMarker.test(r)?"start":t=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(r)?"end":""},this.getFoldWidgetRange=function(e,t,n){return null},this.indentationBlock=function(e,t,n){var i=/\S/,s=e.getLine(t),o=s.search(i);if(o==-1)return;var u=n||s.length,a=e.getLength(),f=t,l=t;while(++tf){var h=e.getLine(l).length;return new r(f,u,l,h)}},this.openingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i+1},u=e.$findClosingBracket(t,o,s);if(!u)return;var a=e.foldWidgets[u.row];return a==null&&(a=e.getFoldWidget(u.row)),a=="start"&&u.row>o.row&&(u.row--,u.column=e.getLine(u.row).length),r.fromPoints(o,u)},this.closingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i},u=e.$findOpeningBracket(t,o);if(!u)return;return u.column++,o.column--,r.fromPoints(u,o)}}).call(i.prototype)}),define("ace/theme/textmate",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";t.isDark=!1,t.cssClass="ace-tm",t.cssText='.ace-tm .ace_gutter {background: #f0f0f0;color: #333;}.ace-tm .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-tm .ace_fold {background-color: #6B72E6;}.ace-tm {background-color: #FFFFFF;color: black;}.ace-tm .ace_cursor {color: black;}.ace-tm .ace_invisible {color: rgb(191, 191, 191);}.ace-tm .ace_storage,.ace-tm .ace_keyword {color: blue;}.ace-tm .ace_constant {color: rgb(197, 6, 11);}.ace-tm .ace_constant.ace_buildin {color: rgb(88, 72, 246);}.ace-tm .ace_constant.ace_language {color: rgb(88, 92, 246);}.ace-tm .ace_constant.ace_library {color: rgb(6, 150, 14);}.ace-tm .ace_invalid {background-color: rgba(255, 0, 0, 0.1);color: red;}.ace-tm .ace_support.ace_function {color: rgb(60, 76, 114);}.ace-tm .ace_support.ace_constant {color: rgb(6, 150, 14);}.ace-tm .ace_support.ace_type,.ace-tm .ace_support.ace_class {color: rgb(109, 121, 222);}.ace-tm .ace_keyword.ace_operator {color: rgb(104, 118, 135);}.ace-tm .ace_string {color: rgb(3, 106, 7);}.ace-tm .ace_comment {color: rgb(76, 136, 107);}.ace-tm .ace_comment.ace_doc {color: rgb(0, 102, 255);}.ace-tm .ace_comment.ace_doc.ace_tag {color: rgb(128, 159, 191);}.ace-tm .ace_constant.ace_numeric {color: rgb(0, 0, 205);}.ace-tm .ace_variable {color: rgb(49, 132, 149);}.ace-tm .ace_xml-pe {color: rgb(104, 104, 91);}.ace-tm .ace_entity.ace_name.ace_function {color: #0000A2;}.ace-tm .ace_heading {color: rgb(12, 7, 255);}.ace-tm .ace_list {color:rgb(185, 6, 144);}.ace-tm .ace_meta.ace_tag {color:rgb(0, 22, 142);}.ace-tm .ace_string.ace_regex {color: rgb(255, 0, 0)}.ace-tm .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-tm.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px white;}.ace-tm .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-tm .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-tm .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-tm .ace_marker-layer .ace_active-line {background: rgba(0, 0, 0, 0.07);}.ace-tm .ace_gutter-active-line {background-color : #dcdcdc;}.ace-tm .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-tm .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;}',t.$id="ace/theme/textmate";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}),define("ace/line_widgets",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/range"],function(e,t,n){"use strict";function o(e){this.session=e,this.session.widgetManager=this,this.session.getRowLength=this.getRowLength,this.session.$getWidgetScreenLength=this.$getWidgetScreenLength,this.updateOnChange=this.updateOnChange.bind(this),this.renderWidgets=this.renderWidgets.bind(this),this.measureWidgets=this.measureWidgets.bind(this),this.session._changedWidgets=[],this.$onChangeEditor=this.$onChangeEditor.bind(this),this.session.on("change",this.updateOnChange),this.session.on("changeFold",this.updateOnFold),this.session.on("changeEditor",this.$onChangeEditor)}var r=e("./lib/oop"),i=e("./lib/dom"),s=e("./range").Range;(function(){this.getRowLength=function(e){var t;return this.lineWidgets?t=this.lineWidgets[e]&&this.lineWidgets[e].rowCount||0:t=0,!this.$useWrapMode||!this.$wrapData[e]?1+t:this.$wrapData[e].length+1+t},this.$getWidgetScreenLength=function(){var e=0;return this.lineWidgets.forEach(function(t){t&&t.rowCount&&!t.hidden&&(e+=t.rowCount)}),e},this.$onChangeEditor=function(e){this.attach(e.editor)},this.attach=function(e){e&&e.widgetManager&&e.widgetManager!=this&&e.widgetManager.detach();if(this.editor==e)return;this.detach(),this.editor=e,e&&(e.widgetManager=this,e.renderer.on("beforeRender",this.measureWidgets),e.renderer.on("afterRender",this.renderWidgets))},this.detach=function(e){var t=this.editor;if(!t)return;this.editor=null,t.widgetManager=null,t.renderer.off("beforeRender",this.measureWidgets),t.renderer.off("afterRender",this.renderWidgets);var n=this.session.lineWidgets;n&&n.forEach(function(e){e&&e.el&&e.el.parentNode&&(e._inDocument=!1,e.el.parentNode.removeChild(e.el))})},this.updateOnFold=function(e,t){var n=t.lineWidgets;if(!n||!e.action)return;var r=e.data,i=r.start.row,s=r.end.row,o=e.action=="add";for(var u=i+1;u0&&!r[i])i--;this.firstRow=n.firstRow,this.lastRow=n.lastRow,t.$cursorLayer.config=n;for(var o=i;o<=s;o++){var u=r[o];if(!u||!u.el)continue;if(u.hidden){u.el.style.top=-100-(u.pixelHeight||0)+"px";continue}u._inDocument||(u._inDocument=!0,t.container.appendChild(u.el));var a=t.$cursorLayer.getPixelPosition({row:o,column:0},!0).top;u.coverLine||(a+=n.lineHeight*this.session.getRowLineCount(u.row)),u.el.style.top=a-n.offset+"px";var f=u.coverGutter?0:t.gutterWidth;u.fixedWidth||(f-=t.scrollLeft),u.el.style.left=f+"px",u.fullWidth&&u.screenWidth&&(u.el.style.minWidth=n.width+2*n.padding+"px"),u.fixedWidth?u.el.style.right=t.scrollBar.getWidth()+"px":u.el.style.right=""}}}).call(o.prototype),t.LineWidgets=o}),define("ace/ext/error_marker",["require","exports","module","ace/line_widgets","ace/lib/dom","ace/range"],function(e,t,n){"use strict";function o(e,t,n){var r=0,i=e.length-1;while(r<=i){var s=r+i>>1,o=n(t,e[s]);if(o>0)r=s+1;else{if(!(o<0))return s;i=s-1}}return-(r+1)}function u(e,t,n){var r=e.getAnnotations().sort(s.comparePoints);if(!r.length)return;var i=o(r,{row:t,column:-1},s.comparePoints);i<0&&(i=-i-1),i>=r.length?i=n>0?0:r.length-1:i===0&&n<0&&(i=r.length-1);var u=r[i];if(!u||!n)return;if(u.row===t){do u=r[i+=n];while(u&&u.row===t);if(!u)return r.slice()}var a=[];t=u.row;do a[n<0?"unshift":"push"](u),u=r[i+=n];while(u&&u.row==t);return a.length&&a}var r=e("../line_widgets").LineWidgets,i=e("../lib/dom"),s=e("../range").Range;t.showErrorMarker=function(e,t){var n=e.session;n.widgetManager||(n.widgetManager=new r(n),n.widgetManager.attach(e));var s=e.getCursorPosition(),o=s.row,a=n.widgetManager.getWidgetsAtRow(o).filter(function(e){return e.type=="errorMarker"})[0];a?a.destroy():o-=t;var f=u(n,o,t),l;if(f){var c=f[0];s.column=(c.pos&&typeof c.column!="number"?c.pos.sc:c.column)||0,s.row=c.row,l=e.renderer.$gutterLayer.$annotations[s.row]}else{if(a)return;l={text:["Looks good!"],className:"ace_ok"}}e.session.unfold(s.row),e.selection.moveToPosition(s);var h={row:s.row,fixedWidth:!0,coverGutter:!0,el:i.createElement("div"),type:"errorMarker"},p=h.el.appendChild(i.createElement("div")),d=h.el.appendChild(i.createElement("div"));d.className="error_widget_arrow "+l.className;var v=e.renderer.$cursorLayer.getPixelPosition(s).left;d.style.left=v+e.renderer.gutterWidth-5+"px",h.el.className="error_widget_wrapper",p.className="error_widget "+l.className,p.innerHTML=l.text.join("
"),p.appendChild(i.createElement("div"));var m=function(e,t,n){if(t===0&&(n==="esc"||n==="return"))return h.destroy(),{command:"null"}};h.destroy=function(){if(e.$mouseHandler.isMousePressed)return;e.keyBinding.removeKeyboardHandler(m),n.widgetManager.removeLineWidget(h),e.off("changeSelection",h.destroy),e.off("changeSession",h.destroy),e.off("mouseup",h.destroy),e.off("change",h.destroy)},e.keyBinding.addKeyboardHandler(m),e.on("changeSelection",h.destroy),e.on("changeSession",h.destroy),e.on("mouseup",h.destroy),e.on("change",h.destroy),e.session.widgetManager.addLineWidget(h),h.el.onmousedown=e.focus.bind(e),e.renderer.scrollCursorIntoView(null,.5,{bottom:h.el.offsetHeight})},i.importCssString(" .error_widget_wrapper { background: inherit; color: inherit; border:none } .error_widget { border-top: solid 2px; border-bottom: solid 2px; margin: 5px 0; padding: 10px 40px; white-space: pre-wrap; } .error_widget.ace_error, .error_widget_arrow.ace_error{ border-color: #ff5a5a } .error_widget.ace_warning, .error_widget_arrow.ace_warning{ border-color: #F1D817 } .error_widget.ace_info, .error_widget_arrow.ace_info{ border-color: #5a5a5a } .error_widget.ace_ok, .error_widget_arrow.ace_ok{ border-color: #5aaa5a } .error_widget_arrow { position: absolute; border: solid 5px; border-top-color: transparent!important; border-right-color: transparent!important; border-left-color: transparent!important; top: -5px; }","")}),define("ace/ace",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/dom","ace/lib/event","ace/range","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/worker/worker_client","ace/keyboard/hash_handler","ace/placeholder","ace/multi_select","ace/mode/folding/fold_mode","ace/theme/textmate","ace/ext/error_marker","ace/config"],function(e,t,n){"use strict";e("./lib/fixoldbrowsers");var r=e("./lib/dom"),i=e("./lib/event"),s=e("./range").Range,o=e("./editor").Editor,u=e("./edit_session").EditSession,a=e("./undomanager").UndoManager,f=e("./virtual_renderer").VirtualRenderer;e("./worker/worker_client"),e("./keyboard/hash_handler"),e("./placeholder"),e("./multi_select"),e("./mode/folding/fold_mode"),e("./theme/textmate"),e("./ext/error_marker"),t.config=e("./config"),t.require=e,typeof define=="function"&&(t.define=define),t.edit=function(e,n){if(typeof e=="string"){var s=e;e=document.getElementById(s);if(!e)throw new Error("ace.edit can't find div #"+s)}if(e&&e.env&&e.env.editor instanceof o)return e.env.editor;var u="";if(e&&/input|textarea/i.test(e.tagName)){var a=e;u=a.value,e=r.createElement("pre"),a.parentNode.replaceChild(e,a)}else e&&(u=e.textContent,e.innerHTML="");var l=t.createEditSession(u),c=new o(new f(e),l,n),h={document:l,editor:c,onResize:c.resize.bind(c,null)};return a&&(h.textarea=a),i.addListener(window,"resize",h.onResize),c.on("destroy",function(){i.removeListener(window,"resize",h.onResize),h.editor.container.env=null}),c.container.env=c.env=h,c},t.createEditSession=function(e,t){var n=new u(e,t);return n.setUndoManager(new a),n},t.Range=s,t.EditSession=u,t.UndoManager=a,t.VirtualRenderer=f,t.version="1.4.1"}); - (function() { - window.require(["ace/ace"], function(a) { - if (a) { - a.config.init(true); - a.define = window.define; - } - if (!window.ace) - window.ace = a; - for (var key in a) if (a.hasOwnProperty(key)) - window.ace[key] = a[key]; - window.ace["default"] = window.ace; - if (typeof module == "object" && typeof exports == "object" && module) { - module.exports = window.ace; +(function () { + function o(n) { + var i = e; + n && (e[n] || (e[n] = {}), (i = e[n])); + if (!i.define || !i.define.packaged) + (t.original = i.define), (i.define = t), (i.define.packaged = !0); + if (!i.require || !i.require.packaged) + (r.original = i.require), (i.require = r), (i.require.packaged = !0); + } + var ACE_NAMESPACE = "", + e = (function () { + return this; + })(); + !e && typeof window != "undefined" && (e = window); + if (!ACE_NAMESPACE && typeof requirejs != "undefined") return; + var t = function (e, n, r) { + if (typeof e != "string") { + t.original + ? t.original.apply(this, arguments) + : (console.error("dropping module because define wasn't a string."), + console.trace()); + return; + } + arguments.length == 2 && (r = n), + t.modules[e] || ((t.payloads[e] = r), (t.modules[e] = null)); + }; + (t.modules = {}), (t.payloads = {}); + var n = function (e, t, n) { + if (typeof t == "string") { + var i = s(e, t); + if (i != undefined) return n && n(), i; + } else if (Object.prototype.toString.call(t) === "[object Array]") { + var o = []; + for (var u = 0, a = t.length; u < a; ++u) { + var f = s(e, t[u]); + if (f == undefined && r.original) return; + o.push(f); + } + return (n && n.apply(null, o)) || !0; + } + }, + r = function (e, t) { + var i = n("", e, t); + return i == undefined && r.original ? r.original.apply(this, arguments) : i; + }, + i = function (e, t) { + if (t.indexOf("!") !== -1) { + var n = t.split("!"); + return i(e, n[0]) + "!" + i(e, n[1]); + } + if (t.charAt(0) == ".") { + var r = e.split("/").slice(0, -1).join("/"); + t = r + "/" + t; + while (t.indexOf(".") !== -1 && s != t) { + var s = t; + t = t.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); + } + } + return t; + }, + s = function (e, r) { + r = i(e, r); + var s = t.modules[r]; + if (!s) { + s = t.payloads[r]; + if (typeof s == "function") { + var o = {}, + u = { id: r, uri: "", exports: o, packaged: !0 }, + a = function (e, t) { + return n(r, e, t); + }, + f = s(a, o, u); + (o = f || u.exports), (t.modules[r] = o), delete t.payloads[r]; + } + s = t.modules[r] = o || s; + } + return s; + }; + o(ACE_NAMESPACE); +})(), + define("ace/lib/regexp", ["require", "exports", "module"], function (e, t, n) { + "use strict"; + function o(e) { + return ( + (e.global ? "g" : "") + + (e.ignoreCase ? "i" : "") + + (e.multiline ? "m" : "") + + (e.extended ? "x" : "") + + (e.sticky ? "y" : "") + ); + } + function u(e, t, n) { + if (Array.prototype.indexOf) return e.indexOf(t, n); + for (var r = n || 0; r < e.length; r++) if (e[r] === t) return r; + return -1; + } + var r = { + exec: RegExp.prototype.exec, + test: RegExp.prototype.test, + match: String.prototype.match, + replace: String.prototype.replace, + split: String.prototype.split, + }, + i = r.exec.call(/()??/, "")[1] === undefined, + s = (function () { + var e = /^/g; + return r.test.call(e, ""), !e.lastIndex; + })(); + if (s && i) return; + (RegExp.prototype.exec = function (e) { + var t = r.exec.apply(this, arguments), + n, + a; + if (typeof e == "string" && t) { + !i && + t.length > 1 && + u(t, "") > -1 && + ((a = RegExp(this.source, r.replace.call(o(this), "g", ""))), + r.replace.call(e.slice(t.index), a, function () { + for (var e = 1; e < arguments.length - 2; e++) + arguments[e] === undefined && (t[e] = undefined); + })); + if (this._xregexp && this._xregexp.captureNames) + for (var f = 1; f < t.length; f++) + (n = this._xregexp.captureNames[f - 1]), n && (t[n] = t[f]); + !s && this.global && !t[0].length && this.lastIndex > t.index && this.lastIndex--; + } + return t; + }), + s || + (RegExp.prototype.test = function (e) { + var t = r.exec.call(this, e); + return ( + t && + this.global && + !t[0].length && + this.lastIndex > t.index && + this.lastIndex--, + !!t + ); + }); + }), + define("ace/lib/es5-shim", ["require", "exports", "module"], function (e, t, n) { + function r() {} + function w(e) { + try { + return Object.defineProperty(e, "sentinel", {}), "sentinel" in e; + } catch (t) {} + } + function H(e) { + return ( + (e = +e), + e !== e + ? (e = 0) + : e !== 0 && + e !== 1 / 0 && + e !== -1 / 0 && + (e = (e > 0 || -1) * Math.floor(Math.abs(e))), + e + ); + } + function B(e) { + var t = typeof e; + return ( + e === null || + t === "undefined" || + t === "boolean" || + t === "number" || + t === "string" + ); + } + function j(e) { + var t, n, r; + if (B(e)) return e; + n = e.valueOf; + if (typeof n == "function") { + t = n.call(e); + if (B(t)) return t; + } + r = e.toString; + if (typeof r == "function") { + t = r.call(e); + if (B(t)) return t; + } + throw new TypeError(); + } + Function.prototype.bind || + (Function.prototype.bind = function (t) { + var n = this; + if (typeof n != "function") + throw new TypeError("Function.prototype.bind called on incompatible " + n); + var i = u.call(arguments, 1), + s = function () { + if (this instanceof s) { + var e = n.apply(this, i.concat(u.call(arguments))); + return Object(e) === e ? e : this; + } + return n.apply(t, i.concat(u.call(arguments))); + }; + return ( + n.prototype && + ((r.prototype = n.prototype), + (s.prototype = new r()), + (r.prototype = null)), + s + ); + }); + var i = Function.prototype.call, + s = Array.prototype, + o = Object.prototype, + u = s.slice, + a = i.bind(o.toString), + f = i.bind(o.hasOwnProperty), + l, + c, + h, + p, + d; + if ((d = f(o, "__defineGetter__"))) + (l = i.bind(o.__defineGetter__)), + (c = i.bind(o.__defineSetter__)), + (h = i.bind(o.__lookupGetter__)), + (p = i.bind(o.__lookupSetter__)); + if ([1, 2].splice(0).length != 2) + if ( + !(function () { + function e(e) { + var t = new Array(e + 2); + return (t[0] = t[1] = 0), t; + } + var t = [], + n; + t.splice.apply(t, e(20)), + t.splice.apply(t, e(26)), + (n = t.length), + t.splice(5, 0, "XXX"), + n + 1 == t.length; + if (n + 1 == t.length) return !0; + })() + ) + Array.prototype.splice = function (e, t) { + var n = this.length; + e > 0 + ? e > n && (e = n) + : e == void 0 + ? (e = 0) + : e < 0 && (e = Math.max(n + e, 0)), + e + t < n || (t = n - e); + var r = this.slice(e, e + t), + i = u.call(arguments, 2), + s = i.length; + if (e === n) s && this.push.apply(this, i); + else { + var o = Math.min(t, n - e), + a = e + o, + f = a + s - o, + l = n - a, + c = n - o; + if (f < a) for (var h = 0; h < l; ++h) this[f + h] = this[a + h]; + else if (f > a) for (h = l; h--; ) this[f + h] = this[a + h]; + if (s && e === c) (this.length = c), this.push.apply(this, i); + else { + this.length = c + s; + for (h = 0; h < s; ++h) this[e + h] = i[h]; + } } + return r; + }; + else { + var v = Array.prototype.splice; + Array.prototype.splice = function (e, t) { + return arguments.length + ? v.apply( + this, + [e === void 0 ? 0 : e, t === void 0 ? this.length - e : t].concat( + u.call(arguments, 2), + ), + ) + : []; + }; + } + Array.isArray || + (Array.isArray = function (t) { + return a(t) == "[object Array]"; + }); + var m = Object("a"), + g = m[0] != "a" || !(0 in m); + Array.prototype.forEach || + (Array.prototype.forEach = function (t) { + var n = F(this), + r = g && a(this) == "[object String]" ? this.split("") : n, + i = arguments[1], + s = -1, + o = r.length >>> 0; + if (a(t) != "[object Function]") throw new TypeError(); + while (++s < o) s in r && t.call(i, r[s], s, n); + }), + Array.prototype.map || + (Array.prototype.map = function (t) { + var n = F(this), + r = g && a(this) == "[object String]" ? this.split("") : n, + i = r.length >>> 0, + s = Array(i), + o = arguments[1]; + if (a(t) != "[object Function]") throw new TypeError(t + " is not a function"); + for (var u = 0; u < i; u++) u in r && (s[u] = t.call(o, r[u], u, n)); + return s; + }), + Array.prototype.filter || + (Array.prototype.filter = function (t) { + var n = F(this), + r = g && a(this) == "[object String]" ? this.split("") : n, + i = r.length >>> 0, + s = [], + o, + u = arguments[1]; + if (a(t) != "[object Function]") throw new TypeError(t + " is not a function"); + for (var f = 0; f < i; f++) + f in r && ((o = r[f]), t.call(u, o, f, n) && s.push(o)); + return s; + }), + Array.prototype.every || + (Array.prototype.every = function (t) { + var n = F(this), + r = g && a(this) == "[object String]" ? this.split("") : n, + i = r.length >>> 0, + s = arguments[1]; + if (a(t) != "[object Function]") throw new TypeError(t + " is not a function"); + for (var o = 0; o < i; o++) if (o in r && !t.call(s, r[o], o, n)) return !1; + return !0; + }), + Array.prototype.some || + (Array.prototype.some = function (t) { + var n = F(this), + r = g && a(this) == "[object String]" ? this.split("") : n, + i = r.length >>> 0, + s = arguments[1]; + if (a(t) != "[object Function]") throw new TypeError(t + " is not a function"); + for (var o = 0; o < i; o++) if (o in r && t.call(s, r[o], o, n)) return !0; + return !1; + }), + Array.prototype.reduce || + (Array.prototype.reduce = function (t) { + var n = F(this), + r = g && a(this) == "[object String]" ? this.split("") : n, + i = r.length >>> 0; + if (a(t) != "[object Function]") throw new TypeError(t + " is not a function"); + if (!i && arguments.length == 1) + throw new TypeError("reduce of empty array with no initial value"); + var s = 0, + o; + if (arguments.length >= 2) o = arguments[1]; + else + do { + if (s in r) { + o = r[s++]; + break; + } + if (++s >= i) + throw new TypeError("reduce of empty array with no initial value"); + } while (!0); + for (; s < i; s++) s in r && (o = t.call(void 0, o, r[s], s, n)); + return o; + }), + Array.prototype.reduceRight || + (Array.prototype.reduceRight = function (t) { + var n = F(this), + r = g && a(this) == "[object String]" ? this.split("") : n, + i = r.length >>> 0; + if (a(t) != "[object Function]") throw new TypeError(t + " is not a function"); + if (!i && arguments.length == 1) + throw new TypeError("reduceRight of empty array with no initial value"); + var s, + o = i - 1; + if (arguments.length >= 2) s = arguments[1]; + else + do { + if (o in r) { + s = r[o--]; + break; + } + if (--o < 0) + throw new TypeError( + "reduceRight of empty array with no initial value", + ); + } while (!0); + do o in this && (s = t.call(void 0, s, r[o], o, n)); + while (o--); + return s; }); - })(); - \ No newline at end of file + if (!Array.prototype.indexOf || [0, 1].indexOf(1, 2) != -1) + Array.prototype.indexOf = function (t) { + var n = g && a(this) == "[object String]" ? this.split("") : F(this), + r = n.length >>> 0; + if (!r) return -1; + var i = 0; + arguments.length > 1 && (i = H(arguments[1])), + (i = i >= 0 ? i : Math.max(0, r + i)); + for (; i < r; i++) if (i in n && n[i] === t) return i; + return -1; + }; + if (!Array.prototype.lastIndexOf || [0, 1].lastIndexOf(0, -3) != -1) + Array.prototype.lastIndexOf = function (t) { + var n = g && a(this) == "[object String]" ? this.split("") : F(this), + r = n.length >>> 0; + if (!r) return -1; + var i = r - 1; + arguments.length > 1 && (i = Math.min(i, H(arguments[1]))), + (i = i >= 0 ? i : r - Math.abs(i)); + for (; i >= 0; i--) if (i in n && t === n[i]) return i; + return -1; + }; + Object.getPrototypeOf || + (Object.getPrototypeOf = function (t) { + return t.__proto__ || (t.constructor ? t.constructor.prototype : o); + }); + if (!Object.getOwnPropertyDescriptor) { + var y = "Object.getOwnPropertyDescriptor called on a non-object: "; + Object.getOwnPropertyDescriptor = function (t, n) { + if ((typeof t != "object" && typeof t != "function") || t === null) + throw new TypeError(y + t); + if (!f(t, n)) return; + var r, i, s; + r = { enumerable: !0, configurable: !0 }; + if (d) { + var u = t.__proto__; + t.__proto__ = o; + var i = h(t, n), + s = p(t, n); + t.__proto__ = u; + if (i || s) return i && (r.get = i), s && (r.set = s), r; + } + return (r.value = t[n]), r; + }; + } + Object.getOwnPropertyNames || + (Object.getOwnPropertyNames = function (t) { + return Object.keys(t); + }); + if (!Object.create) { + var b; + Object.prototype.__proto__ === null + ? (b = function () { + return { __proto__: null }; + }) + : (b = function () { + var e = {}; + for (var t in e) e[t] = null; + return ( + (e.constructor = + e.hasOwnProperty = + e.propertyIsEnumerable = + e.isPrototypeOf = + e.toLocaleString = + e.toString = + e.valueOf = + e.__proto__ = + null), + e + ); + }), + (Object.create = function (t, n) { + var r; + if (t === null) r = b(); + else { + if (typeof t != "object") + throw new TypeError("typeof prototype[" + typeof t + "] != 'object'"); + var i = function () {}; + (i.prototype = t), (r = new i()), (r.__proto__ = t); + } + return n !== void 0 && Object.defineProperties(r, n), r; + }); + } + if (Object.defineProperty) { + var E = w({}), + S = typeof document == "undefined" || w(document.createElement("div")); + if (!E || !S) var x = Object.defineProperty; + } + if (!Object.defineProperty || x) { + var T = "Property description must be an object: ", + N = "Object.defineProperty called on non-object: ", + C = "getters & setters can not be defined on this javascript engine"; + Object.defineProperty = function (t, n, r) { + if ((typeof t != "object" && typeof t != "function") || t === null) + throw new TypeError(N + t); + if ((typeof r != "object" && typeof r != "function") || r === null) + throw new TypeError(T + r); + if (x) + try { + return x.call(Object, t, n, r); + } catch (i) {} + if (f(r, "value")) + if (d && (h(t, n) || p(t, n))) { + var s = t.__proto__; + (t.__proto__ = o), delete t[n], (t[n] = r.value), (t.__proto__ = s); + } else t[n] = r.value; + else { + if (!d) throw new TypeError(C); + f(r, "get") && l(t, n, r.get), f(r, "set") && c(t, n, r.set); + } + return t; + }; + } + Object.defineProperties || + (Object.defineProperties = function (t, n) { + for (var r in n) f(n, r) && Object.defineProperty(t, r, n[r]); + return t; + }), + Object.seal || + (Object.seal = function (t) { + return t; + }), + Object.freeze || + (Object.freeze = function (t) { + return t; + }); + try { + Object.freeze(function () {}); + } catch (k) { + Object.freeze = (function (t) { + return function (n) { + return typeof n == "function" ? n : t(n); + }; + })(Object.freeze); + } + Object.preventExtensions || + (Object.preventExtensions = function (t) { + return t; + }), + Object.isSealed || + (Object.isSealed = function (t) { + return !1; + }), + Object.isFrozen || + (Object.isFrozen = function (t) { + return !1; + }), + Object.isExtensible || + (Object.isExtensible = function (t) { + if (Object(t) === t) throw new TypeError(); + var n = ""; + while (f(t, n)) n += "?"; + t[n] = !0; + var r = f(t, n); + return delete t[n], r; + }); + if (!Object.keys) { + var L = !0, + A = [ + "toString", + "toLocaleString", + "valueOf", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "constructor", + ], + O = A.length; + for (var M in { toString: null }) L = !1; + Object.keys = function I(e) { + if ((typeof e != "object" && typeof e != "function") || e === null) + throw new TypeError("Object.keys called on a non-object"); + var I = []; + for (var t in e) f(e, t) && I.push(t); + if (L) + for (var n = 0, r = O; n < r; n++) { + var i = A[n]; + f(e, i) && I.push(i); + } + return I; + }; + } + Date.now || + (Date.now = function () { + return new Date().getTime(); + }); + var _ = + " \n\x0b\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\ufeff"; + if (!String.prototype.trim || _.trim()) { + _ = "[" + _ + "]"; + var D = new RegExp("^" + _ + _ + "*"), + P = new RegExp(_ + _ + "*$"); + String.prototype.trim = function () { + return String(this).replace(D, "").replace(P, ""); + }; + } + var F = function (e) { + if (e == null) throw new TypeError("can't convert " + e + " to object"); + return Object(e); + }; + }), + define( + "ace/lib/fixoldbrowsers", + ["require", "exports", "module", "ace/lib/regexp", "ace/lib/es5-shim"], + function (e, t, n) { + "use strict"; + e("./regexp"), + e("./es5-shim"), + typeof Element != "undefined" && + !Element.prototype.remove && + Object.defineProperty(Element.prototype, "remove", { + enumerable: !1, + writable: !0, + configurable: !0, + value: function () { + this.parentNode && this.parentNode.removeChild(this); + }, + }); + }, + ), + define("ace/lib/useragent", ["require", "exports", "module"], function (e, t, n) { + "use strict"; + (t.OS = { LINUX: "LINUX", MAC: "MAC", WINDOWS: "WINDOWS" }), + (t.getOS = function () { + return t.isMac ? t.OS.MAC : t.isLinux ? t.OS.LINUX : t.OS.WINDOWS; + }); + if (typeof navigator != "object") return; + var r = (navigator.platform.match(/mac|win|linux/i) || ["other"])[0].toLowerCase(), + i = navigator.userAgent; + (t.isWin = r == "win"), + (t.isMac = r == "mac"), + (t.isLinux = r == "linux"), + (t.isIE = + navigator.appName == "Microsoft Internet Explorer" || + navigator.appName.indexOf("MSAppHost") >= 0 + ? parseFloat( + (i.match(/(?:MSIE |Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/) || + [])[1], + ) + : parseFloat( + (i.match(/(?:Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/) || [])[1], + )), + (t.isOldIE = t.isIE && t.isIE < 9), + (t.isGecko = t.isMozilla = i.match(/ Gecko\/\d+/)), + (t.isOpera = + window.opera && Object.prototype.toString.call(window.opera) == "[object Opera]"), + (t.isWebKit = parseFloat(i.split("WebKit/")[1]) || undefined), + (t.isChrome = parseFloat(i.split(" Chrome/")[1]) || undefined), + (t.isEdge = parseFloat(i.split(" Edge/")[1]) || undefined), + (t.isAIR = i.indexOf("AdobeAIR") >= 0), + (t.isIPad = i.indexOf("iPad") >= 0), + (t.isAndroid = i.indexOf("Android") >= 0), + (t.isChromeOS = i.indexOf(" CrOS ") >= 0), + (t.isIOS = /iPad|iPhone|iPod/.test(i) && !window.MSStream), + t.isIOS && (t.isMac = !0), + (t.isMobile = t.isIPad || t.isAndroid); + }), + define( + "ace/lib/dom", + ["require", "exports", "module", "ace/lib/useragent"], + function (e, t, n) { + "use strict"; + var r = e("./useragent"), + i = "http://www.w3.org/1999/xhtml"; + (t.buildDom = function o(e, t, n) { + if (typeof e == "string" && e) { + var r = document.createTextNode(e); + return t && t.appendChild(r), r; + } + if (!Array.isArray(e)) return e; + if (typeof e[0] != "string" || !e[0]) { + var i = []; + for (var s = 0; s < e.length; s++) { + var u = o(e[s], t, n); + u && i.push(u); + } + return i; + } + var a = document.createElement(e[0]), + f = e[1], + l = 1; + f && typeof f == "object" && !Array.isArray(f) && (l = 2); + for (var s = l; s < e.length; s++) o(e[s], a, n); + return ( + l == 2 && + Object.keys(f).forEach(function (e) { + var t = f[e]; + e === "class" + ? (a.className = Array.isArray(t) ? t.join(" ") : t) + : typeof t == "function" || e == "value" + ? (a[e] = t) + : e === "ref" + ? n && (n[t] = a) + : t != null && a.setAttribute(e, t); + }), + t && t.appendChild(a), + a + ); + }), + (t.getDocumentHead = function (e) { + return ( + e || (e = document), + e.head || e.getElementsByTagName("head")[0] || e.documentElement + ); + }), + (t.createElement = function (e, t) { + return document.createElementNS + ? document.createElementNS(t || i, e) + : document.createElement(e); + }), + (t.removeChildren = function (e) { + e.innerHTML = ""; + }), + (t.createTextNode = function (e, t) { + var n = t ? t.ownerDocument : document; + return n.createTextNode(e); + }), + (t.createFragment = function (e) { + var t = e ? e.ownerDocument : document; + return t.createDocumentFragment(); + }), + (t.hasCssClass = function (e, t) { + var n = (e.className + "").split(/\s+/g); + return n.indexOf(t) !== -1; + }), + (t.addCssClass = function (e, n) { + t.hasCssClass(e, n) || (e.className += " " + n); + }), + (t.removeCssClass = function (e, t) { + var n = e.className.split(/\s+/g); + for (;;) { + var r = n.indexOf(t); + if (r == -1) break; + n.splice(r, 1); + } + e.className = n.join(" "); + }), + (t.toggleCssClass = function (e, t) { + var n = e.className.split(/\s+/g), + r = !0; + for (;;) { + var i = n.indexOf(t); + if (i == -1) break; + (r = !1), n.splice(i, 1); + } + return r && n.push(t), (e.className = n.join(" ")), r; + }), + (t.setCssClass = function (e, n, r) { + r ? t.addCssClass(e, n) : t.removeCssClass(e, n); + }), + (t.hasCssString = function (e, t) { + var n = 0, + r; + t = t || document; + if ((r = t.querySelectorAll("style"))) + while (n < r.length) if (r[n++].id === e) return !0; + }), + (t.importCssString = function (n, r, i) { + var s = i && i.getRootNode ? i.getRootNode() : document, + o = s.ownerDocument || s; + if (r && t.hasCssString(r, s)) return null; + r && (n += "\n/*# sourceURL=ace/css/" + r + " */"); + var u = t.createElement("style"); + u.appendChild(o.createTextNode(n)), + r && (u.id = r), + s == o && (s = t.getDocumentHead(o)), + s.insertBefore(u, s.firstChild); + }), + (t.importCssStylsheet = function (e, n) { + t.buildDom(["link", { rel: "stylesheet", href: e }], t.getDocumentHead(n)); + }), + (t.scrollbarWidth = function (e) { + var n = t.createElement("ace_inner"); + (n.style.width = "100%"), + (n.style.minWidth = "0px"), + (n.style.height = "200px"), + (n.style.display = "block"); + var r = t.createElement("ace_outer"), + i = r.style; + (i.position = "absolute"), + (i.left = "-10000px"), + (i.overflow = "hidden"), + (i.width = "200px"), + (i.minWidth = "0px"), + (i.height = "150px"), + (i.display = "block"), + r.appendChild(n); + var s = e.documentElement; + s.appendChild(r); + var o = n.offsetWidth; + i.overflow = "scroll"; + var u = n.offsetWidth; + return o == u && (u = r.clientWidth), s.removeChild(r), o - u; + }), + typeof document == "undefined" && (t.importCssString = function () {}), + (t.computedStyle = function (e, t) { + return window.getComputedStyle(e, "") || {}; + }), + (t.setStyle = function (e, t, n) { + e[t] !== n && (e[t] = n); + }), + (t.HAS_CSS_ANIMATION = !1), + (t.HAS_CSS_TRANSFORMS = !1), + (t.HI_DPI = r.isWin + ? typeof window != "undefined" && window.devicePixelRatio >= 1.5 + : !0); + if (typeof document != "undefined") { + var s = document.createElement("div"); + t.HI_DPI && s.style.transform !== undefined && (t.HAS_CSS_TRANSFORMS = !0), + !r.isEdge && + typeof s.style.animationName != "undefined" && + (t.HAS_CSS_ANIMATION = !0), + (s = null); + } + t.HAS_CSS_TRANSFORMS + ? (t.translate = function (e, t, n) { + e.style.transform = + "translate(" + Math.round(t) + "px, " + Math.round(n) + "px)"; + }) + : (t.translate = function (e, t, n) { + (e.style.top = Math.round(n) + "px"), (e.style.left = Math.round(t) + "px"); + }); + }, + ), + define("ace/lib/oop", ["require", "exports", "module"], function (e, t, n) { + "use strict"; + (t.inherits = function (e, t) { + (e.super_ = t), + (e.prototype = Object.create(t.prototype, { + constructor: { value: e, enumerable: !1, writable: !0, configurable: !0 }, + })); + }), + (t.mixin = function (e, t) { + for (var n in t) e[n] = t[n]; + return e; + }), + (t.implement = function (e, n) { + t.mixin(e, n); + }); + }), + define( + "ace/lib/keys", + ["require", "exports", "module", "ace/lib/fixoldbrowsers", "ace/lib/oop"], + function (e, t, n) { + "use strict"; + e("./fixoldbrowsers"); + var r = e("./oop"), + i = (function () { + var e = { + MODIFIER_KEYS: { 16: "Shift", 17: "Ctrl", 18: "Alt", 224: "Meta" }, + KEY_MODS: { + ctrl: 1, + alt: 2, + option: 2, + shift: 4, + super: 8, + meta: 8, + command: 8, + cmd: 8, + }, + FUNCTION_KEYS: { + 8: "Backspace", + 9: "Tab", + 13: "Return", + 19: "Pause", + 27: "Esc", + 32: "Space", + 33: "PageUp", + 34: "PageDown", + 35: "End", + 36: "Home", + 37: "Left", + 38: "Up", + 39: "Right", + 40: "Down", + 44: "Print", + 45: "Insert", + 46: "Delete", + 96: "Numpad0", + 97: "Numpad1", + 98: "Numpad2", + 99: "Numpad3", + 100: "Numpad4", + 101: "Numpad5", + 102: "Numpad6", + 103: "Numpad7", + 104: "Numpad8", + 105: "Numpad9", + "-13": "NumpadEnter", + 112: "F1", + 113: "F2", + 114: "F3", + 115: "F4", + 116: "F5", + 117: "F6", + 118: "F7", + 119: "F8", + 120: "F9", + 121: "F10", + 122: "F11", + 123: "F12", + 144: "Numlock", + 145: "Scrolllock", + }, + PRINTABLE_KEYS: { + 32: " ", + 48: "0", + 49: "1", + 50: "2", + 51: "3", + 52: "4", + 53: "5", + 54: "6", + 55: "7", + 56: "8", + 57: "9", + 59: ";", + 61: "=", + 65: "a", + 66: "b", + 67: "c", + 68: "d", + 69: "e", + 70: "f", + 71: "g", + 72: "h", + 73: "i", + 74: "j", + 75: "k", + 76: "l", + 77: "m", + 78: "n", + 79: "o", + 80: "p", + 81: "q", + 82: "r", + 83: "s", + 84: "t", + 85: "u", + 86: "v", + 87: "w", + 88: "x", + 89: "y", + 90: "z", + 107: "+", + 109: "-", + 110: ".", + 186: ";", + 187: "=", + 188: ",", + 189: "-", + 190: ".", + 191: "/", + 192: "`", + 219: "[", + 220: "\\", + 221: "]", + 222: "'", + 111: "/", + 106: "*", + }, + }, + t, + n; + for (n in e.FUNCTION_KEYS) + (t = e.FUNCTION_KEYS[n].toLowerCase()), (e[t] = parseInt(n, 10)); + for (n in e.PRINTABLE_KEYS) + (t = e.PRINTABLE_KEYS[n].toLowerCase()), (e[t] = parseInt(n, 10)); + return ( + r.mixin(e, e.MODIFIER_KEYS), + r.mixin(e, e.PRINTABLE_KEYS), + r.mixin(e, e.FUNCTION_KEYS), + (e.enter = e["return"]), + (e.escape = e.esc), + (e.del = e["delete"]), + (e[173] = "-"), + (function () { + var t = ["cmd", "ctrl", "alt", "shift"]; + for (var n = Math.pow(2, t.length); n--; ) + e.KEY_MODS[n] = + t + .filter(function (t) { + return n & e.KEY_MODS[t]; + }) + .join("-") + "-"; + })(), + (e.KEY_MODS[0] = ""), + (e.KEY_MODS[-1] = "input-"), + e + ); + })(); + r.mixin(t, i), + (t.keyCodeToString = function (e) { + var t = i[e]; + return typeof t != "string" && (t = String.fromCharCode(e)), t.toLowerCase(); + }); + }, + ), + define( + "ace/lib/event", + ["require", "exports", "module", "ace/lib/keys", "ace/lib/useragent"], + function (e, t, n) { + "use strict"; + function a(e, t, n) { + var a = u(t); + if (!i.isMac && s) { + t.getModifierState && + (t.getModifierState("OS") || t.getModifierState("Win")) && + (a |= 8); + if (s.altGr) { + if ((3 & a) == 3) return; + s.altGr = 0; + } + if (n === 18 || n === 17) { + var f = "location" in t ? t.location : t.keyLocation; + if (n === 17 && f === 1) s[n] == 1 && (o = t.timeStamp); + else if (n === 18 && a === 3 && f === 2) { + var l = t.timeStamp - o; + l < 50 && (s.altGr = !0); + } + } + } + n in r.MODIFIER_KEYS && (n = -1), a & 8 && n >= 91 && n <= 93 && (n = -1); + if (!a && n === 13) { + var f = "location" in t ? t.location : t.keyLocation; + if (f === 3) { + e(t, a, -n); + if (t.defaultPrevented) return; + } + } + if (i.isChromeOS && a & 8) { + e(t, a, n); + if (t.defaultPrevented) return; + a &= -9; + } + return !!a || n in r.FUNCTION_KEYS || n in r.PRINTABLE_KEYS ? e(t, a, n) : !1; + } + function f() { + s = Object.create(null); + } + var r = e("./keys"), + i = e("./useragent"), + s = null, + o = 0; + (t.addListener = function (e, t, n) { + if (e.addEventListener) return e.addEventListener(t, n, !1); + if (e.attachEvent) { + var r = function () { + n.call(e, window.event); + }; + (n._wrapper = r), e.attachEvent("on" + t, r); + } + }), + (t.removeListener = function (e, t, n) { + if (e.removeEventListener) return e.removeEventListener(t, n, !1); + e.detachEvent && e.detachEvent("on" + t, n._wrapper || n); + }), + (t.stopEvent = function (e) { + return t.stopPropagation(e), t.preventDefault(e), !1; + }), + (t.stopPropagation = function (e) { + e.stopPropagation ? e.stopPropagation() : (e.cancelBubble = !0); + }), + (t.preventDefault = function (e) { + e.preventDefault ? e.preventDefault() : (e.returnValue = !1); + }), + (t.getButton = function (e) { + return e.type == "dblclick" + ? 0 + : e.type == "contextmenu" || + (i.isMac && e.ctrlKey && !e.altKey && !e.shiftKey) + ? 2 + : e.preventDefault + ? e.button + : { 1: 0, 2: 2, 4: 1 }[e.button]; + }), + (t.capture = function (e, n, r) { + function i(e) { + n && n(e), + r && r(e), + t.removeListener(document, "mousemove", n, !0), + t.removeListener(document, "mouseup", i, !0), + t.removeListener(document, "dragstart", i, !0); + } + return ( + t.addListener(document, "mousemove", n, !0), + t.addListener(document, "mouseup", i, !0), + t.addListener(document, "dragstart", i, !0), + i + ); + }), + (t.addTouchMoveListener = function (e, n) { + var r, i; + t.addListener(e, "touchstart", function (e) { + var t = e.touches, + n = t[0]; + (r = n.clientX), (i = n.clientY); + }), + t.addListener(e, "touchmove", function (e) { + var t = e.touches; + if (t.length > 1) return; + var s = t[0]; + (e.wheelX = r - s.clientX), + (e.wheelY = i - s.clientY), + (r = s.clientX), + (i = s.clientY), + n(e); + }); + }), + (t.addMouseWheelListener = function (e, n) { + "onmousewheel" in e + ? t.addListener(e, "mousewheel", function (e) { + var t = 8; + e.wheelDeltaX !== undefined + ? ((e.wheelX = -e.wheelDeltaX / t), + (e.wheelY = -e.wheelDeltaY / t)) + : ((e.wheelX = 0), (e.wheelY = -e.wheelDelta / t)), + n(e); + }) + : "onwheel" in e + ? t.addListener(e, "wheel", function (e) { + var t = 0.35; + switch (e.deltaMode) { + case e.DOM_DELTA_PIXEL: + (e.wheelX = e.deltaX * t || 0), + (e.wheelY = e.deltaY * t || 0); + break; + case e.DOM_DELTA_LINE: + case e.DOM_DELTA_PAGE: + (e.wheelX = (e.deltaX || 0) * 5), + (e.wheelY = (e.deltaY || 0) * 5); + } + n(e); + }) + : t.addListener(e, "DOMMouseScroll", function (e) { + e.axis && e.axis == e.HORIZONTAL_AXIS + ? ((e.wheelX = (e.detail || 0) * 5), (e.wheelY = 0)) + : ((e.wheelX = 0), (e.wheelY = (e.detail || 0) * 5)), + n(e); + }); + }), + (t.addMultiMouseDownListener = function (e, n, r, s) { + function c(e) { + t.getButton(e) !== 0 + ? (o = 0) + : e.detail > 1 + ? (o++, o > 4 && (o = 1)) + : (o = 1); + if (i.isIE) { + var c = Math.abs(e.clientX - u) > 5 || Math.abs(e.clientY - a) > 5; + if (!f || c) o = 1; + f && clearTimeout(f), + (f = setTimeout( + function () { + f = null; + }, + n[o - 1] || 600, + )), + o == 1 && ((u = e.clientX), (a = e.clientY)); + } + (e._clicks = o), r[s]("mousedown", e); + if (o > 4) o = 0; + else if (o > 1) return r[s](l[o], e); + } + function h(e) { + (o = 2), + f && clearTimeout(f), + (f = setTimeout( + function () { + f = null; + }, + n[o - 1] || 600, + )), + r[s]("mousedown", e), + r[s](l[o], e); + } + var o = 0, + u, + a, + f, + l = { 2: "dblclick", 3: "tripleclick", 4: "quadclick" }; + Array.isArray(e) || (e = [e]), + e.forEach(function (e) { + t.addListener(e, "mousedown", c), + i.isOldIE && t.addListener(e, "dblclick", h); + }); + }); + var u = + !i.isMac || !i.isOpera || "KeyboardEvent" in window + ? function (e) { + return ( + 0 | + (e.ctrlKey ? 1 : 0) | + (e.altKey ? 2 : 0) | + (e.shiftKey ? 4 : 0) | + (e.metaKey ? 8 : 0) + ); + } + : function (e) { + return ( + 0 | + (e.metaKey ? 1 : 0) | + (e.altKey ? 2 : 0) | + (e.shiftKey ? 4 : 0) | + (e.ctrlKey ? 8 : 0) + ); + }; + (t.getModifierString = function (e) { + return r.KEY_MODS[u(e)]; + }), + (t.addCommandKeyListener = function (e, n) { + var r = t.addListener; + if (i.isOldGecko || (i.isOpera && !("KeyboardEvent" in window))) { + var o = null; + r(e, "keydown", function (e) { + o = e.keyCode; + }), + r(e, "keypress", function (e) { + return a(n, e, o); + }); + } else { + var u = null; + r(e, "keydown", function (e) { + s[e.keyCode] = (s[e.keyCode] || 0) + 1; + var t = a(n, e, e.keyCode); + return (u = e.defaultPrevented), t; + }), + r(e, "keypress", function (e) { + u && + (e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) && + (t.stopEvent(e), (u = null)); + }), + r(e, "keyup", function (e) { + s[e.keyCode] = null; + }), + s || (f(), r(window, "focus", f)); + } + }); + if (typeof window == "object" && window.postMessage && !i.isOldIE) { + var l = 1; + t.nextTick = function (e, n) { + n = n || window; + var r = "zero-timeout-message-" + l++, + i = function (s) { + s.data == r && + (t.stopPropagation(s), t.removeListener(n, "message", i), e()); + }; + t.addListener(n, "message", i), n.postMessage(r, "*"); + }; + } + (t.$idleBlocked = !1), + (t.onIdle = function (e, n) { + return setTimeout(function r() { + t.$idleBlocked ? setTimeout(r, 100) : e(); + }, n); + }), + (t.$idleBlockId = null), + (t.blockIdle = function (e) { + t.$idleBlockId && clearTimeout(t.$idleBlockId), + (t.$idleBlocked = !0), + (t.$idleBlockId = setTimeout(function () { + t.$idleBlocked = !1; + }, e || 100)); + }), + (t.nextFrame = + typeof window == "object" && + (window.requestAnimationFrame || + window.mozRequestAnimationFrame || + window.webkitRequestAnimationFrame || + window.msRequestAnimationFrame || + window.oRequestAnimationFrame)), + t.nextFrame + ? (t.nextFrame = t.nextFrame.bind(window)) + : (t.nextFrame = function (e) { + setTimeout(e, 17); + }); + }, + ), + define("ace/range", ["require", "exports", "module"], function (e, t, n) { + "use strict"; + var r = function (e, t) { + return e.row - t.row || e.column - t.column; + }, + i = function (e, t, n, r) { + (this.start = { row: e, column: t }), (this.end = { row: n, column: r }); + }; + (function () { + (this.isEqual = function (e) { + return ( + this.start.row === e.start.row && + this.end.row === e.end.row && + this.start.column === e.start.column && + this.end.column === e.end.column + ); + }), + (this.toString = function () { + return ( + "Range: [" + + this.start.row + + "/" + + this.start.column + + "] -> [" + + this.end.row + + "/" + + this.end.column + + "]" + ); + }), + (this.contains = function (e, t) { + return this.compare(e, t) == 0; + }), + (this.compareRange = function (e) { + var t, + n = e.end, + r = e.start; + return ( + (t = this.compare(n.row, n.column)), + t == 1 + ? ((t = this.compare(r.row, r.column)), t == 1 ? 2 : t == 0 ? 1 : 0) + : t == -1 + ? -2 + : ((t = this.compare(r.row, r.column)), + t == -1 ? -1 : t == 1 ? 42 : 0) + ); + }), + (this.comparePoint = function (e) { + return this.compare(e.row, e.column); + }), + (this.containsRange = function (e) { + return this.comparePoint(e.start) == 0 && this.comparePoint(e.end) == 0; + }), + (this.intersects = function (e) { + var t = this.compareRange(e); + return t == -1 || t == 0 || t == 1; + }), + (this.isEnd = function (e, t) { + return this.end.row == e && this.end.column == t; + }), + (this.isStart = function (e, t) { + return this.start.row == e && this.start.column == t; + }), + (this.setStart = function (e, t) { + typeof e == "object" + ? ((this.start.column = e.column), (this.start.row = e.row)) + : ((this.start.row = e), (this.start.column = t)); + }), + (this.setEnd = function (e, t) { + typeof e == "object" + ? ((this.end.column = e.column), (this.end.row = e.row)) + : ((this.end.row = e), (this.end.column = t)); + }), + (this.inside = function (e, t) { + return this.compare(e, t) == 0 + ? this.isEnd(e, t) || this.isStart(e, t) + ? !1 + : !0 + : !1; + }), + (this.insideStart = function (e, t) { + return this.compare(e, t) == 0 ? (this.isEnd(e, t) ? !1 : !0) : !1; + }), + (this.insideEnd = function (e, t) { + return this.compare(e, t) == 0 ? (this.isStart(e, t) ? !1 : !0) : !1; + }), + (this.compare = function (e, t) { + return !this.isMultiLine() && e === this.start.row + ? t < this.start.column + ? -1 + : t > this.end.column + ? 1 + : 0 + : e < this.start.row + ? -1 + : e > this.end.row + ? 1 + : this.start.row === e + ? t >= this.start.column + ? 0 + : -1 + : this.end.row === e + ? t <= this.end.column + ? 0 + : 1 + : 0; + }), + (this.compareStart = function (e, t) { + return this.start.row == e && this.start.column == t ? -1 : this.compare(e, t); + }), + (this.compareEnd = function (e, t) { + return this.end.row == e && this.end.column == t ? 1 : this.compare(e, t); + }), + (this.compareInside = function (e, t) { + return this.end.row == e && this.end.column == t + ? 1 + : this.start.row == e && this.start.column == t + ? -1 + : this.compare(e, t); + }), + (this.clipRows = function (e, t) { + if (this.end.row > t) var n = { row: t + 1, column: 0 }; + else if (this.end.row < e) var n = { row: e, column: 0 }; + if (this.start.row > t) var r = { row: t + 1, column: 0 }; + else if (this.start.row < e) var r = { row: e, column: 0 }; + return i.fromPoints(r || this.start, n || this.end); + }), + (this.extend = function (e, t) { + var n = this.compare(e, t); + if (n == 0) return this; + if (n == -1) var r = { row: e, column: t }; + else var s = { row: e, column: t }; + return i.fromPoints(r || this.start, s || this.end); + }), + (this.isEmpty = function () { + return this.start.row === this.end.row && this.start.column === this.end.column; + }), + (this.isMultiLine = function () { + return this.start.row !== this.end.row; + }), + (this.clone = function () { + return i.fromPoints(this.start, this.end); + }), + (this.collapseRows = function () { + return this.end.column == 0 + ? new i(this.start.row, 0, Math.max(this.start.row, this.end.row - 1), 0) + : new i(this.start.row, 0, this.end.row, 0); + }), + (this.toScreenRange = function (e) { + var t = e.documentToScreenPosition(this.start), + n = e.documentToScreenPosition(this.end); + return new i(t.row, t.column, n.row, n.column); + }), + (this.moveBy = function (e, t) { + (this.start.row += e), + (this.start.column += t), + (this.end.row += e), + (this.end.column += t); + }); + }).call(i.prototype), + (i.fromPoints = function (e, t) { + return new i(e.row, e.column, t.row, t.column); + }), + (i.comparePoints = r), + (i.comparePoints = function (e, t) { + return e.row - t.row || e.column - t.column; + }), + (t.Range = i); + }), + define("ace/lib/lang", ["require", "exports", "module"], function (e, t, n) { + "use strict"; + (t.last = function (e) { + return e[e.length - 1]; + }), + (t.stringReverse = function (e) { + return e.split("").reverse().join(""); + }), + (t.stringRepeat = function (e, t) { + var n = ""; + while (t > 0) { + t & 1 && (n += e); + if ((t >>= 1)) e += e; + } + return n; + }); + var r = /^\s\s*/, + i = /\s\s*$/; + (t.stringTrimLeft = function (e) { + return e.replace(r, ""); + }), + (t.stringTrimRight = function (e) { + return e.replace(i, ""); + }), + (t.copyObject = function (e) { + var t = {}; + for (var n in e) t[n] = e[n]; + return t; + }), + (t.copyArray = function (e) { + var t = []; + for (var n = 0, r = e.length; n < r; n++) + e[n] && typeof e[n] == "object" + ? (t[n] = this.copyObject(e[n])) + : (t[n] = e[n]); + return t; + }), + (t.deepCopy = function s(e) { + if (typeof e != "object" || !e) return e; + var t; + if (Array.isArray(e)) { + t = []; + for (var n = 0; n < e.length; n++) t[n] = s(e[n]); + return t; + } + if (Object.prototype.toString.call(e) !== "[object Object]") return e; + t = {}; + for (var n in e) t[n] = s(e[n]); + return t; + }), + (t.arrayToMap = function (e) { + var t = {}; + for (var n = 0; n < e.length; n++) t[e[n]] = 1; + return t; + }), + (t.createMap = function (e) { + var t = Object.create(null); + for (var n in e) t[n] = e[n]; + return t; + }), + (t.arrayRemove = function (e, t) { + for (var n = 0; n <= e.length; n++) t === e[n] && e.splice(n, 1); + }), + (t.escapeRegExp = function (e) { + return e.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1"); + }), + (t.escapeHTML = function (e) { + return ("" + e) + .replace(/&/g, "&") + .replace(/"/g, """) + .replace(/'/g, "'") + .replace(/ h.length + ? (e = e.substr(9)) + : e.substr(0, 4) == h.substr(0, 4) + ? (e = e.substr(4, e.length - h.length + 1)) + : e.charAt(e.length - 1) == h.charAt(0) && + (e = e.slice(0, -1)), + e != h.charAt(0) && + e.charAt(e.length - 1) == h.charAt(0) && + (e = e.slice(0, -1)), + e && t.onTextInput(e)), + p && (p = !1), + L && (L = !1); + }, + O = function (e) { + if (m) return; + var t = c.value; + A(t), T(); + }, + M = function (e, t, n) { + var r = e.clipboardData || window.clipboardData; + if (!r || f) return; + var i = l || n ? "Text" : "text/plain"; + try { + return t ? r.setData(i, t) !== !1 : r.getData(i); + } catch (e) { + if (!n) return M(e, t, !0); + } + }, + _ = function (e, n) { + var s = t.getCopyText(); + if (!s) return r.preventDefault(e); + M(e, s) + ? (i.isIOS && + ((d = n), + (c.value = "\n aa" + s + "a a\n"), + c.setSelectionRange(4, 4 + s.length), + (p = { value: s })), + n ? t.onCut() : t.onCopy(), + i.isIOS || r.preventDefault(e)) + : ((p = !0), + (c.value = s), + c.select(), + setTimeout(function () { + (p = !1), T(), x(), n ? t.onCut() : t.onCopy(); + })); + }, + D = function (e) { + _(e, !0); + }, + P = function (e) { + _(e, !1); + }, + H = function (e) { + var n = M(e); + typeof n == "string" + ? (n && t.onPaste(n, e), + i.isIE && setTimeout(x), + r.preventDefault(e)) + : ((c.value = ""), (v = !0)); + }; + r.addCommandKeyListener(c, t.onCommandKey.bind(t)), + r.addListener(c, "select", C), + r.addListener(c, "input", O), + r.addListener(c, "cut", D), + r.addListener(c, "copy", P), + r.addListener(c, "paste", H); + var B = function (e) { + if (m || !t.onCompositionStart || t.$readOnly) return; + (m = {}), + (m.canUndo = t.session.$undoManager), + t.onCompositionStart(), + setTimeout(j, 0), + t.on("mousedown", F), + m.canUndo && + !t.selection.isEmpty() && + (t.insert(""), + t.session.markUndoGroup(), + t.selection.clearSelection()), + t.session.markUndoGroup(); + }, + j = function () { + if (!m || !t.onCompositionUpdate || t.$readOnly) return; + var e = c.value.replace(/\x01/g, ""); + if (m.lastValue === e) return; + t.onCompositionUpdate(e), + m.lastValue && t.undo(), + m.canUndo && (m.lastValue = e); + if (m.lastValue) { + var n = t.selection.getRange(); + t.insert(m.lastValue), + t.session.markUndoGroup(), + (m.range = t.selection.getRange()), + t.selection.setRange(n), + t.selection.clearSelection(); + } + }, + F = function (e) { + if (!t.onCompositionEnd || t.$readOnly) return; + var n = m; + m = !1; + var r = setTimeout(function () { + r = null; + var e = c.value.replace(/\x01/g, ""); + if (m) return; + e == n.lastValue ? T() : !n.lastValue && e && (T(), A(e)); + }); + (k = function (i) { + return ( + r && clearTimeout(r), + (i = i.replace(/\x01/g, "")), + i == n.lastValue ? "" : (n.lastValue && r && t.undo(), i) + ); + }), + t.onCompositionEnd(), + t.removeListener("mousedown", F), + e.type == "compositionend" && + n.range && + t.selection.setRange(n.range); + var s = + (!!i.isChrome && i.isChrome >= 53) || + (!!i.isWebKit && i.isWebKit >= 603); + s && O(); + }, + I = o.delayedCall(j, 50); + r.addListener(c, "compositionstart", B), + r.addListener(c, "compositionupdate", function () { + I.schedule(); + }), + r.addListener(c, "keyup", function () { + I.schedule(); + }), + r.addListener(c, "keydown", function () { + I.schedule(); + }), + r.addListener(c, "compositionend", F), + (this.getElement = function () { + return c; + }), + (this.setReadOnly = function (e) { + c.readOnly = e; + }), + (this.onContextMenu = function (e) { + (L = !0), + x(t.selection.isEmpty()), + t._emit("nativecontextmenu", { target: t, domEvent: e }), + this.moveToMouse(e, !0); + }), + (this.moveToMouse = function (e, n) { + g || (g = c.style.cssText), + (c.style.cssText = + (n ? "z-index:100000;" : "") + + "height:" + + c.style.height + + ";" + + (i.isIE ? "opacity:0.1;" : "")); + var o = t.container.getBoundingClientRect(), + u = s.computedStyle(t.container), + a = o.top + (parseInt(u.borderTopWidth) || 0), + f = o.left + (parseInt(o.borderLeftWidth) || 0), + l = o.bottom - a - c.clientHeight - 2, + h = function (e) { + (c.style.left = e.clientX - f - 2 + "px"), + (c.style.top = Math.min(e.clientY - a - 2, l) + "px"); + }; + h(e); + if (e.type != "mousedown") return; + t.renderer.$keepTextAreaAtCursor && + (t.renderer.$keepTextAreaAtCursor = null), + clearTimeout(q), + i.isWin && r.capture(t.container, h, R); + }), + (this.onContextMenuClose = R); + var q, + U = function (e) { + t.textInput.onContextMenu(e), R(); + }; + r.addListener(c, "mouseup", U), + r.addListener(c, "mousedown", function (e) { + e.preventDefault(), R(); + }), + r.addListener(t.renderer.scroller, "contextmenu", U), + r.addListener(c, "contextmenu", U); + if (i.isIOS) { + var z = null, + W = !1; + e.addEventListener("keydown", function (e) { + z && clearTimeout(z), (W = !0); + }), + e.addEventListener("keyup", function (e) { + z = setTimeout(function () { + W = !1; + }, 100); + }); + var X = function (e) { + if (document.activeElement !== c) return; + if (W) return; + if (d) + return setTimeout(function () { + d = !1; + }, 100); + var n = c.selectionStart, + r = c.selectionEnd; + c.setSelectionRange(4, 5); + if (n == r) + switch (n) { + case 0: + t.onCommandKey(null, 0, u.up); + break; + case 1: + t.onCommandKey(null, 0, u.home); + break; + case 2: + t.onCommandKey(null, a.option, u.left); + break; + case 4: + t.onCommandKey(null, 0, u.left); + break; + case 5: + t.onCommandKey(null, 0, u.right); + break; + case 7: + t.onCommandKey(null, a.option, u.right); + break; + case 8: + t.onCommandKey(null, 0, u.end); + break; + case 9: + t.onCommandKey(null, 0, u.down); + } + else { + switch (r) { + case 6: + t.onCommandKey(null, a.shift, u.right); + break; + case 7: + t.onCommandKey(null, a.shift | a.option, u.right); + break; + case 8: + t.onCommandKey(null, a.shift, u.end); + break; + case 9: + t.onCommandKey(null, a.shift, u.down); + } + switch (n) { + case 0: + t.onCommandKey(null, a.shift, u.up); + break; + case 1: + t.onCommandKey(null, a.shift, u.home); + break; + case 2: + t.onCommandKey(null, a.shift | a.option, u.left); + break; + case 3: + t.onCommandKey(null, a.shift, u.left); + } + } + }; + document.addEventListener("selectionchange", X), + t.on("destroy", function () { + document.removeEventListener("selectionchange", X); + }); + } + }; + t.TextInput = c; + }, + ), + define( + "ace/keyboard/textinput", + [ + "require", + "exports", + "module", + "ace/lib/event", + "ace/lib/useragent", + "ace/lib/dom", + "ace/lib/lang", + "ace/keyboard/textinput_ios", + ], + function (e, t, n) { + "use strict"; + var r = e("../lib/event"), + i = e("../lib/useragent"), + s = e("../lib/dom"), + o = e("../lib/lang"), + u = i.isChrome < 18, + a = i.isIE, + f = i.isChrome > 63, + l = 400, + c = e("./textinput_ios").TextInput, + h = function (e, t) { + function C() { + if (d || v) return; + if (!T && !O) return; + d = !0; + var e = t.selection, + r = e.getRange(), + i = e.cursor.row, + s = r.start.column, + o = r.end.column, + u = t.session.getLine(i); + if (r.start.row != i) { + var a = t.session.getLine(i - 1); + (s = r.start.row < i - 1 ? 0 : s), + (o += a.length + 1), + (u = a + "\n" + u); + } else if (r.end.row != i) { + var f = t.session.getLine(i + 1); + (o = r.end.row > i + 1 ? f.length : o), + (o += u.length + 1), + (u = u + "\n" + f); + } + u.length > l && + (s < l && o < l ? (u = u.slice(0, l)) : ((u = "\n"), (s = 0), (o = 1))); + var c = u + "\n\n"; + c != E && ((n.value = E = c), (S = x = c.length)), + O && ((S = n.selectionStart), (x = n.selectionEnd)); + if (x != o || S != s) + try { + n.setSelectionRange(s, o), (S = s), (x = o); + } catch (h) {} + d = !1; + } + function R() { + (w = !0), n.blur(), n.focus(), (w = !1); + } + function z(e) { + e.keyCode == 27 && + n.value.length < n.selectionStart && + (d || (E = n.value), (S = x = -1), C()), + U(); + } + function X() { + clearTimeout(W), + (W = setTimeout(function () { + m && ((n.style.cssText = m), (m = "")), + t.renderer.$keepTextAreaAtCursor == null && + ((t.renderer.$keepTextAreaAtCursor = !0), + t.renderer.$moveTextAreaToCursor()); + }, 0)); + } + if (i.isIOS) return c.call(this, e, t); + var n = s.createElement("textarea"); + (n.className = "ace_text-input"), + n.setAttribute("wrap", "off"), + n.setAttribute("autocorrect", "off"), + n.setAttribute("autocapitalize", "off"), + n.setAttribute("spellcheck", !1), + (n.style.opacity = "0"), + e.insertBefore(n, e.firstChild); + var h = !1, + p = !1, + d = !1, + v = !1, + m = "", + g = !0, + y = !1; + i.isMobile || (n.style.fontSize = "1px"); + var b = !1, + w = !1, + E = "", + S = 0, + x = 0; + try { + var T = document.activeElement === n; + } catch (N) {} + r.addListener(n, "blur", function (e) { + if (w) return; + t.onBlur(e), (T = !1); + }), + r.addListener(n, "focus", function (e) { + if (w) return; + (T = !0), t.onFocus(e), C(); + }), + (this.$focusScroll = !1), + (this.focus = function () { + if (m || f || this.$focusScroll == "browser") + return n.focus({ preventScroll: !0 }); + if (!document.documentElement.contains(n)) return; + var e = n.style.top; + (n.style.position = "fixed"), (n.style.top = "0px"); + var t = n.getBoundingClientRect().top != 0, + r = []; + if (t) { + var i = n.parentElement; + while (i && i.nodeType == 1) + r.push(i), + i.setAttribute("ace_nocontext", !0), + !i.parentElement && i.getRootNode + ? (i = i.getRootNode().host) + : (i = i.parentElement); + } + n.focus({ preventScroll: !0 }), + t && + r.forEach(function (e) { + e.removeAttribute("ace_nocontext"); + }), + setTimeout(function () { + (n.style.position = ""), + n.style.top == "0px" && (n.style.top = e); + }, 0); + }), + (this.blur = function () { + n.blur(); + }), + (this.isFocused = function () { + return T; + }), + t.on("beforeEndOperation", function () { + if (t.curOp && t.curOp.command.name == "insertstring") return; + d && ((E = n.value = ""), q()), C(); + }), + T && t.onFocus(); + var k = function (e) { + return ( + e.selectionStart === 0 && + e.selectionEnd >= E.length && + e.value === E && + E && + e.selectionEnd !== x + ); + }, + L = function (e) { + if (d) return; + h ? (h = !1) : k(n) && (t.selectAll(), C()); + }, + A = null; + (this.setInputHandler = function (e) { + A = e; + }), + (this.getInputHandler = function () { + return A; + }); + var O = !1, + M = function (e, r) { + O && (O = !1); + if (p) return C(), e && t.onPaste(e), (p = !1), ""; + var i = n.selectionStart, + s = n.selectionEnd, + o = S, + u = E.length - x, + a = e, + f = e.length - i, + l = e.length - s, + c = 0; + while (o > 0 && E[c] == e[c]) c++, o--; + (a = a.slice(c)), (c = 1); + while ( + u > 0 && + E.length - c > S - 1 && + E[E.length - c] == e[e.length - c] + ) + c++, u--; + return ( + (f -= c - 1), + (l -= c - 1), + (a = a.slice(0, a.length - c + 1)), + !r && f == a.length && !o && !u && !l + ? "" + : ((v = !0), + (a && !o && !u && !f && !l) || b + ? t.onTextInput(a) + : t.onTextInput(a, { + extendLeft: o, + extendRight: u, + restoreStart: f, + restoreEnd: l, + }), + (v = !1), + (E = e), + (S = i), + (x = s), + a) + ); + }, + _ = function (e) { + if (d) return I(); + var t = n.value, + r = M(t, !0); + (t.length > l + 100 || /\n/.test(r)) && C(); + }, + D = function (e, t, n) { + var r = e.clipboardData || window.clipboardData; + if (!r || u) return; + var i = a || n ? "Text" : "text/plain"; + try { + return t ? r.setData(i, t) !== !1 : r.getData(i); + } catch (e) { + if (!n) return D(e, t, !0); + } + }, + P = function (e, i) { + var s = t.getCopyText(); + if (!s) return r.preventDefault(e); + D(e, s) + ? (i ? t.onCut() : t.onCopy(), r.preventDefault(e)) + : ((h = !0), + (n.value = s), + n.select(), + setTimeout(function () { + (h = !1), C(), i ? t.onCut() : t.onCopy(); + })); + }, + H = function (e) { + P(e, !0); + }, + B = function (e) { + P(e, !1); + }, + j = function (e) { + var s = D(e); + typeof s == "string" + ? (s && t.onPaste(s, e), + i.isIE && setTimeout(C), + r.preventDefault(e)) + : ((n.value = ""), (p = !0)); + }; + r.addCommandKeyListener(n, t.onCommandKey.bind(t)), + r.addListener(n, "select", L), + r.addListener(n, "input", _), + r.addListener(n, "cut", H), + r.addListener(n, "copy", B), + r.addListener(n, "paste", j), + (!("oncut" in n) || !("oncopy" in n) || !("onpaste" in n)) && + r.addListener(e, "keydown", function (e) { + if ((i.isMac && !e.metaKey) || !e.ctrlKey) return; + switch (e.keyCode) { + case 67: + B(e); + break; + case 86: + j(e); + break; + case 88: + H(e); + } + }); + var F = function (e) { + if (d || !t.onCompositionStart || t.$readOnly) return; + d = {}; + if (b) return; + setTimeout(I, 0), t.on("mousedown", R); + var r = t.getSelectionRange(); + (r.end.row = r.start.row), + (r.end.column = r.start.column), + (d.markerRange = r), + (d.selectionStart = S), + t.onCompositionStart(d), + d.useTextareaForIME + ? ((n.value = ""), (E = ""), (S = 0), (x = 0)) + : (n.msGetInputContext && (d.context = n.msGetInputContext()), + n.getInputContext && (d.context = n.getInputContext())); + }, + I = function () { + if (!d || !t.onCompositionUpdate || t.$readOnly) return; + if (b) return R(); + if (d.useTextareaForIME) t.onCompositionUpdate(n.value); + else { + var e = n.value; + M(e), + d.markerRange && + (d.context && + (d.markerRange.start.column = d.selectionStart = + d.context.compositionStartOffset), + (d.markerRange.end.column = + d.markerRange.start.column + x - d.selectionStart)); + } + }, + q = function (e) { + if (!t.onCompositionEnd || t.$readOnly) return; + (d = !1), t.onCompositionEnd(), t.off("mousedown", R), e && _(); + }, + U = o.delayedCall(I, 50).schedule.bind(null, null); + r.addListener(n, "compositionstart", F), + r.addListener(n, "compositionupdate", I), + r.addListener(n, "keyup", z), + r.addListener(n, "keydown", U), + r.addListener(n, "compositionend", q), + (this.getElement = function () { + return n; + }), + (this.setCommandMode = function (e) { + (b = e), (n.readOnly = !1); + }), + (this.setReadOnly = function (e) { + b || (n.readOnly = e); + }), + (this.setCopyWithEmptySelection = function (e) { + y = e; + }), + (this.onContextMenu = function (e) { + (O = !0), + C(), + t._emit("nativecontextmenu", { target: t, domEvent: e }), + this.moveToMouse(e, !0); + }), + (this.moveToMouse = function (e, o) { + m || (m = n.style.cssText), + (n.style.cssText = + (o ? "z-index:100000;" : "") + + (i.isIE ? "opacity:0.1;" : "") + + "text-indent: -" + + (S + x) * t.renderer.characterWidth * 0.5 + + "px;"); + var u = t.container.getBoundingClientRect(), + a = s.computedStyle(t.container), + f = u.top + (parseInt(a.borderTopWidth) || 0), + l = u.left + (parseInt(u.borderLeftWidth) || 0), + c = u.bottom - f - n.clientHeight - 2, + h = function (e) { + (n.style.left = e.clientX - l - 2 + "px"), + (n.style.top = Math.min(e.clientY - f - 2, c) + "px"); + }; + h(e); + if (e.type != "mousedown") return; + t.renderer.$keepTextAreaAtCursor && + (t.renderer.$keepTextAreaAtCursor = null), + clearTimeout(W), + i.isWin && r.capture(t.container, h, X); + }), + (this.onContextMenuClose = X); + var W, + V = function (e) { + t.textInput.onContextMenu(e), X(); + }; + r.addListener(n, "mouseup", V), + r.addListener(n, "mousedown", function (e) { + e.preventDefault(), X(); + }), + r.addListener(t.renderer.scroller, "contextmenu", V), + r.addListener(n, "contextmenu", V); + }; + t.TextInput = h; + }, + ), + define( + "ace/mouse/default_handlers", + ["require", "exports", "module", "ace/lib/useragent"], + function (e, t, n) { + "use strict"; + function o(e) { + e.$clickSelection = null; + var t = e.editor; + t.setDefaultHandler("mousedown", this.onMouseDown.bind(e)), + t.setDefaultHandler("dblclick", this.onDoubleClick.bind(e)), + t.setDefaultHandler("tripleclick", this.onTripleClick.bind(e)), + t.setDefaultHandler("quadclick", this.onQuadClick.bind(e)), + t.setDefaultHandler("mousewheel", this.onMouseWheel.bind(e)), + t.setDefaultHandler("touchmove", this.onTouchMove.bind(e)); + var n = [ + "select", + "startSelect", + "selectEnd", + "selectAllEnd", + "selectByWordsEnd", + "selectByLinesEnd", + "dragWait", + "dragWaitEnd", + "focusWait", + ]; + n.forEach(function (t) { + e[t] = this[t]; + }, this), + (e.selectByLines = this.extendSelectionBy.bind(e, "getLineRange")), + (e.selectByWords = this.extendSelectionBy.bind(e, "getWordRange")); + } + function u(e, t, n, r) { + return Math.sqrt(Math.pow(n - e, 2) + Math.pow(r - t, 2)); + } + function a(e, t) { + if (e.start.row == e.end.row) var n = 2 * t.column - e.start.column - e.end.column; + else if (e.start.row == e.end.row - 1 && !e.start.column && !e.end.column) + var n = t.column - 4; + else var n = 2 * t.row - e.start.row - e.end.row; + return n < 0 + ? { cursor: e.start, anchor: e.end } + : { cursor: e.end, anchor: e.start }; + } + var r = e("../lib/useragent"), + i = 0, + s = 250; + (function () { + (this.onMouseDown = function (e) { + var t = e.inSelection(), + n = e.getDocumentPosition(); + this.mousedownEvent = e; + var i = this.editor, + s = e.getButton(); + if (s !== 0) { + var o = i.getSelectionRange(), + u = o.isEmpty(); + (u || s == 1) && i.selection.moveToPosition(n), + s == 2 && + (i.textInput.onContextMenu(e.domEvent), + r.isMozilla || e.preventDefault()); + return; + } + this.mousedownEvent.time = Date.now(); + if (t && !i.isFocused()) { + i.focus(); + if (this.$focusTimeout && !this.$clickSelection && !i.inMultiSelectMode) { + this.setState("focusWait"), this.captureMouse(e); + return; + } + } + return ( + this.captureMouse(e), + this.startSelect(n, e.domEvent._clicks > 1), + e.preventDefault() + ); + }), + (this.startSelect = function (e, t) { + e = e || this.editor.renderer.screenToTextCoordinates(this.x, this.y); + var n = this.editor; + if (!this.mousedownEvent) return; + this.mousedownEvent.getShiftKey() + ? n.selection.selectToPosition(e) + : t || n.selection.moveToPosition(e), + t || this.select(), + n.renderer.scroller.setCapture && n.renderer.scroller.setCapture(), + n.setStyle("ace_selecting"), + this.setState("select"); + }), + (this.select = function () { + var e, + t = this.editor, + n = t.renderer.screenToTextCoordinates(this.x, this.y); + if (this.$clickSelection) { + var r = this.$clickSelection.comparePoint(n); + if (r == -1) e = this.$clickSelection.end; + else if (r == 1) e = this.$clickSelection.start; + else { + var i = a(this.$clickSelection, n); + (n = i.cursor), (e = i.anchor); + } + t.selection.setSelectionAnchor(e.row, e.column); + } + t.selection.selectToPosition(n), t.renderer.scrollCursorIntoView(); + }), + (this.extendSelectionBy = function (e) { + var t, + n = this.editor, + r = n.renderer.screenToTextCoordinates(this.x, this.y), + i = n.selection[e](r.row, r.column); + if (this.$clickSelection) { + var s = this.$clickSelection.comparePoint(i.start), + o = this.$clickSelection.comparePoint(i.end); + if (s == -1 && o <= 0) { + t = this.$clickSelection.end; + if (i.end.row != r.row || i.end.column != r.column) r = i.start; + } else if (o == 1 && s >= 0) { + t = this.$clickSelection.start; + if (i.start.row != r.row || i.start.column != r.column) r = i.end; + } else if (s == -1 && o == 1) (r = i.end), (t = i.start); + else { + var u = a(this.$clickSelection, r); + (r = u.cursor), (t = u.anchor); + } + n.selection.setSelectionAnchor(t.row, t.column); + } + n.selection.selectToPosition(r), n.renderer.scrollCursorIntoView(); + }), + (this.selectEnd = + this.selectAllEnd = + this.selectByWordsEnd = + this.selectByLinesEnd = + function () { + (this.$clickSelection = null), + this.editor.unsetStyle("ace_selecting"), + this.editor.renderer.scroller.releaseCapture && + this.editor.renderer.scroller.releaseCapture(); + }), + (this.focusWait = function () { + var e = u(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y), + t = Date.now(); + (e > i || t - this.mousedownEvent.time > this.$focusTimeout) && + this.startSelect(this.mousedownEvent.getDocumentPosition()); + }), + (this.onDoubleClick = function (e) { + var t = e.getDocumentPosition(), + n = this.editor, + r = n.session, + i = r.getBracketRange(t); + i + ? (i.isEmpty() && (i.start.column--, i.end.column++), + this.setState("select")) + : ((i = n.selection.getWordRange(t.row, t.column)), + this.setState("selectByWords")), + (this.$clickSelection = i), + this.select(); + }), + (this.onTripleClick = function (e) { + var t = e.getDocumentPosition(), + n = this.editor; + this.setState("selectByLines"); + var r = n.getSelectionRange(); + r.isMultiLine() && r.contains(t.row, t.column) + ? ((this.$clickSelection = n.selection.getLineRange(r.start.row)), + (this.$clickSelection.end = n.selection.getLineRange(r.end.row).end)) + : (this.$clickSelection = n.selection.getLineRange(t.row)), + this.select(); + }), + (this.onQuadClick = function (e) { + var t = this.editor; + t.selectAll(), + (this.$clickSelection = t.getSelectionRange()), + this.setState("selectAll"); + }), + (this.onMouseWheel = function (e) { + if (e.getAccelKey()) return; + e.getShiftKey() && + e.wheelY && + !e.wheelX && + ((e.wheelX = e.wheelY), (e.wheelY = 0)); + var t = this.editor; + this.$lastScroll || (this.$lastScroll = { t: 0, vx: 0, vy: 0, allowed: 0 }); + var n = this.$lastScroll, + r = e.domEvent.timeStamp, + i = r - n.t, + o = i ? e.wheelX / i : n.vx, + u = i ? e.wheelY / i : n.vy; + i < s && ((o = (o + n.vx) / 2), (u = (u + n.vy) / 2)); + var a = Math.abs(o / u), + f = !1; + a >= 1 && t.renderer.isScrollableBy(e.wheelX * e.speed, 0) && (f = !0), + a <= 1 && t.renderer.isScrollableBy(0, e.wheelY * e.speed) && (f = !0); + if (f) n.allowed = r; + else if (r - n.allowed < s) { + var l = + Math.abs(o) <= 1.1 * Math.abs(n.vx) && + Math.abs(u) <= 1.1 * Math.abs(n.vy); + l ? ((f = !0), (n.allowed = r)) : (n.allowed = 0); + } + (n.t = r), (n.vx = o), (n.vy = u); + if (f) + return ( + t.renderer.scrollBy(e.wheelX * e.speed, e.wheelY * e.speed), + e.stop() + ); + }), + (this.onTouchMove = function (e) { + this.editor._emit("mousewheel", e); + }); + }).call(o.prototype), + (t.DefaultHandlers = o); + }, + ), + define( + "ace/tooltip", + ["require", "exports", "module", "ace/lib/oop", "ace/lib/dom"], + function (e, t, n) { + "use strict"; + function s(e) { + (this.isOpen = !1), (this.$element = null), (this.$parentNode = e); + } + var r = e("./lib/oop"), + i = e("./lib/dom"); + (function () { + (this.$init = function () { + return ( + (this.$element = i.createElement("div")), + (this.$element.className = "ace_tooltip"), + (this.$element.style.display = "none"), + this.$parentNode.appendChild(this.$element), + this.$element + ); + }), + (this.getElement = function () { + return this.$element || this.$init(); + }), + (this.setText = function (e) { + this.getElement().textContent = e; + }), + (this.setHtml = function (e) { + this.getElement().innerHTML = e; + }), + (this.setPosition = function (e, t) { + (this.getElement().style.left = e + "px"), + (this.getElement().style.top = t + "px"); + }), + (this.setClassName = function (e) { + i.addCssClass(this.getElement(), e); + }), + (this.show = function (e, t, n) { + e != null && this.setText(e), + t != null && n != null && this.setPosition(t, n), + this.isOpen || + ((this.getElement().style.display = "block"), (this.isOpen = !0)); + }), + (this.hide = function () { + this.isOpen && + ((this.getElement().style.display = "none"), (this.isOpen = !1)); + }), + (this.getHeight = function () { + return this.getElement().offsetHeight; + }), + (this.getWidth = function () { + return this.getElement().offsetWidth; + }), + (this.destroy = function () { + (this.isOpen = !1), + this.$element && + this.$element.parentNode && + this.$element.parentNode.removeChild(this.$element); + }); + }).call(s.prototype), + (t.Tooltip = s); + }, + ), + define( + "ace/mouse/default_gutter_handler", + [ + "require", + "exports", + "module", + "ace/lib/dom", + "ace/lib/oop", + "ace/lib/event", + "ace/tooltip", + ], + function (e, t, n) { + "use strict"; + function u(e) { + function l() { + var r = u.getDocumentPosition().row, + s = n.$annotations[r]; + if (!s) return c(); + var o = t.session.getLength(); + if (r == o) { + var a = t.renderer.pixelToScreenCoordinates(0, u.y).row, + l = u.$pos; + if (a > t.session.documentToScreenRow(l.row, l.column)) return c(); + } + if (f == s) return; + (f = s.text.join("
")), + i.setHtml(f), + i.show(), + t._signal("showGutterTooltip", i), + t.on("mousewheel", c); + if (e.$tooltipFollowsMouse) h(u); + else { + var p = u.domEvent.target, + d = p.getBoundingClientRect(), + v = i.getElement().style; + (v.left = d.right + "px"), (v.top = d.bottom + "px"); + } + } + function c() { + o && (o = clearTimeout(o)), + f && + (i.hide(), + (f = null), + t._signal("hideGutterTooltip", i), + t.removeEventListener("mousewheel", c)); + } + function h(e) { + i.setPosition(e.x, e.y); + } + var t = e.editor, + n = t.renderer.$gutterLayer, + i = new a(t.container); + e.editor.setDefaultHandler("guttermousedown", function (r) { + if (!t.isFocused() || r.getButton() != 0) return; + var i = n.getRegion(r); + if (i == "foldWidgets") return; + var s = r.getDocumentPosition().row, + o = t.session.selection; + if (r.getShiftKey()) o.selectTo(s, 0); + else { + if (r.domEvent.detail == 2) return t.selectAll(), r.preventDefault(); + e.$clickSelection = t.selection.getLineRange(s); + } + return e.setState("selectByLines"), e.captureMouse(r), r.preventDefault(); + }); + var o, u, f; + e.editor.setDefaultHandler("guttermousemove", function (t) { + var n = t.domEvent.target || t.domEvent.srcElement; + if (r.hasCssClass(n, "ace_fold-widget")) return c(); + f && e.$tooltipFollowsMouse && h(t), (u = t); + if (o) return; + o = setTimeout(function () { + (o = null), u && !e.isMousePressed ? l() : c(); + }, 50); + }), + s.addListener(t.renderer.$gutter, "mouseout", function (e) { + u = null; + if (!f || o) return; + o = setTimeout(function () { + (o = null), c(); + }, 50); + }), + t.on("changeSession", c); + } + function a(e) { + o.call(this, e); + } + var r = e("../lib/dom"), + i = e("../lib/oop"), + s = e("../lib/event"), + o = e("../tooltip").Tooltip; + i.inherits(a, o), + function () { + this.setPosition = function (e, t) { + var n = window.innerWidth || document.documentElement.clientWidth, + r = window.innerHeight || document.documentElement.clientHeight, + i = this.getWidth(), + s = this.getHeight(); + (e += 15), + (t += 15), + e + i > n && (e -= e + i - n), + t + s > r && (t -= 20 + s), + o.prototype.setPosition.call(this, e, t); + }; + }.call(a.prototype), + (t.GutterHandler = u); + }, + ), + define( + "ace/mouse/mouse_event", + ["require", "exports", "module", "ace/lib/event", "ace/lib/useragent"], + function (e, t, n) { + "use strict"; + var r = e("../lib/event"), + i = e("../lib/useragent"), + s = (t.MouseEvent = function (e, t) { + (this.domEvent = e), + (this.editor = t), + (this.x = this.clientX = e.clientX), + (this.y = this.clientY = e.clientY), + (this.$pos = null), + (this.$inSelection = null), + (this.propagationStopped = !1), + (this.defaultPrevented = !1); + }); + (function () { + (this.stopPropagation = function () { + r.stopPropagation(this.domEvent), (this.propagationStopped = !0); + }), + (this.preventDefault = function () { + r.preventDefault(this.domEvent), (this.defaultPrevented = !0); + }), + (this.stop = function () { + this.stopPropagation(), this.preventDefault(); + }), + (this.getDocumentPosition = function () { + return this.$pos + ? this.$pos + : ((this.$pos = this.editor.renderer.screenToTextCoordinates( + this.clientX, + this.clientY, + )), + this.$pos); + }), + (this.inSelection = function () { + if (this.$inSelection !== null) return this.$inSelection; + var e = this.editor, + t = e.getSelectionRange(); + if (t.isEmpty()) this.$inSelection = !1; + else { + var n = this.getDocumentPosition(); + this.$inSelection = t.contains(n.row, n.column); + } + return this.$inSelection; + }), + (this.getButton = function () { + return r.getButton(this.domEvent); + }), + (this.getShiftKey = function () { + return this.domEvent.shiftKey; + }), + (this.getAccelKey = i.isMac + ? function () { + return this.domEvent.metaKey; + } + : function () { + return this.domEvent.ctrlKey; + }); + }).call(s.prototype); + }, + ), + define( + "ace/mouse/dragdrop_handler", + ["require", "exports", "module", "ace/lib/dom", "ace/lib/event", "ace/lib/useragent"], + function (e, t, n) { + "use strict"; + function f(e) { + function T(e, n) { + var r = Date.now(), + i = !n || e.row != n.row, + s = !n || e.column != n.column; + if (!S || i || s) t.moveCursorToPosition(e), (S = r), (x = { x: p, y: d }); + else { + var o = l(x.x, x.y, p, d); + o > a + ? (S = null) + : r - S >= u && (t.renderer.scrollCursorIntoView(), (S = null)); + } + } + function N(e, n) { + var r = Date.now(), + i = t.renderer.layerConfig.lineHeight, + s = t.renderer.layerConfig.characterWidth, + u = t.renderer.scroller.getBoundingClientRect(), + a = { + x: { left: p - u.left, right: u.right - p }, + y: { top: d - u.top, bottom: u.bottom - d }, + }, + f = Math.min(a.x.left, a.x.right), + l = Math.min(a.y.top, a.y.bottom), + c = { row: e.row, column: e.column }; + f / s <= 2 && (c.column += a.x.left < a.x.right ? -3 : 2), + l / i <= 1 && (c.row += a.y.top < a.y.bottom ? -1 : 1); + var h = e.row != c.row, + v = e.column != c.column, + m = !n || e.row != n.row; + h || (v && !m) + ? E + ? r - E >= o && t.renderer.scrollCursorIntoView(c) + : (E = r) + : (E = null); + } + function C() { + var e = g; + (g = t.renderer.screenToTextCoordinates(p, d)), T(g, e), N(g, e); + } + function k() { + (m = t.selection.toOrientedRange()), + (h = t.session.addMarker(m, "ace_selection", t.getSelectionStyle())), + t.clearSelection(), + t.isFocused() && t.renderer.$cursorLayer.setBlinking(!1), + clearInterval(v), + C(), + (v = setInterval(C, 20)), + (y = 0), + i.addListener(document, "mousemove", O); + } + function L() { + clearInterval(v), + t.session.removeMarker(h), + (h = null), + t.selection.fromOrientedRange(m), + t.isFocused() && + !w && + t.renderer.$cursorLayer.setBlinking(!t.getReadOnly()), + (m = null), + (g = null), + (y = 0), + (E = null), + (S = null), + i.removeListener(document, "mousemove", O); + } + function O() { + A == null && + (A = setTimeout(function () { + A != null && h && L(); + }, 20)); + } + function M(e) { + var t = e.types; + return ( + !t || + Array.prototype.some.call(t, function (e) { + return e == "text/plain" || e == "Text"; + }) + ); + } + function _(e) { + var t = ["copy", "copymove", "all", "uninitialized"], + n = ["move", "copymove", "linkmove", "all", "uninitialized"], + r = s.isMac ? e.altKey : e.ctrlKey, + i = "uninitialized"; + try { + i = e.dataTransfer.effectAllowed.toLowerCase(); + } catch (e) {} + var o = "none"; + return ( + r && t.indexOf(i) >= 0 + ? (o = "copy") + : n.indexOf(i) >= 0 + ? (o = "move") + : t.indexOf(i) >= 0 && (o = "copy"), + o + ); + } + var t = e.editor, + n = r.createElement("img"); + (n.src = + "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="), + s.isOpera && + (n.style.cssText = + "width:1px;height:1px;position:fixed;top:0;left:0;z-index:2147483647;opacity:0;"); + var f = ["dragWait", "dragWaitEnd", "startDrag", "dragReadyEnd", "onMouseDrag"]; + f.forEach(function (t) { + e[t] = this[t]; + }, this), + t.addEventListener("mousedown", this.onMouseDown.bind(e)); + var c = t.container, + h, + p, + d, + v, + m, + g, + y = 0, + b, + w, + E, + S, + x; + (this.onDragStart = function (e) { + if (this.cancelDrag || !c.draggable) { + var r = this; + return ( + setTimeout(function () { + r.startSelect(), r.captureMouse(e); + }, 0), + e.preventDefault() + ); + } + m = t.getSelectionRange(); + var i = e.dataTransfer; + (i.effectAllowed = t.getReadOnly() ? "copy" : "copyMove"), + s.isOpera && (t.container.appendChild(n), (n.scrollTop = 0)), + i.setDragImage && i.setDragImage(n, 0, 0), + s.isOpera && t.container.removeChild(n), + i.clearData(), + i.setData("Text", t.session.getTextRange()), + (w = !0), + this.setState("drag"); + }), + (this.onDragEnd = function (e) { + (c.draggable = !1), (w = !1), this.setState(null); + if (!t.getReadOnly()) { + var n = e.dataTransfer.dropEffect; + !b && n == "move" && t.session.remove(t.getSelectionRange()), + t.renderer.$cursorLayer.setBlinking(!0); + } + this.editor.unsetStyle("ace_dragging"), + this.editor.renderer.setCursorStyle(""); + }), + (this.onDragEnter = function (e) { + if (t.getReadOnly() || !M(e.dataTransfer)) return; + return ( + (p = e.clientX), + (d = e.clientY), + h || k(), + y++, + (e.dataTransfer.dropEffect = b = _(e)), + i.preventDefault(e) + ); + }), + (this.onDragOver = function (e) { + if (t.getReadOnly() || !M(e.dataTransfer)) return; + return ( + (p = e.clientX), + (d = e.clientY), + h || (k(), y++), + A !== null && (A = null), + (e.dataTransfer.dropEffect = b = _(e)), + i.preventDefault(e) + ); + }), + (this.onDragLeave = function (e) { + y--; + if (y <= 0 && h) return L(), (b = null), i.preventDefault(e); + }), + (this.onDrop = function (e) { + if (!g) return; + var n = e.dataTransfer; + if (w) + switch (b) { + case "move": + m.contains(g.row, g.column) + ? (m = { start: g, end: g }) + : (m = t.moveText(m, g)); + break; + case "copy": + m = t.moveText(m, g, !0); + } + else { + var r = n.getData("Text"); + (m = { start: g, end: t.session.insert(g, r) }), t.focus(), (b = null); + } + return L(), i.preventDefault(e); + }), + i.addListener(c, "dragstart", this.onDragStart.bind(e)), + i.addListener(c, "dragend", this.onDragEnd.bind(e)), + i.addListener(c, "dragenter", this.onDragEnter.bind(e)), + i.addListener(c, "dragover", this.onDragOver.bind(e)), + i.addListener(c, "dragleave", this.onDragLeave.bind(e)), + i.addListener(c, "drop", this.onDrop.bind(e)); + var A = null; + } + function l(e, t, n, r) { + return Math.sqrt(Math.pow(n - e, 2) + Math.pow(r - t, 2)); + } + var r = e("../lib/dom"), + i = e("../lib/event"), + s = e("../lib/useragent"), + o = 200, + u = 200, + a = 5; + (function () { + (this.dragWait = function () { + var e = Date.now() - this.mousedownEvent.time; + e > this.editor.getDragDelay() && this.startDrag(); + }), + (this.dragWaitEnd = function () { + var e = this.editor.container; + (e.draggable = !1), + this.startSelect(this.mousedownEvent.getDocumentPosition()), + this.selectEnd(); + }), + (this.dragReadyEnd = function (e) { + this.editor.renderer.$cursorLayer.setBlinking(!this.editor.getReadOnly()), + this.editor.unsetStyle("ace_dragging"), + this.editor.renderer.setCursorStyle(""), + this.dragWaitEnd(); + }), + (this.startDrag = function () { + this.cancelDrag = !1; + var e = this.editor, + t = e.container; + (t.draggable = !0), + e.renderer.$cursorLayer.setBlinking(!1), + e.setStyle("ace_dragging"); + var n = s.isWin ? "default" : "move"; + e.renderer.setCursorStyle(n), this.setState("dragReady"); + }), + (this.onMouseDrag = function (e) { + var t = this.editor.container; + if (s.isIE && this.state == "dragReady") { + var n = l(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); + n > 3 && t.dragDrop(); + } + if (this.state === "dragWait") { + var n = l(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); + n > 0 && + ((t.draggable = !1), + this.startSelect(this.mousedownEvent.getDocumentPosition())); + } + }), + (this.onMouseDown = function (e) { + if (!this.$dragEnabled) return; + this.mousedownEvent = e; + var t = this.editor, + n = e.inSelection(), + r = e.getButton(), + i = e.domEvent.detail || 1; + if (i === 1 && r === 0 && n) { + if (e.editor.inMultiSelectMode && (e.getAccelKey() || e.getShiftKey())) + return; + this.mousedownEvent.time = Date.now(); + var o = e.domEvent.target || e.domEvent.srcElement; + "unselectable" in o && (o.unselectable = "on"); + if (t.getDragDelay()) { + if (s.isWebKit) { + this.cancelDrag = !0; + var u = t.container; + u.draggable = !0; + } + this.setState("dragWait"); + } else this.startDrag(); + this.captureMouse(e, this.onMouseDrag.bind(this)), + (e.defaultPrevented = !0); + } + }); + }).call(f.prototype), + (t.DragdropHandler = f); + }, + ), + define("ace/lib/net", ["require", "exports", "module", "ace/lib/dom"], function (e, t, n) { + "use strict"; + var r = e("./dom"); + (t.get = function (e, t) { + var n = new XMLHttpRequest(); + n.open("GET", e, !0), + (n.onreadystatechange = function () { + n.readyState === 4 && t(n.responseText); + }), + n.send(null); + }), + (t.loadScript = function (e, t) { + var n = r.getDocumentHead(), + i = document.createElement("script"); + (i.src = e), + n.appendChild(i), + (i.onload = i.onreadystatechange = + function (e, n) { + if ( + n || + !i.readyState || + i.readyState == "loaded" || + i.readyState == "complete" + ) + (i = i.onload = i.onreadystatechange = null), n || t(); + }); + }), + (t.qualifyURL = function (e) { + var t = document.createElement("a"); + return (t.href = e), t.href; + }); + }), + define("ace/lib/event_emitter", ["require", "exports", "module"], function (e, t, n) { + "use strict"; + var r = {}, + i = function () { + this.propagationStopped = !0; + }, + s = function () { + this.defaultPrevented = !0; + }; + (r._emit = r._dispatchEvent = + function (e, t) { + this._eventRegistry || (this._eventRegistry = {}), + this._defaultHandlers || (this._defaultHandlers = {}); + var n = this._eventRegistry[e] || [], + r = this._defaultHandlers[e]; + if (!n.length && !r) return; + if (typeof t != "object" || !t) t = {}; + t.type || (t.type = e), + t.stopPropagation || (t.stopPropagation = i), + t.preventDefault || (t.preventDefault = s), + (n = n.slice()); + for (var o = 0; o < n.length; o++) { + n[o](t, this); + if (t.propagationStopped) break; + } + if (r && !t.defaultPrevented) return r(t, this); + }), + (r._signal = function (e, t) { + var n = (this._eventRegistry || {})[e]; + if (!n) return; + n = n.slice(); + for (var r = 0; r < n.length; r++) n[r](t, this); + }), + (r.once = function (e, t) { + var n = this; + t && + this.addEventListener(e, function r() { + n.removeEventListener(e, r), t.apply(null, arguments); + }); + }), + (r.setDefaultHandler = function (e, t) { + var n = this._defaultHandlers; + n || (n = this._defaultHandlers = { _disabled_: {} }); + if (n[e]) { + var r = n[e], + i = n._disabled_[e]; + i || (n._disabled_[e] = i = []), i.push(r); + var s = i.indexOf(t); + s != -1 && i.splice(s, 1); + } + n[e] = t; + }), + (r.removeDefaultHandler = function (e, t) { + var n = this._defaultHandlers; + if (!n) return; + var r = n._disabled_[e]; + if (n[e] == t) r && this.setDefaultHandler(e, r.pop()); + else if (r) { + var i = r.indexOf(t); + i != -1 && r.splice(i, 1); + } + }), + (r.on = r.addEventListener = + function (e, t, n) { + this._eventRegistry = this._eventRegistry || {}; + var r = this._eventRegistry[e]; + return ( + r || (r = this._eventRegistry[e] = []), + r.indexOf(t) == -1 && r[n ? "unshift" : "push"](t), + t + ); + }), + (r.off = + r.removeListener = + r.removeEventListener = + function (e, t) { + this._eventRegistry = this._eventRegistry || {}; + var n = this._eventRegistry[e]; + if (!n) return; + var r = n.indexOf(t); + r !== -1 && n.splice(r, 1); + }), + (r.removeAllListeners = function (e) { + this._eventRegistry && (this._eventRegistry[e] = []); + }), + (t.EventEmitter = r); + }), + define( + "ace/lib/app_config", + ["require", "exports", "module", "ace/lib/oop", "ace/lib/event_emitter"], + function (e, t, n) { + "no use strict"; + function o(e) { + typeof console != "undefined" && + console.warn && + console.warn.apply(console, arguments); + } + function u(e, t) { + var n = new Error(e); + (n.data = t), + typeof console == "object" && console.error && console.error(n), + setTimeout(function () { + throw n; + }); + } + var r = e("./oop"), + i = e("./event_emitter").EventEmitter, + s = { + setOptions: function (e) { + Object.keys(e).forEach(function (t) { + this.setOption(t, e[t]); + }, this); + }, + getOptions: function (e) { + var t = {}; + if (!e) { + var n = this.$options; + e = Object.keys(n).filter(function (e) { + return !n[e].hidden; + }); + } else Array.isArray(e) || ((t = e), (e = Object.keys(t))); + return ( + e.forEach(function (e) { + t[e] = this.getOption(e); + }, this), + t + ); + }, + setOption: function (e, t) { + if (this["$" + e] === t) return; + var n = this.$options[e]; + if (!n) return o('misspelled option "' + e + '"'); + if (n.forwardTo) + return this[n.forwardTo] && this[n.forwardTo].setOption(e, t); + n.handlesSet || (this["$" + e] = t), n && n.set && n.set.call(this, t); + }, + getOption: function (e) { + var t = this.$options[e]; + return t + ? t.forwardTo + ? this[t.forwardTo] && this[t.forwardTo].getOption(e) + : t && t.get + ? t.get.call(this) + : this["$" + e] + : o('misspelled option "' + e + '"'); + }, + }, + a = function () { + this.$defaultOptions = {}; + }; + (function () { + r.implement(this, i), + (this.defineOptions = function (e, t, n) { + return ( + e.$options || (this.$defaultOptions[t] = e.$options = {}), + Object.keys(n).forEach(function (t) { + var r = n[t]; + typeof r == "string" && (r = { forwardTo: r }), + r.name || (r.name = t), + (e.$options[r.name] = r), + "initialValue" in r && (e["$" + r.name] = r.initialValue); + }), + r.implement(e, s), + this + ); + }), + (this.resetOptions = function (e) { + Object.keys(e.$options).forEach(function (t) { + var n = e.$options[t]; + "value" in n && e.setOption(t, n.value); + }); + }), + (this.setDefaultValue = function (e, t, n) { + var r = this.$defaultOptions[e] || (this.$defaultOptions[e] = {}); + r[t] && + (r.forwardTo + ? this.setDefaultValue(r.forwardTo, t, n) + : (r[t].value = n)); + }), + (this.setDefaultValues = function (e, t) { + Object.keys(t).forEach(function (n) { + this.setDefaultValue(e, n, t[n]); + }, this); + }), + (this.warn = o), + (this.reportError = u); + }).call(a.prototype), + (t.AppConfig = a); + }, + ), + define( + "ace/config", + [ + "require", + "exports", + "module", + "ace/lib/lang", + "ace/lib/oop", + "ace/lib/net", + "ace/lib/app_config", + ], + function (e, t, n) { + "no use strict"; + function l(r) { + if (!u || !u.document) return; + a.packaged = r || e.packaged || n.packaged || (u.define && define.packaged); + var i = {}, + s = "", + o = document.currentScript || document._currentScript, + f = (o && o.ownerDocument) || document, + l = f.getElementsByTagName("script"); + for (var h = 0; h < l.length; h++) { + var p = l[h], + d = p.src || p.getAttribute("src"); + if (!d) continue; + var v = p.attributes; + for (var m = 0, g = v.length; m < g; m++) { + var y = v[m]; + y.name.indexOf("data-ace-") === 0 && + (i[c(y.name.replace(/^data-ace-/, ""))] = y.value); + } + var b = d.match(/^(.*)\/ace(\-\w+)?\.js(\?|$)/); + b && (s = b[1]); + } + s && ((i.base = i.base || s), (i.packaged = !0)), + (i.basePath = i.base), + (i.workerPath = i.workerPath || i.base), + (i.modePath = i.modePath || i.base), + (i.themePath = i.themePath || i.base), + delete i.base; + for (var w in i) typeof i[w] != "undefined" && t.set(w, i[w]); + } + function c(e) { + return e.replace(/-(.)/g, function (e, t) { + return t.toUpperCase(); + }); + } + var r = e("./lib/lang"), + i = e("./lib/oop"), + s = e("./lib/net"), + o = e("./lib/app_config").AppConfig; + n.exports = t = new o(); + var u = (function () { + return this || (typeof window != "undefined" && window); + })(), + a = { + packaged: !1, + workerPath: null, + modePath: null, + themePath: null, + basePath: "", + suffix: ".js", + $moduleUrls: {}, + }; + (t.get = function (e) { + if (!a.hasOwnProperty(e)) throw new Error("Unknown config key: " + e); + return a[e]; + }), + (t.set = function (e, t) { + if (!a.hasOwnProperty(e)) throw new Error("Unknown config key: " + e); + a[e] = t; + }), + (t.all = function () { + return r.copyObject(a); + }), + (t.$modes = {}), + (t.moduleUrl = function (e, t) { + if (a.$moduleUrls[e]) return a.$moduleUrls[e]; + var n = e.split("/"); + t = t || n[n.length - 2] || ""; + var r = t == "snippets" ? "/" : "-", + i = n[n.length - 1]; + if (t == "worker" && r == "-") { + var s = new RegExp("^" + t + "[\\-_]|[\\-_]" + t + "$", "g"); + i = i.replace(s, ""); + } + (!i || i == t) && n.length > 1 && (i = n[n.length - 2]); + var o = a[t + "Path"]; + return ( + o == null ? (o = a.basePath) : r == "/" && (t = r = ""), + o && o.slice(-1) != "/" && (o += "/"), + o + t + r + i + this.get("suffix") + ); + }), + (t.setModuleUrl = function (e, t) { + return (a.$moduleUrls[e] = t); + }), + (t.$loading = {}), + (t.loadModule = function (n, r) { + var i, o; + Array.isArray(n) && ((o = n[0]), (n = n[1])); + try { + i = e(n); + } catch (u) {} + if (i && !t.$loading[n]) return r && r(i); + t.$loading[n] || (t.$loading[n] = []), t.$loading[n].push(r); + if (t.$loading[n].length > 1) return; + var a = function () { + e([n], function (e) { + t._emit("load.module", { name: n, module: e }); + var r = t.$loading[n]; + (t.$loading[n] = null), + r.forEach(function (t) { + t && t(e); + }); + }); + }; + if (!t.get("packaged")) return a(); + s.loadScript(t.moduleUrl(n, o), a), f(); + }); + var f = function () { + !a.basePath && + !a.workerPath && + !a.modePath && + !a.themePath && + !Object.keys(a.$moduleUrls).length && + (console.error( + "Unable to infer path to ace from script src,", + "use ace.config.set('basePath', 'path') to enable dynamic loading of modes and themes", + "or with webpack use ace/webpack-resolver", + ), + (f = function () {})); + }; + t.init = l; + }, + ), + define( + "ace/mouse/mouse_handler", + [ + "require", + "exports", + "module", + "ace/lib/event", + "ace/lib/useragent", + "ace/mouse/default_handlers", + "ace/mouse/default_gutter_handler", + "ace/mouse/mouse_event", + "ace/mouse/dragdrop_handler", + "ace/config", + ], + function (e, t, n) { + "use strict"; + var r = e("../lib/event"), + i = e("../lib/useragent"), + s = e("./default_handlers").DefaultHandlers, + o = e("./default_gutter_handler").GutterHandler, + u = e("./mouse_event").MouseEvent, + a = e("./dragdrop_handler").DragdropHandler, + f = e("../config"), + l = function (e) { + var t = this; + (this.editor = e), new s(this), new o(this), new a(this); + var n = function (t) { + var n = + !document.hasFocus || + !document.hasFocus() || + (!e.isFocused() && + document.activeElement == + (e.textInput && e.textInput.getElement())); + n && window.focus(), e.focus(); + }, + u = e.renderer.getMouseEventTarget(); + r.addListener(u, "click", this.onMouseEvent.bind(this, "click")), + r.addListener(u, "mousemove", this.onMouseMove.bind(this, "mousemove")), + r.addMultiMouseDownListener( + [ + u, + e.renderer.scrollBarV && e.renderer.scrollBarV.inner, + e.renderer.scrollBarH && e.renderer.scrollBarH.inner, + e.textInput && e.textInput.getElement(), + ].filter(Boolean), + [400, 300, 250], + this, + "onMouseEvent", + ), + r.addMouseWheelListener( + e.container, + this.onMouseWheel.bind(this, "mousewheel"), + ), + r.addTouchMoveListener( + e.container, + this.onTouchMove.bind(this, "touchmove"), + ); + var f = e.renderer.$gutter; + r.addListener(f, "mousedown", this.onMouseEvent.bind(this, "guttermousedown")), + r.addListener(f, "click", this.onMouseEvent.bind(this, "gutterclick")), + r.addListener( + f, + "dblclick", + this.onMouseEvent.bind(this, "gutterdblclick"), + ), + r.addListener( + f, + "mousemove", + this.onMouseEvent.bind(this, "guttermousemove"), + ), + r.addListener(u, "mousedown", n), + r.addListener(f, "mousedown", n), + i.isIE && + e.renderer.scrollBarV && + (r.addListener(e.renderer.scrollBarV.element, "mousedown", n), + r.addListener(e.renderer.scrollBarH.element, "mousedown", n)), + e.on("mousemove", function (n) { + if (t.state || t.$dragDelay || !t.$dragEnabled) return; + var r = e.renderer.screenToTextCoordinates(n.x, n.y), + i = e.session.selection.getRange(), + s = e.renderer; + !i.isEmpty() && i.insideStart(r.row, r.column) + ? s.setCursorStyle("default") + : s.setCursorStyle(""); + }); + }; + (function () { + (this.onMouseEvent = function (e, t) { + this.editor._emit(e, new u(t, this.editor)); + }), + (this.onMouseMove = function (e, t) { + var n = this.editor._eventRegistry && this.editor._eventRegistry.mousemove; + if (!n || !n.length) return; + this.editor._emit(e, new u(t, this.editor)); + }), + (this.onMouseWheel = function (e, t) { + var n = new u(t, this.editor); + (n.speed = this.$scrollSpeed * 2), + (n.wheelX = t.wheelX), + (n.wheelY = t.wheelY), + this.editor._emit(e, n); + }), + (this.onTouchMove = function (e, t) { + var n = new u(t, this.editor); + (n.speed = 1), + (n.wheelX = t.wheelX), + (n.wheelY = t.wheelY), + this.editor._emit(e, n); + }), + (this.setState = function (e) { + this.state = e; + }), + (this.captureMouse = function (e, t) { + (this.x = e.x), (this.y = e.y), (this.isMousePressed = !0); + var n = this.editor, + s = this.editor.renderer; + s.$keepTextAreaAtCursor && (s.$keepTextAreaAtCursor = null); + var o = this, + a = function (e) { + if (!e) return; + if (i.isWebKit && !e.which && o.releaseMouse) + return o.releaseMouse(); + (o.x = e.clientX), + (o.y = e.clientY), + t && t(e), + (o.mouseEvent = new u(e, o.editor)), + (o.$mouseMoved = !0); + }, + f = function (e) { + n.off("beforeEndOperation", c), + clearInterval(h), + l(), + o[o.state + "End"] && o[o.state + "End"](e), + (o.state = ""), + s.$keepTextAreaAtCursor == null && + ((s.$keepTextAreaAtCursor = !0), s.$moveTextAreaToCursor()), + (o.isMousePressed = !1), + (o.$onCaptureMouseMove = o.releaseMouse = null), + e && o.onMouseEvent("mouseup", e), + n.endOperation(); + }, + l = function () { + o[o.state] && o[o.state](), (o.$mouseMoved = !1); + }; + if (i.isOldIE && e.domEvent.type == "dblclick") + return setTimeout(function () { + f(e); + }); + var c = function (e) { + if (!o.releaseMouse) return; + n.curOp.command.name && + n.curOp.selectionChanged && + (o[o.state + "End"] && o[o.state + "End"](), + (o.state = ""), + o.releaseMouse()); + }; + n.on("beforeEndOperation", c), + n.startOperation({ command: { name: "mouse" } }), + (o.$onCaptureMouseMove = a), + (o.releaseMouse = r.capture(this.editor.container, a, f)); + var h = setInterval(l, 20); + }), + (this.releaseMouse = null), + (this.cancelContextMenu = function () { + var e = function (t) { + if (t && t.domEvent && t.domEvent.type != "contextmenu") return; + this.editor.off("nativecontextmenu", e), + t && t.domEvent && r.stopEvent(t.domEvent); + }.bind(this); + setTimeout(e, 10), this.editor.on("nativecontextmenu", e); + }); + }).call(l.prototype), + f.defineOptions(l.prototype, "mouseHandler", { + scrollSpeed: { initialValue: 2 }, + dragDelay: { initialValue: i.isMac ? 150 : 0 }, + dragEnabled: { initialValue: !0 }, + focusTimeout: { initialValue: 0 }, + tooltipFollowsMouse: { initialValue: !0 }, + }), + (t.MouseHandler = l); + }, + ), + define( + "ace/mouse/fold_handler", + ["require", "exports", "module", "ace/lib/dom"], + function (e, t, n) { + "use strict"; + function i(e) { + e.on("click", function (t) { + var n = t.getDocumentPosition(), + i = e.session, + s = i.getFoldAt(n.row, n.column, 1); + s && (t.getAccelKey() ? i.removeFold(s) : i.expandFold(s), t.stop()); + var o = t.domEvent && t.domEvent.target; + o && + r.hasCssClass(o, "ace_inline_button") && + r.hasCssClass(o, "ace_toggle_wrap") && + (i.setOption("wrap", !0), e.renderer.scrollCursorIntoView()); + }), + e.on("gutterclick", function (t) { + var n = e.renderer.$gutterLayer.getRegion(t); + if (n == "foldWidgets") { + var r = t.getDocumentPosition().row, + i = e.session; + i.foldWidgets && i.foldWidgets[r] && e.session.onFoldWidgetClick(r, t), + e.isFocused() || e.focus(), + t.stop(); + } + }), + e.on("gutterdblclick", function (t) { + var n = e.renderer.$gutterLayer.getRegion(t); + if (n == "foldWidgets") { + var r = t.getDocumentPosition().row, + i = e.session, + s = i.getParentFoldRangeData(r, !0), + o = s.range || s.firstRange; + if (o) { + r = o.start.row; + var u = i.getFoldAt(r, i.getLine(r).length, 1); + u + ? i.removeFold(u) + : (i.addFold("...", o), + e.renderer.scrollCursorIntoView({ + row: o.start.row, + column: 0, + })); + } + t.stop(); + } + }); + } + var r = e("../lib/dom"); + t.FoldHandler = i; + }, + ), + define( + "ace/keyboard/keybinding", + ["require", "exports", "module", "ace/lib/keys", "ace/lib/event"], + function (e, t, n) { + "use strict"; + var r = e("../lib/keys"), + i = e("../lib/event"), + s = function (e) { + (this.$editor = e), + (this.$data = { editor: e }), + (this.$handlers = []), + this.setDefaultHandler(e.commands); + }; + (function () { + (this.setDefaultHandler = function (e) { + this.removeKeyboardHandler(this.$defaultHandler), + (this.$defaultHandler = e), + this.addKeyboardHandler(e, 0); + }), + (this.setKeyboardHandler = function (e) { + var t = this.$handlers; + if (t[t.length - 1] == e) return; + while (t[t.length - 1] && t[t.length - 1] != this.$defaultHandler) + this.removeKeyboardHandler(t[t.length - 1]); + this.addKeyboardHandler(e, 1); + }), + (this.addKeyboardHandler = function (e, t) { + if (!e) return; + typeof e == "function" && !e.handleKeyboard && (e.handleKeyboard = e); + var n = this.$handlers.indexOf(e); + n != -1 && this.$handlers.splice(n, 1), + t == undefined + ? this.$handlers.push(e) + : this.$handlers.splice(t, 0, e), + n == -1 && e.attach && e.attach(this.$editor); + }), + (this.removeKeyboardHandler = function (e) { + var t = this.$handlers.indexOf(e); + return t == -1 + ? !1 + : (this.$handlers.splice(t, 1), e.detach && e.detach(this.$editor), !0); + }), + (this.getKeyboardHandler = function () { + return this.$handlers[this.$handlers.length - 1]; + }), + (this.getStatusText = function () { + var e = this.$data, + t = e.editor; + return this.$handlers + .map(function (n) { + return (n.getStatusText && n.getStatusText(t, e)) || ""; + }) + .filter(Boolean) + .join(" "); + }), + (this.$callKeyboardHandlers = function (e, t, n, r) { + var s, + o = !1, + u = this.$editor.commands; + for (var a = this.$handlers.length; a--; ) { + s = this.$handlers[a].handleKeyboard(this.$data, e, t, n, r); + if (!s || !s.command) continue; + s.command == "null" + ? (o = !0) + : (o = u.exec(s.command, this.$editor, s.args, r)), + o && + r && + e != -1 && + s.passEvent != 1 && + s.command.passEvent != 1 && + i.stopEvent(r); + if (o) break; + } + return ( + !o && + e == -1 && + ((s = { command: "insertstring" }), + (o = u.exec("insertstring", this.$editor, t))), + o && + this.$editor._signal && + this.$editor._signal("keyboardActivity", s), + o + ); + }), + (this.onCommandKey = function (e, t, n) { + var i = r.keyCodeToString(n); + this.$callKeyboardHandlers(t, i, n, e); + }), + (this.onTextInput = function (e) { + this.$callKeyboardHandlers(-1, e); + }); + }).call(s.prototype), + (t.KeyBinding = s); + }, + ), + define("ace/lib/bidiutil", ["require", "exports", "module"], function (e, t, n) { + "use strict"; + function F(e, t, n, r) { + var i = s ? d : p, + c = null, + h = null, + v = null, + m = 0, + g = null, + y = null, + b = -1, + w = null, + E = null, + T = []; + if (!r) for (w = 0, r = []; w < n; w++) r[w] = R(e[w]); + (o = s), (u = !1), (a = !1), (f = !1), (l = !1); + for (E = 0; E < n; E++) { + (c = m), + (T[E] = h = q(e, r, T, E)), + (m = i[c][h]), + (g = m & 240), + (m &= 15), + (t[E] = v = i[m][5]); + if (g > 0) + if (g == 16) { + for (w = b; w < E; w++) t[w] = 1; + b = -1; + } else b = -1; + y = i[m][6]; + if (y) b == -1 && (b = E); + else if (b > -1) { + for (w = b; w < E; w++) t[w] = v; + b = -1; + } + r[E] == S && (t[E] = 0), (o |= v); + } + if (l) + for (w = 0; w < n; w++) + if (r[w] == x) { + t[w] = s; + for (var C = w - 1; C >= 0; C--) { + if (r[C] != N) break; + t[C] = s; + } + } + } + function I(e, t, n) { + if (o < e) return; + if (e == 1 && s == m && !f) { + n.reverse(); + return; + } + var r = n.length, + i = 0, + u, + a, + l, + c; + while (i < r) { + if (t[i] >= e) { + u = i + 1; + while (u < r && t[u] >= e) u++; + for (a = i, l = u - 1; a < l; a++, l--) (c = n[a]), (n[a] = n[l]), (n[l] = c); + i = u; + } + i++; + } + } + function q(e, t, n, r) { + var i = t[r], + o, + c, + h, + p; + switch (i) { + case g: + case y: + u = !1; + case E: + case w: + return i; + case b: + return u ? w : b; + case T: + return (u = !0), (a = !0), y; + case N: + return E; + case C: + if ( + r < 1 || + r + 1 >= t.length || + ((o = n[r - 1]) != b && o != w) || + ((c = t[r + 1]) != b && c != w) + ) + return E; + return u && (c = w), c == o ? c : E; + case k: + o = r > 0 ? n[r - 1] : S; + if (o == b && r + 1 < t.length && t[r + 1] == b) return b; + return E; + case L: + if (r > 0 && n[r - 1] == b) return b; + if (u) return E; + (p = r + 1), (h = t.length); + while (p < h && t[p] == L) p++; + if (p < h && t[p] == b) return b; + return E; + case A: + (h = t.length), (p = r + 1); + while (p < h && t[p] == A) p++; + if (p < h) { + var d = e[r], + v = (d >= 1425 && d <= 2303) || d == 64286; + o = t[p]; + if (v && (o == y || o == T)) return y; + } + if (r < 1 || (o = t[r - 1]) == S) return E; + return n[r - 1]; + case S: + return (u = !1), (f = !0), s; + case x: + return (l = !0), E; + case O: + case M: + case D: + case P: + case _: + u = !1; + case H: + return E; + } + } + function R(e) { + var t = e.charCodeAt(0), + n = t >> 8; + return n == 0 + ? t > 191 + ? g + : B[t] + : n == 5 + ? /[\u0591-\u05f4]/.test(e) + ? y + : g + : n == 6 + ? /[\u0610-\u061a\u064b-\u065f\u06d6-\u06e4\u06e7-\u06ed]/.test(e) + ? A + : /[\u0660-\u0669\u066b-\u066c]/.test(e) + ? w + : t == 1642 + ? L + : /[\u06f0-\u06f9]/.test(e) + ? b + : T + : n == 32 && t <= 8287 + ? j[t & 255] + : n == 254 + ? t >= 65136 + ? T + : E + : E; + } + function U(e) { + return e >= "\u064b" && e <= "\u0655"; + } + var r = ["\u0621", "\u0641"], + i = ["\u063a", "\u064a"], + s = 0, + o = 0, + u = !1, + a = !1, + f = !1, + l = !1, + c = !1, + h = !1, + p = [ + [0, 3, 0, 1, 0, 0, 0], + [0, 3, 0, 1, 2, 2, 0], + [0, 3, 0, 17, 2, 0, 1], + [0, 3, 5, 5, 4, 1, 0], + [0, 3, 21, 21, 4, 0, 1], + [0, 3, 5, 5, 4, 2, 0], + ], + d = [ + [2, 0, 1, 1, 0, 1, 0], + [2, 0, 1, 1, 0, 2, 0], + [2, 0, 2, 1, 3, 2, 0], + [2, 0, 2, 33, 3, 1, 1], + ], + v = 0, + m = 1, + g = 0, + y = 1, + b = 2, + w = 3, + E = 4, + S = 5, + x = 6, + T = 7, + N = 8, + C = 9, + k = 10, + L = 11, + A = 12, + O = 13, + M = 14, + _ = 15, + D = 16, + P = 17, + H = 18, + B = [ + H, + H, + H, + H, + H, + H, + H, + H, + H, + x, + S, + x, + N, + S, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + S, + S, + S, + x, + N, + E, + E, + L, + L, + L, + E, + E, + E, + E, + E, + k, + C, + k, + C, + C, + b, + b, + b, + b, + b, + b, + b, + b, + b, + b, + C, + E, + E, + E, + E, + E, + E, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + E, + E, + E, + E, + E, + E, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + g, + E, + E, + E, + E, + H, + H, + H, + H, + H, + H, + S, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + H, + C, + E, + L, + L, + L, + L, + E, + E, + E, + E, + g, + E, + E, + H, + E, + E, + L, + L, + b, + b, + E, + g, + E, + E, + E, + b, + g, + E, + E, + E, + E, + E, + ], + j = [ + N, + N, + N, + N, + N, + N, + N, + N, + N, + N, + N, + H, + H, + H, + g, + y, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + N, + S, + O, + M, + _, + D, + P, + C, + L, + L, + L, + L, + L, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + C, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + E, + N, + ]; + (t.L = g), + (t.R = y), + (t.EN = b), + (t.ON_R = 3), + (t.AN = 4), + (t.R_H = 5), + (t.B = 6), + (t.RLE = 7), + (t.DOT = "\u00b7"), + (t.doBidiReorder = function (e, n, r) { + if (e.length < 2) return {}; + var i = e.split(""), + o = new Array(i.length), + u = new Array(i.length), + a = []; + (s = r ? m : v), F(i, a, i.length, n); + for (var f = 0; f < o.length; o[f] = f, f++); + I(2, a, o), I(1, a, o); + for (var f = 0; f < o.length - 1; f++) + n[f] === w + ? (a[f] = t.AN) + : a[f] === y && ((n[f] > T && n[f] < O) || n[f] === E || n[f] === H) + ? (a[f] = t.ON_R) + : f > 0 && + i[f - 1] === "\u0644" && + /\u0622|\u0623|\u0625|\u0627/.test(i[f]) && + ((a[f - 1] = a[f] = t.R_H), f++); + i[i.length - 1] === t.DOT && (a[i.length - 1] = t.B), + i[0] === "\u202b" && (a[0] = t.RLE); + for (var f = 0; f < o.length; f++) u[f] = a[o[f]]; + return { logicalFromVisual: o, bidiLevels: u }; + }), + (t.hasBidiCharacters = function (e, t) { + var n = !1; + for (var r = 0; r < e.length; r++) + (t[r] = R(e.charAt(r))), + !n && (t[r] == y || t[r] == T || t[r] == w) && (n = !0); + return n; + }), + (t.getVisualFromLogicalIdx = function (e, t) { + for (var n = 0; n < t.logicalFromVisual.length; n++) + if (t.logicalFromVisual[n] == e) return n; + return 0; + }); + }), + define( + "ace/bidihandler", + ["require", "exports", "module", "ace/lib/bidiutil", "ace/lib/lang"], + function (e, t, n) { + "use strict"; + var r = e("./lib/bidiutil"), + i = e("./lib/lang"), + s = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac\u202B]/, + o = function (e) { + (this.session = e), + (this.bidiMap = {}), + (this.currentRow = null), + (this.bidiUtil = r), + (this.charWidths = []), + (this.EOL = "\u00ac"), + (this.showInvisibles = !0), + (this.isRtlDir = !1), + (this.line = ""), + (this.wrapIndent = 0), + (this.EOF = "\u00b6"), + (this.RLE = "\u202b"), + (this.contentWidth = 0), + (this.fontMetrics = null), + (this.rtlLineOffset = 0), + (this.wrapOffset = 0), + (this.isMoveLeftOperation = !1), + (this.seenBidi = s.test(e.getValue())); + }; + (function () { + (this.isBidiRow = function (e, t, n) { + return this.seenBidi + ? (e !== this.currentRow && + ((this.currentRow = e), + this.updateRowLine(t, n), + this.updateBidiMap()), + this.bidiMap.bidiLevels) + : !1; + }), + (this.onChange = function (e) { + this.seenBidi + ? (this.currentRow = null) + : e.action == "insert" && + s.test(e.lines.join("\n")) && + ((this.seenBidi = !0), (this.currentRow = null)); + }), + (this.getDocumentRow = function () { + var e = 0, + t = this.session.$screenRowCache; + if (t.length) { + var n = this.session.$getRowCacheIndex(t, this.currentRow); + n >= 0 && (e = this.session.$docRowCache[n]); + } + return e; + }), + (this.getSplitIndex = function () { + var e = 0, + t = this.session.$screenRowCache; + if (t.length) { + var n, + r = this.session.$getRowCacheIndex(t, this.currentRow); + while (this.currentRow - e > 0) { + n = this.session.$getRowCacheIndex(t, this.currentRow - e - 1); + if (n !== r) break; + (r = n), e++; + } + } else e = this.currentRow; + return e; + }), + (this.updateRowLine = function (e, t) { + e === undefined && (e = this.getDocumentRow()); + var n = e === this.session.getLength() - 1, + s = n ? this.EOF : this.EOL; + (this.wrapIndent = 0), + (this.line = this.session.getLine(e)), + (this.isRtlDir = this.line.charAt(0) === this.RLE); + if (this.session.$useWrapMode) { + var o = this.session.$wrapData[e]; + o && + (t === undefined && (t = this.getSplitIndex()), + t > 0 && o.length + ? ((this.wrapIndent = o.indent), + (this.wrapOffset = this.wrapIndent * this.charWidths[r.L]), + (this.line = + t < o.length + ? this.line.substring(o[t - 1], o[t]) + : this.line.substring(o[o.length - 1]))) + : (this.line = this.line.substring(0, o[t]))), + t == o.length && (this.line += this.showInvisibles ? s : r.DOT); + } else this.line += this.showInvisibles ? s : r.DOT; + var u = this.session, + a = 0, + f; + (this.line = this.line.replace( + /\t|[\u1100-\u2029, \u202F-\uFFE6]/g, + function (e, t) { + return e === " " || u.isFullWidth(e.charCodeAt(0)) + ? ((f = e === " " ? u.getScreenTabSize(t + a) : 2), + (a += f - 1), + i.stringRepeat(r.DOT, f)) + : e; + }, + )), + this.isRtlDir && + ((this.fontMetrics.$main.innerHTML = + this.line.charAt(this.line.length - 1) == r.DOT + ? this.line.substr(0, this.line.length - 1) + : this.line), + (this.rtlLineOffset = + this.contentWidth - + this.fontMetrics.$main.getBoundingClientRect().width)); + }), + (this.updateBidiMap = function () { + var e = []; + r.hasBidiCharacters(this.line, e) || this.isRtlDir + ? (this.bidiMap = r.doBidiReorder(this.line, e, this.isRtlDir)) + : (this.bidiMap = {}); + }), + (this.markAsDirty = function () { + this.currentRow = null; + }), + (this.updateCharacterWidths = function (e) { + if (this.characterWidth === e.$characterSize.width) return; + this.fontMetrics = e; + var t = (this.characterWidth = e.$characterSize.width), + n = e.$measureCharWidth("\u05d4"); + (this.charWidths[r.L] = + this.charWidths[r.EN] = + this.charWidths[r.ON_R] = + t), + (this.charWidths[r.R] = this.charWidths[r.AN] = n), + (this.charWidths[r.R_H] = n * 0.45), + (this.charWidths[r.B] = this.charWidths[r.RLE] = 0), + (this.currentRow = null); + }), + (this.setShowInvisibles = function (e) { + (this.showInvisibles = e), (this.currentRow = null); + }), + (this.setEolChar = function (e) { + this.EOL = e; + }), + (this.setContentWidth = function (e) { + this.contentWidth = e; + }), + (this.isRtlLine = function (e) { + return e != undefined + ? this.session.getLine(e).charAt(0) == this.RLE + : this.isRtlDir; + }), + (this.setRtlDirection = function (e, t) { + var n = e.getCursorPosition(); + for (var r = e.selection.getSelectionAnchor().row; r <= n.row; r++) + !t && e.session.getLine(r).charAt(0) === e.session.$bidiHandler.RLE + ? e.session.doc.removeInLine(r, 0, 1) + : t && + e.session.getLine(r).charAt(0) !== e.session.$bidiHandler.RLE && + e.session.doc.insert( + { column: 0, row: r }, + e.session.$bidiHandler.RLE, + ); + }), + (this.getPosLeft = function (e) { + e -= this.wrapIndent; + var t = this.line.charAt(0) === this.RLE ? 1 : 0, + n = e > t ? (this.session.getOverwrite() ? e : e - 1) : t, + i = r.getVisualFromLogicalIdx(n, this.bidiMap), + s = this.bidiMap.bidiLevels, + o = 0; + !this.session.getOverwrite() && e <= t && s[i] % 2 !== 0 && i++; + for (var u = 0; u < i; u++) o += this.charWidths[s[u]]; + return ( + !this.session.getOverwrite() && + e > t && + s[i] % 2 === 0 && + (o += this.charWidths[s[i]]), + this.wrapIndent && + (o += this.isRtlDir ? -1 * this.wrapOffset : this.wrapOffset), + this.isRtlDir && (o += this.rtlLineOffset), + o + ); + }), + (this.getSelections = function (e, t) { + var n = this.bidiMap, + r = n.bidiLevels, + i, + s = [], + o = 0, + u = Math.min(e, t) - this.wrapIndent, + a = Math.max(e, t) - this.wrapIndent, + f = !1, + l = !1, + c = 0; + this.wrapIndent && + (o += this.isRtlDir ? -1 * this.wrapOffset : this.wrapOffset); + for (var h, p = 0; p < r.length; p++) + (h = n.logicalFromVisual[p]), + (i = r[p]), + (f = h >= u && h < a), + f && !l ? (c = o) : !f && l && s.push({ left: c, width: o - c }), + (o += this.charWidths[i]), + (l = f); + f && p === r.length && s.push({ left: c, width: o - c }); + if (this.isRtlDir) + for (var d = 0; d < s.length; d++) s[d].left += this.rtlLineOffset; + return s; + }), + (this.offsetToCol = function (e) { + this.isRtlDir && (e -= this.rtlLineOffset); + var t = 0, + e = Math.max(e, 0), + n = 0, + r = 0, + i = this.bidiMap.bidiLevels, + s = this.charWidths[i[r]]; + this.wrapIndent && + (e -= this.isRtlDir ? -1 * this.wrapOffset : this.wrapOffset); + while (e > n + s / 2) { + n += s; + if (r === i.length - 1) { + s = 0; + break; + } + s = this.charWidths[i[++r]]; + } + return ( + r > 0 && i[r - 1] % 2 !== 0 && i[r] % 2 === 0 + ? (e < n && r--, (t = this.bidiMap.logicalFromVisual[r])) + : r > 0 && i[r - 1] % 2 === 0 && i[r] % 2 !== 0 + ? (t = + 1 + + (e > n + ? this.bidiMap.logicalFromVisual[r] + : this.bidiMap.logicalFromVisual[r - 1])) + : (this.isRtlDir && + r === i.length - 1 && + s === 0 && + i[r - 1] % 2 === 0) || + (!this.isRtlDir && r === 0 && i[r] % 2 !== 0) + ? (t = 1 + this.bidiMap.logicalFromVisual[r]) + : (r > 0 && i[r - 1] % 2 !== 0 && s !== 0 && r--, + (t = this.bidiMap.logicalFromVisual[r])), + t === 0 && this.isRtlDir && t++, + t + this.wrapIndent + ); + }); + }).call(o.prototype), + (t.BidiHandler = o); + }, + ), + define( + "ace/selection", + [ + "require", + "exports", + "module", + "ace/lib/oop", + "ace/lib/lang", + "ace/lib/event_emitter", + "ace/range", + ], + function (e, t, n) { + "use strict"; + var r = e("./lib/oop"), + i = e("./lib/lang"), + s = e("./lib/event_emitter").EventEmitter, + o = e("./range").Range, + u = function (e) { + (this.session = e), + (this.doc = e.getDocument()), + this.clearSelection(), + (this.cursor = this.lead = this.doc.createAnchor(0, 0)), + (this.anchor = this.doc.createAnchor(0, 0)), + (this.$silent = !1); + var t = this; + this.cursor.on("change", function (e) { + (t.$cursorChanged = !0), + t.$silent || t._emit("changeCursor"), + !t.$isEmpty && !t.$silent && t._emit("changeSelection"), + !t.$keepDesiredColumnOnChange && + e.old.column != e.value.column && + (t.$desiredColumn = null); + }), + this.anchor.on("change", function () { + (t.$anchorChanged = !0), + !t.$isEmpty && !t.$silent && t._emit("changeSelection"); + }); + }; + (function () { + r.implement(this, s), + (this.isEmpty = function () { + return ( + this.$isEmpty || + (this.anchor.row == this.lead.row && + this.anchor.column == this.lead.column) + ); + }), + (this.isMultiLine = function () { + return !this.$isEmpty && this.anchor.row != this.cursor.row; + }), + (this.getCursor = function () { + return this.lead.getPosition(); + }), + (this.setSelectionAnchor = function (e, t) { + (this.$isEmpty = !1), this.anchor.setPosition(e, t); + }), + (this.getAnchor = this.getSelectionAnchor = + function () { + return this.$isEmpty + ? this.getSelectionLead() + : this.anchor.getPosition(); + }), + (this.getSelectionLead = function () { + return this.lead.getPosition(); + }), + (this.isBackwards = function () { + var e = this.anchor, + t = this.lead; + return e.row > t.row || (e.row == t.row && e.column > t.column); + }), + (this.getRange = function () { + var e = this.anchor, + t = this.lead; + return this.$isEmpty + ? o.fromPoints(t, t) + : this.isBackwards() + ? o.fromPoints(t, e) + : o.fromPoints(e, t); + }), + (this.clearSelection = function () { + this.$isEmpty || ((this.$isEmpty = !0), this._emit("changeSelection")); + }), + (this.selectAll = function () { + this.$setSelection(0, 0, Number.MAX_VALUE, Number.MAX_VALUE); + }), + (this.setRange = this.setSelectionRange = + function (e, t) { + var n = t ? e.end : e.start, + r = t ? e.start : e.end; + this.$setSelection(n.row, n.column, r.row, r.column); + }), + (this.$setSelection = function (e, t, n, r) { + var i = this.$isEmpty, + s = this.inMultiSelectMode; + (this.$silent = !0), + (this.$cursorChanged = this.$anchorChanged = !1), + this.anchor.setPosition(e, t), + this.cursor.setPosition(n, r), + (this.$isEmpty = !o.comparePoints(this.anchor, this.cursor)), + (this.$silent = !1), + this.$cursorChanged && this._emit("changeCursor"), + (this.$cursorChanged || + this.$anchorChanged || + i != this.$isEmpty || + s) && + this._emit("changeSelection"); + }), + (this.$moveSelection = function (e) { + var t = this.lead; + this.$isEmpty && this.setSelectionAnchor(t.row, t.column), e.call(this); + }), + (this.selectTo = function (e, t) { + this.$moveSelection(function () { + this.moveCursorTo(e, t); + }); + }), + (this.selectToPosition = function (e) { + this.$moveSelection(function () { + this.moveCursorToPosition(e); + }); + }), + (this.moveTo = function (e, t) { + this.clearSelection(), this.moveCursorTo(e, t); + }), + (this.moveToPosition = function (e) { + this.clearSelection(), this.moveCursorToPosition(e); + }), + (this.selectUp = function () { + this.$moveSelection(this.moveCursorUp); + }), + (this.selectDown = function () { + this.$moveSelection(this.moveCursorDown); + }), + (this.selectRight = function () { + this.$moveSelection(this.moveCursorRight); + }), + (this.selectLeft = function () { + this.$moveSelection(this.moveCursorLeft); + }), + (this.selectLineStart = function () { + this.$moveSelection(this.moveCursorLineStart); + }), + (this.selectLineEnd = function () { + this.$moveSelection(this.moveCursorLineEnd); + }), + (this.selectFileEnd = function () { + this.$moveSelection(this.moveCursorFileEnd); + }), + (this.selectFileStart = function () { + this.$moveSelection(this.moveCursorFileStart); + }), + (this.selectWordRight = function () { + this.$moveSelection(this.moveCursorWordRight); + }), + (this.selectWordLeft = function () { + this.$moveSelection(this.moveCursorWordLeft); + }), + (this.getWordRange = function (e, t) { + if (typeof t == "undefined") { + var n = e || this.lead; + (e = n.row), (t = n.column); + } + return this.session.getWordRange(e, t); + }), + (this.selectWord = function () { + this.setSelectionRange(this.getWordRange()); + }), + (this.selectAWord = function () { + var e = this.getCursor(), + t = this.session.getAWordRange(e.row, e.column); + this.setSelectionRange(t); + }), + (this.getLineRange = function (e, t) { + var n = typeof e == "number" ? e : this.lead.row, + r, + i = this.session.getFoldLine(n); + return ( + i ? ((n = i.start.row), (r = i.end.row)) : (r = n), + t === !0 + ? new o(n, 0, r, this.session.getLine(r).length) + : new o(n, 0, r + 1, 0) + ); + }), + (this.selectLine = function () { + this.setSelectionRange(this.getLineRange()); + }), + (this.moveCursorUp = function () { + this.moveCursorBy(-1, 0); + }), + (this.moveCursorDown = function () { + this.moveCursorBy(1, 0); + }), + (this.wouldMoveIntoSoftTab = function (e, t, n) { + var r = e.column, + i = e.column + t; + return ( + n < 0 && ((r = e.column - t), (i = e.column)), + this.session.isTabStop(e) && + this.doc.getLine(e.row).slice(r, i).split(" ").length - 1 == t + ); + }), + (this.moveCursorLeft = function () { + var e = this.lead.getPosition(), + t; + if ((t = this.session.getFoldAt(e.row, e.column, -1))) + this.moveCursorTo(t.start.row, t.start.column); + else if (e.column === 0) + e.row > 0 && + this.moveCursorTo(e.row - 1, this.doc.getLine(e.row - 1).length); + else { + var n = this.session.getTabSize(); + this.wouldMoveIntoSoftTab(e, n, -1) && + !this.session.getNavigateWithinSoftTabs() + ? this.moveCursorBy(0, -n) + : this.moveCursorBy(0, -1); + } + }), + (this.moveCursorRight = function () { + var e = this.lead.getPosition(), + t; + if ((t = this.session.getFoldAt(e.row, e.column, 1))) + this.moveCursorTo(t.end.row, t.end.column); + else if (this.lead.column == this.doc.getLine(this.lead.row).length) + this.lead.row < this.doc.getLength() - 1 && + this.moveCursorTo(this.lead.row + 1, 0); + else { + var n = this.session.getTabSize(), + e = this.lead; + this.wouldMoveIntoSoftTab(e, n, 1) && + !this.session.getNavigateWithinSoftTabs() + ? this.moveCursorBy(0, n) + : this.moveCursorBy(0, 1); + } + }), + (this.moveCursorLineStart = function () { + var e = this.lead.row, + t = this.lead.column, + n = this.session.documentToScreenRow(e, t), + r = this.session.screenToDocumentPosition(n, 0), + i = this.session.getDisplayLine(e, null, r.row, r.column), + s = i.match(/^\s*/); + s[0].length != t && + !this.session.$useEmacsStyleLineStart && + (r.column += s[0].length), + this.moveCursorToPosition(r); + }), + (this.moveCursorLineEnd = function () { + var e = this.lead, + t = this.session.getDocumentLastRowColumnPosition(e.row, e.column); + if (this.lead.column == t.column) { + var n = this.session.getLine(t.row); + if (t.column == n.length) { + var r = n.search(/\s+$/); + r > 0 && (t.column = r); + } + } + this.moveCursorTo(t.row, t.column); + }), + (this.moveCursorFileEnd = function () { + var e = this.doc.getLength() - 1, + t = this.doc.getLine(e).length; + this.moveCursorTo(e, t); + }), + (this.moveCursorFileStart = function () { + this.moveCursorTo(0, 0); + }), + (this.moveCursorLongWordRight = function () { + var e = this.lead.row, + t = this.lead.column, + n = this.doc.getLine(e), + r = n.substring(t); + (this.session.nonTokenRe.lastIndex = 0), + (this.session.tokenRe.lastIndex = 0); + var i = this.session.getFoldAt(e, t, 1); + if (i) { + this.moveCursorTo(i.end.row, i.end.column); + return; + } + this.session.nonTokenRe.exec(r) && + ((t += this.session.nonTokenRe.lastIndex), + (this.session.nonTokenRe.lastIndex = 0), + (r = n.substring(t))); + if (t >= n.length) { + this.moveCursorTo(e, n.length), + this.moveCursorRight(), + e < this.doc.getLength() - 1 && this.moveCursorWordRight(); + return; + } + this.session.tokenRe.exec(r) && + ((t += this.session.tokenRe.lastIndex), + (this.session.tokenRe.lastIndex = 0)), + this.moveCursorTo(e, t); + }), + (this.moveCursorLongWordLeft = function () { + var e = this.lead.row, + t = this.lead.column, + n; + if ((n = this.session.getFoldAt(e, t, -1))) { + this.moveCursorTo(n.start.row, n.start.column); + return; + } + var r = this.session.getFoldStringAt(e, t, -1); + r == null && (r = this.doc.getLine(e).substring(0, t)); + var s = i.stringReverse(r); + (this.session.nonTokenRe.lastIndex = 0), + (this.session.tokenRe.lastIndex = 0), + this.session.nonTokenRe.exec(s) && + ((t -= this.session.nonTokenRe.lastIndex), + (s = s.slice(this.session.nonTokenRe.lastIndex)), + (this.session.nonTokenRe.lastIndex = 0)); + if (t <= 0) { + this.moveCursorTo(e, 0), + this.moveCursorLeft(), + e > 0 && this.moveCursorWordLeft(); + return; + } + this.session.tokenRe.exec(s) && + ((t -= this.session.tokenRe.lastIndex), + (this.session.tokenRe.lastIndex = 0)), + this.moveCursorTo(e, t); + }), + (this.$shortWordEndIndex = function (e) { + var t = 0, + n, + r = /\s/, + i = this.session.tokenRe; + i.lastIndex = 0; + if (this.session.tokenRe.exec(e)) t = this.session.tokenRe.lastIndex; + else { + while ((n = e[t]) && r.test(n)) t++; + if (t < 1) { + i.lastIndex = 0; + while ((n = e[t]) && !i.test(n)) { + (i.lastIndex = 0), t++; + if (r.test(n)) { + if (t > 2) { + t--; + break; + } + while ((n = e[t]) && r.test(n)) t++; + if (t > 2) break; + } + } + } + } + return (i.lastIndex = 0), t; + }), + (this.moveCursorShortWordRight = function () { + var e = this.lead.row, + t = this.lead.column, + n = this.doc.getLine(e), + r = n.substring(t), + i = this.session.getFoldAt(e, t, 1); + if (i) return this.moveCursorTo(i.end.row, i.end.column); + if (t == n.length) { + var s = this.doc.getLength(); + do e++, (r = this.doc.getLine(e)); + while (e < s && /^\s*$/.test(r)); + /^\s+/.test(r) || (r = ""), (t = 0); + } + var o = this.$shortWordEndIndex(r); + this.moveCursorTo(e, t + o); + }), + (this.moveCursorShortWordLeft = function () { + var e = this.lead.row, + t = this.lead.column, + n; + if ((n = this.session.getFoldAt(e, t, -1))) + return this.moveCursorTo(n.start.row, n.start.column); + var r = this.session.getLine(e).substring(0, t); + if (t === 0) { + do e--, (r = this.doc.getLine(e)); + while (e > 0 && /^\s*$/.test(r)); + (t = r.length), /\s+$/.test(r) || (r = ""); + } + var s = i.stringReverse(r), + o = this.$shortWordEndIndex(s); + return this.moveCursorTo(e, t - o); + }), + (this.moveCursorWordRight = function () { + this.session.$selectLongWords + ? this.moveCursorLongWordRight() + : this.moveCursorShortWordRight(); + }), + (this.moveCursorWordLeft = function () { + this.session.$selectLongWords + ? this.moveCursorLongWordLeft() + : this.moveCursorShortWordLeft(); + }), + (this.moveCursorBy = function (e, t) { + var n = this.session.documentToScreenPosition( + this.lead.row, + this.lead.column, + ), + r; + t === 0 && + (e !== 0 && + (this.session.$bidiHandler.isBidiRow(n.row, this.lead.row) + ? ((r = this.session.$bidiHandler.getPosLeft(n.column)), + (n.column = Math.round( + r / this.session.$bidiHandler.charWidths[0], + ))) + : (r = n.column * this.session.$bidiHandler.charWidths[0])), + this.$desiredColumn + ? (n.column = this.$desiredColumn) + : (this.$desiredColumn = n.column)); + var i = this.session.screenToDocumentPosition(n.row + e, n.column, r); + e !== 0 && + t === 0 && + i.row === this.lead.row && + i.column === this.lead.column && + this.session.lineWidgets && + this.session.lineWidgets[i.row] && + (i.row > 0 || e > 0) && + i.row++, + this.moveCursorTo(i.row, i.column + t, t === 0); + }), + (this.moveCursorToPosition = function (e) { + this.moveCursorTo(e.row, e.column); + }), + (this.moveCursorTo = function (e, t, n) { + var r = this.session.getFoldAt(e, t, 1); + r && ((e = r.start.row), (t = r.start.column)), + (this.$keepDesiredColumnOnChange = !0); + var i = this.session.getLine(e); + /[\uDC00-\uDFFF]/.test(i.charAt(t)) && + i.charAt(t - 1) && + (this.lead.row == e && this.lead.column == t + 1 ? (t -= 1) : (t += 1)), + this.lead.setPosition(e, t), + (this.$keepDesiredColumnOnChange = !1), + n || (this.$desiredColumn = null); + }), + (this.moveCursorToScreen = function (e, t, n) { + var r = this.session.screenToDocumentPosition(e, t); + this.moveCursorTo(r.row, r.column, n); + }), + (this.detach = function () { + this.lead.detach(), this.anchor.detach(), (this.session = this.doc = null); + }), + (this.fromOrientedRange = function (e) { + this.setSelectionRange(e, e.cursor == e.start), + (this.$desiredColumn = e.desiredColumn || this.$desiredColumn); + }), + (this.toOrientedRange = function (e) { + var t = this.getRange(); + return ( + e + ? ((e.start.column = t.start.column), + (e.start.row = t.start.row), + (e.end.column = t.end.column), + (e.end.row = t.end.row)) + : (e = t), + (e.cursor = this.isBackwards() ? e.start : e.end), + (e.desiredColumn = this.$desiredColumn), + e + ); + }), + (this.getRangeOfMovements = function (e) { + var t = this.getCursor(); + try { + e(this); + var n = this.getCursor(); + return o.fromPoints(t, n); + } catch (r) { + return o.fromPoints(t, t); + } finally { + this.moveCursorToPosition(t); + } + }), + (this.toJSON = function () { + if (this.rangeCount) + var e = this.ranges.map(function (e) { + var t = e.clone(); + return (t.isBackwards = e.cursor == e.start), t; + }); + else { + var e = this.getRange(); + e.isBackwards = this.isBackwards(); + } + return e; + }), + (this.fromJSON = function (e) { + if (e.start == undefined) { + if (this.rangeList) { + this.toSingleRange(e[0]); + for (var t = e.length; t--; ) { + var n = o.fromPoints(e[t].start, e[t].end); + e[t].isBackwards && (n.cursor = n.start), this.addRange(n, !0); + } + return; + } + e = e[0]; + } + this.rangeList && this.toSingleRange(e), + this.setSelectionRange(e, e.isBackwards); + }), + (this.isEqual = function (e) { + if ((e.length || this.rangeCount) && e.length != this.rangeCount) return !1; + if (!e.length || !this.ranges) return this.getRange().isEqual(e); + for (var t = this.ranges.length; t--; ) + if (!this.ranges[t].isEqual(e[t])) return !1; + return !0; + }); + }).call(u.prototype), + (t.Selection = u); + }, + ), + define("ace/tokenizer", ["require", "exports", "module", "ace/config"], function (e, t, n) { + "use strict"; + var r = e("./config"), + i = 2e3, + s = function (e) { + (this.states = e), (this.regExps = {}), (this.matchMappings = {}); + for (var t in this.states) { + var n = this.states[t], + r = [], + i = 0, + s = (this.matchMappings[t] = { defaultToken: "text" }), + o = "g", + u = []; + for (var a = 0; a < n.length; a++) { + var f = n[a]; + f.defaultToken && (s.defaultToken = f.defaultToken), + f.caseInsensitive && (o = "gi"); + if (f.regex == null) continue; + f.regex instanceof RegExp && (f.regex = f.regex.toString().slice(1, -1)); + var l = f.regex, + c = new RegExp("(?:(" + l + ")|(.))").exec("a").length - 2; + Array.isArray(f.token) + ? f.token.length == 1 || c == 1 + ? (f.token = f.token[0]) + : c - 1 != f.token.length + ? (this.reportError( + "number of classes and regexp groups doesn't match", + { rule: f, groupCount: c - 1 }, + ), + (f.token = f.token[0])) + : ((f.tokenArray = f.token), + (f.token = null), + (f.onMatch = this.$arrayTokens)) + : typeof f.token == "function" && + !f.onMatch && + (c > 1 ? (f.onMatch = this.$applyToken) : (f.onMatch = f.token)), + c > 1 && + (/\\\d/.test(f.regex) + ? (l = f.regex.replace(/\\([0-9]+)/g, function (e, t) { + return "\\" + (parseInt(t, 10) + i + 1); + })) + : ((c = 1), (l = this.removeCapturingGroups(f.regex))), + !f.splitRegex && typeof f.token != "string" && u.push(f)), + (s[i] = a), + (i += c), + r.push(l), + f.onMatch || (f.onMatch = null); + } + r.length || ((s[0] = 0), r.push("$")), + u.forEach(function (e) { + e.splitRegex = this.createSplitterRegexp(e.regex, o); + }, this), + (this.regExps[t] = new RegExp("(" + r.join(")|(") + ")|($)", o)); + } + }; + (function () { + (this.$setMaxTokenCount = function (e) { + i = e | 0; + }), + (this.$applyToken = function (e) { + var t = this.splitRegex.exec(e).slice(1), + n = this.token.apply(this, t); + if (typeof n == "string") return [{ type: n, value: e }]; + var r = []; + for (var i = 0, s = n.length; i < s; i++) + t[i] && (r[r.length] = { type: n[i], value: t[i] }); + return r; + }), + (this.$arrayTokens = function (e) { + if (!e) return []; + var t = this.splitRegex.exec(e); + if (!t) return "text"; + var n = [], + r = this.tokenArray; + for (var i = 0, s = r.length; i < s; i++) + t[i + 1] && (n[n.length] = { type: r[i], value: t[i + 1] }); + return n; + }), + (this.removeCapturingGroups = function (e) { + var t = e.replace(/\\.|\[(?:\\.|[^\\\]])*|\(\?[:=!]|(\()/g, function (e, t) { + return t ? "(?:" : e; + }); + return t; + }), + (this.createSplitterRegexp = function (e, t) { + if (e.indexOf("(?=") != -1) { + var n = 0, + r = !1, + i = {}; + e.replace( + /(\\.)|(\((?:\?[=!])?)|(\))|([\[\]])/g, + function (e, t, s, o, u, a) { + return ( + r + ? (r = u != "]") + : u + ? (r = !0) + : o + ? (n == i.stack && ((i.end = a + 1), (i.stack = -1)), + n--) + : s && + (n++, + s.length != 1 && ((i.stack = n), (i.start = a))), + e + ); + }, + ), + i.end != null && + /^\)*$/.test(e.substr(i.end)) && + (e = e.substring(0, i.start) + e.substr(i.end)); + } + return ( + e.charAt(0) != "^" && (e = "^" + e), + e.charAt(e.length - 1) != "$" && (e += "$"), + new RegExp(e, (t || "").replace("g", "")) + ); + }), + (this.getLineTokens = function (e, t) { + if (t && typeof t != "string") { + var n = t.slice(0); + (t = n[0]), t === "#tmp" && (n.shift(), (t = n.shift())); + } else var n = []; + var r = t || "start", + s = this.states[r]; + s || ((r = "start"), (s = this.states[r])); + var o = this.matchMappings[r], + u = this.regExps[r]; + u.lastIndex = 0; + var a, + f = [], + l = 0, + c = 0, + h = { type: null, value: "" }; + while ((a = u.exec(e))) { + var p = o.defaultToken, + d = null, + v = a[0], + m = u.lastIndex; + if (m - v.length > l) { + var g = e.substring(l, m - v.length); + h.type == p + ? (h.value += g) + : (h.type && f.push(h), (h = { type: p, value: g })); + } + for (var y = 0; y < a.length - 2; y++) { + if (a[y + 1] === undefined) continue; + (d = s[o[y]]), + d.onMatch ? (p = d.onMatch(v, r, n, e)) : (p = d.token), + d.next && + (typeof d.next == "string" ? (r = d.next) : (r = d.next(r, n)), + (s = this.states[r]), + s || + (this.reportError("state doesn't exist", r), + (r = "start"), + (s = this.states[r])), + (o = this.matchMappings[r]), + (l = m), + (u = this.regExps[r]), + (u.lastIndex = m)), + d.consumeLineEnd && (l = m); + break; + } + if (v) + if (typeof p == "string") + (!!d && d.merge === !1) || h.type !== p + ? (h.type && f.push(h), (h = { type: p, value: v })) + : (h.value += v); + else if (p) { + h.type && f.push(h), (h = { type: null, value: "" }); + for (var y = 0; y < p.length; y++) f.push(p[y]); + } + if (l == e.length) break; + l = m; + if (c++ > i) { + c > 2 * e.length && + this.reportError("infinite loop with in ace tokenizer", { + startState: t, + line: e, + }); + while (l < e.length) + h.type && f.push(h), + (h = { value: e.substring(l, (l += 2e3)), type: "overflow" }); + (r = "start"), (n = []); + break; + } + } + return ( + h.type && f.push(h), + n.length > 1 && n[0] !== r && n.unshift("#tmp", r), + { tokens: f, state: n.length ? n : r } + ); + }), + (this.reportError = r.reportError); + }).call(s.prototype), + (t.Tokenizer = s); + }), + define( + "ace/mode/text_highlight_rules", + ["require", "exports", "module", "ace/lib/lang"], + function (e, t, n) { + "use strict"; + var r = e("../lib/lang"), + i = function () { + this.$rules = { + start: [{ token: "empty_line", regex: "^$" }, { defaultToken: "text" }], + }; + }; + (function () { + (this.addRules = function (e, t) { + if (!t) { + for (var n in e) this.$rules[n] = e[n]; + return; + } + for (var n in e) { + var r = e[n]; + for (var i = 0; i < r.length; i++) { + var s = r[i]; + if (s.next || s.onMatch) + typeof s.next == "string" && + s.next.indexOf(t) !== 0 && + (s.next = t + s.next), + s.nextState && + s.nextState.indexOf(t) !== 0 && + (s.nextState = t + s.nextState); + } + this.$rules[t + n] = r; + } + }), + (this.getRules = function () { + return this.$rules; + }), + (this.embedRules = function (e, t, n, i, s) { + var o = typeof e == "function" ? new e().getRules() : e; + if (i) for (var u = 0; u < i.length; u++) i[u] = t + i[u]; + else { + i = []; + for (var a in o) i.push(t + a); + } + this.addRules(o, t); + if (n) { + var f = Array.prototype[s ? "push" : "unshift"]; + for (var u = 0; u < i.length; u++) + f.apply(this.$rules[i[u]], r.deepCopy(n)); + } + this.$embeds || (this.$embeds = []), this.$embeds.push(t); + }), + (this.getEmbeds = function () { + return this.$embeds; + }); + var e = function (e, t) { + return ( + (e != "start" || t.length) && t.unshift(this.nextState, e), + this.nextState + ); + }, + t = function (e, t) { + return t.shift(), t.shift() || "start"; + }; + (this.normalizeRules = function () { + function i(s) { + var o = r[s]; + o.processed = !0; + for (var u = 0; u < o.length; u++) { + var a = o[u], + f = null; + Array.isArray(a) && ((f = a), (a = {})), + !a.regex && + a.start && + ((a.regex = a.start), + a.next || (a.next = []), + a.next.push( + { defaultToken: a.token }, + { + token: a.token + ".end", + regex: a.end || a.start, + next: "pop", + }, + ), + (a.token = a.token + ".start"), + (a.push = !0)); + var l = a.next || a.push; + if (l && Array.isArray(l)) { + var c = a.stateName; + c || + ((c = a.token), + typeof c != "string" && (c = c[0] || ""), + r[c] && (c += n++)), + (r[c] = l), + (a.next = c), + i(c); + } else l == "pop" && (a.next = t); + a.push && + ((a.nextState = a.next || a.push), (a.next = e), delete a.push); + if (a.rules) + for (var h in a.rules) + r[h] + ? r[h].push && r[h].push.apply(r[h], a.rules[h]) + : (r[h] = a.rules[h]); + var p = typeof a == "string" ? a : a.include; + p && + (Array.isArray(p) + ? (f = p.map(function (e) { + return r[e]; + })) + : (f = r[p])); + if (f) { + var d = [u, 1].concat(f); + a.noEscape && + (d = d.filter(function (e) { + return !e.next; + })), + o.splice.apply(o, d), + u--; + } + a.keywordMap && + ((a.token = this.createKeywordMapper( + a.keywordMap, + a.defaultToken || "text", + a.caseInsensitive, + )), + delete a.defaultToken); + } + } + var n = 0, + r = this.$rules; + Object.keys(r).forEach(i, this); + }), + (this.createKeywordMapper = function (e, t, n, r) { + var i = Object.create(null); + return ( + Object.keys(e).forEach(function (t) { + var s = e[t]; + n && (s = s.toLowerCase()); + var o = s.split(r || "|"); + for (var u = o.length; u--; ) i[o[u]] = t; + }), + Object.getPrototypeOf(i) && (i.__proto__ = null), + (this.$keywordList = Object.keys(i)), + (e = null), + n + ? function (e) { + return i[e.toLowerCase()] || t; + } + : function (e) { + return i[e] || t; + } + ); + }), + (this.getKeywords = function () { + return this.$keywords; + }); + }).call(i.prototype), + (t.TextHighlightRules = i); + }, + ), + define("ace/mode/behaviour", ["require", "exports", "module"], function (e, t, n) { + "use strict"; + var r = function () { + this.$behaviours = {}; + }; + (function () { + (this.add = function (e, t, n) { + switch (undefined) { + case this.$behaviours: + this.$behaviours = {}; + case this.$behaviours[e]: + this.$behaviours[e] = {}; + } + this.$behaviours[e][t] = n; + }), + (this.addBehaviours = function (e) { + for (var t in e) for (var n in e[t]) this.add(t, n, e[t][n]); + }), + (this.remove = function (e) { + this.$behaviours && this.$behaviours[e] && delete this.$behaviours[e]; + }), + (this.inherit = function (e, t) { + if (typeof e == "function") var n = new e().getBehaviours(t); + else var n = e.getBehaviours(t); + this.addBehaviours(n); + }), + (this.getBehaviours = function (e) { + if (!e) return this.$behaviours; + var t = {}; + for (var n = 0; n < e.length; n++) + this.$behaviours[e[n]] && (t[e[n]] = this.$behaviours[e[n]]); + return t; + }); + }).call(r.prototype), + (t.Behaviour = r); + }), + define("ace/token_iterator", ["require", "exports", "module", "ace/range"], function (e, t, n) { + "use strict"; + var r = e("./range").Range, + i = function (e, t, n) { + (this.$session = e), (this.$row = t), (this.$rowTokens = e.getTokens(t)); + var r = e.getTokenAt(t, n); + this.$tokenIndex = r ? r.index : -1; + }; + (function () { + (this.stepBackward = function () { + this.$tokenIndex -= 1; + while (this.$tokenIndex < 0) { + this.$row -= 1; + if (this.$row < 0) return (this.$row = 0), null; + (this.$rowTokens = this.$session.getTokens(this.$row)), + (this.$tokenIndex = this.$rowTokens.length - 1); + } + return this.$rowTokens[this.$tokenIndex]; + }), + (this.stepForward = function () { + this.$tokenIndex += 1; + var e; + while (this.$tokenIndex >= this.$rowTokens.length) { + (this.$row += 1), e || (e = this.$session.getLength()); + if (this.$row >= e) return (this.$row = e - 1), null; + (this.$rowTokens = this.$session.getTokens(this.$row)), + (this.$tokenIndex = 0); + } + return this.$rowTokens[this.$tokenIndex]; + }), + (this.getCurrentToken = function () { + return this.$rowTokens[this.$tokenIndex]; + }), + (this.getCurrentTokenRow = function () { + return this.$row; + }), + (this.getCurrentTokenColumn = function () { + var e = this.$rowTokens, + t = this.$tokenIndex, + n = e[t].start; + if (n !== undefined) return n; + n = 0; + while (t > 0) (t -= 1), (n += e[t].value.length); + return n; + }), + (this.getCurrentTokenPosition = function () { + return { row: this.$row, column: this.getCurrentTokenColumn() }; + }), + (this.getCurrentTokenRange = function () { + var e = this.$rowTokens[this.$tokenIndex], + t = this.getCurrentTokenColumn(); + return new r(this.$row, t, this.$row, t + e.value.length); + }); + }).call(i.prototype), + (t.TokenIterator = i); + }), + define( + "ace/mode/behaviour/cstyle", + [ + "require", + "exports", + "module", + "ace/lib/oop", + "ace/mode/behaviour", + "ace/token_iterator", + "ace/lib/lang", + ], + function (e, t, n) { + "use strict"; + var r = e("../../lib/oop"), + i = e("../behaviour").Behaviour, + s = e("../../token_iterator").TokenIterator, + o = e("../../lib/lang"), + u = ["text", "paren.rparen", "punctuation.operator"], + a = ["text", "paren.rparen", "punctuation.operator", "comment"], + f, + l = {}, + c = { '"': '"', "'": "'" }, + h = function (e) { + var t = -1; + e.multiSelect && + ((t = e.selection.index), + l.rangeCount != e.multiSelect.rangeCount && + (l = { rangeCount: e.multiSelect.rangeCount })); + if (l[t]) return (f = l[t]); + f = l[t] = { + autoInsertedBrackets: 0, + autoInsertedRow: -1, + autoInsertedLineEnd: "", + maybeInsertedBrackets: 0, + maybeInsertedRow: -1, + maybeInsertedLineStart: "", + maybeInsertedLineEnd: "", + }; + }, + p = function (e, t, n, r) { + var i = e.end.row - e.start.row; + return { + text: n + t + r, + selection: [0, e.start.column + 1, i, e.end.column + (i ? 0 : 1)], + }; + }, + d = function (e) { + this.add("braces", "insertion", function (t, n, r, i, s) { + var u = r.getCursorPosition(), + a = i.doc.getLine(u.row); + if (s == "{") { + h(r); + var l = r.getSelectionRange(), + c = i.doc.getTextRange(l); + if (c !== "" && c !== "{" && r.getWrapBehavioursEnabled()) + return p(l, c, "{", "}"); + if (d.isSaneInsertion(r, i)) + return /[\]\}\)]/.test(a[u.column]) || + r.inMultiSelectMode || + (e && e.braces) + ? (d.recordAutoInsert(r, i, "}"), + { text: "{}", selection: [1, 1] }) + : (d.recordMaybeInsert(r, i, "{"), + { text: "{", selection: [1, 1] }); + } else if (s == "}") { + h(r); + var v = a.substring(u.column, u.column + 1); + if (v == "}") { + var m = i.$findOpeningBracket("}", { + column: u.column + 1, + row: u.row, + }); + if (m !== null && d.isAutoInsertedClosing(u, a, s)) + return ( + d.popAutoInsertedClosing(), { text: "", selection: [1, 1] } + ); + } + } else { + if (s == "\n" || s == "\r\n") { + h(r); + var g = ""; + d.isMaybeInsertedClosing(u, a) && + ((g = o.stringRepeat("}", f.maybeInsertedBrackets)), + d.clearMaybeInsertedClosing()); + var v = a.substring(u.column, u.column + 1); + if (v === "}") { + var y = i.findMatchingBracket( + { row: u.row, column: u.column + 1 }, + "}", + ); + if (!y) return null; + var b = this.$getIndent(i.getLine(y.row)); + } else { + if (!g) { + d.clearMaybeInsertedClosing(); + return; + } + var b = this.$getIndent(a); + } + var w = b + i.getTabString(); + return { + text: "\n" + w + "\n" + b + g, + selection: [1, w.length, 1, w.length], + }; + } + d.clearMaybeInsertedClosing(); + } + }), + this.add("braces", "deletion", function (e, t, n, r, i) { + var s = r.doc.getTextRange(i); + if (!i.isMultiLine() && s == "{") { + h(n); + var o = r.doc.getLine(i.start.row), + u = o.substring(i.end.column, i.end.column + 1); + if (u == "}") return i.end.column++, i; + f.maybeInsertedBrackets--; + } + }), + this.add("parens", "insertion", function (e, t, n, r, i) { + if (i == "(") { + h(n); + var s = n.getSelectionRange(), + o = r.doc.getTextRange(s); + if (o !== "" && n.getWrapBehavioursEnabled()) + return p(s, o, "(", ")"); + if (d.isSaneInsertion(n, r)) + return ( + d.recordAutoInsert(n, r, ")"), + { text: "()", selection: [1, 1] } + ); + } else if (i == ")") { + h(n); + var u = n.getCursorPosition(), + a = r.doc.getLine(u.row), + f = a.substring(u.column, u.column + 1); + if (f == ")") { + var l = r.$findOpeningBracket(")", { + column: u.column + 1, + row: u.row, + }); + if (l !== null && d.isAutoInsertedClosing(u, a, i)) + return ( + d.popAutoInsertedClosing(), + { text: "", selection: [1, 1] } + ); + } + } + }), + this.add("parens", "deletion", function (e, t, n, r, i) { + var s = r.doc.getTextRange(i); + if (!i.isMultiLine() && s == "(") { + h(n); + var o = r.doc.getLine(i.start.row), + u = o.substring(i.start.column + 1, i.start.column + 2); + if (u == ")") return i.end.column++, i; + } + }), + this.add("brackets", "insertion", function (e, t, n, r, i) { + if (i == "[") { + h(n); + var s = n.getSelectionRange(), + o = r.doc.getTextRange(s); + if (o !== "" && n.getWrapBehavioursEnabled()) + return p(s, o, "[", "]"); + if (d.isSaneInsertion(n, r)) + return ( + d.recordAutoInsert(n, r, "]"), + { text: "[]", selection: [1, 1] } + ); + } else if (i == "]") { + h(n); + var u = n.getCursorPosition(), + a = r.doc.getLine(u.row), + f = a.substring(u.column, u.column + 1); + if (f == "]") { + var l = r.$findOpeningBracket("]", { + column: u.column + 1, + row: u.row, + }); + if (l !== null && d.isAutoInsertedClosing(u, a, i)) + return ( + d.popAutoInsertedClosing(), + { text: "", selection: [1, 1] } + ); + } + } + }), + this.add("brackets", "deletion", function (e, t, n, r, i) { + var s = r.doc.getTextRange(i); + if (!i.isMultiLine() && s == "[") { + h(n); + var o = r.doc.getLine(i.start.row), + u = o.substring(i.start.column + 1, i.start.column + 2); + if (u == "]") return i.end.column++, i; + } + }), + this.add("string_dquotes", "insertion", function (e, t, n, r, i) { + var s = r.$mode.$quotes || c; + if (i.length == 1 && s[i]) { + if (this.lineCommentStart && this.lineCommentStart.indexOf(i) != -1) + return; + h(n); + var o = i, + u = n.getSelectionRange(), + a = r.doc.getTextRange(u); + if ( + a !== "" && + (a.length != 1 || !s[a]) && + n.getWrapBehavioursEnabled() + ) + return p(u, a, o, o); + if (!a) { + var f = n.getCursorPosition(), + l = r.doc.getLine(f.row), + d = l.substring(f.column - 1, f.column), + v = l.substring(f.column, f.column + 1), + m = r.getTokenAt(f.row, f.column), + g = r.getTokenAt(f.row, f.column + 1); + if (d == "\\" && m && /escape/.test(m.type)) return null; + var y = m && /string|escape/.test(m.type), + b = !g || /string|escape/.test(g.type), + w; + if (v == o) + (w = y !== b), w && /string\.end/.test(g.type) && (w = !1); + else { + if (y && !b) return null; + if (y && b) return null; + var E = r.$mode.tokenRe; + E.lastIndex = 0; + var S = E.test(d); + E.lastIndex = 0; + var x = E.test(d); + if (S || x) return null; + if (v && !/[\s;,.})\]\\]/.test(v)) return null; + w = !0; + } + return { text: w ? o + o : "", selection: [1, 1] }; + } + } + }), + this.add("string_dquotes", "deletion", function (e, t, n, r, i) { + var s = r.$mode.$quotes || c, + o = r.doc.getTextRange(i); + if (!i.isMultiLine() && s.hasOwnProperty(o)) { + h(n); + var u = r.doc.getLine(i.start.row), + a = u.substring(i.start.column + 1, i.start.column + 2); + if (a == o) return i.end.column++, i; + } + }); + }; + (d.isSaneInsertion = function (e, t) { + var n = e.getCursorPosition(), + r = new s(t, n.row, n.column); + if (!this.$matchTokenType(r.getCurrentToken() || "text", u)) { + var i = new s(t, n.row, n.column + 1); + if (!this.$matchTokenType(i.getCurrentToken() || "text", u)) return !1; + } + return ( + r.stepForward(), + r.getCurrentTokenRow() !== n.row || + this.$matchTokenType(r.getCurrentToken() || "text", a) + ); + }), + (d.$matchTokenType = function (e, t) { + return t.indexOf(e.type || e) > -1; + }), + (d.recordAutoInsert = function (e, t, n) { + var r = e.getCursorPosition(), + i = t.doc.getLine(r.row); + this.isAutoInsertedClosing(r, i, f.autoInsertedLineEnd[0]) || + (f.autoInsertedBrackets = 0), + (f.autoInsertedRow = r.row), + (f.autoInsertedLineEnd = n + i.substr(r.column)), + f.autoInsertedBrackets++; + }), + (d.recordMaybeInsert = function (e, t, n) { + var r = e.getCursorPosition(), + i = t.doc.getLine(r.row); + this.isMaybeInsertedClosing(r, i) || (f.maybeInsertedBrackets = 0), + (f.maybeInsertedRow = r.row), + (f.maybeInsertedLineStart = i.substr(0, r.column) + n), + (f.maybeInsertedLineEnd = i.substr(r.column)), + f.maybeInsertedBrackets++; + }), + (d.isAutoInsertedClosing = function (e, t, n) { + return ( + f.autoInsertedBrackets > 0 && + e.row === f.autoInsertedRow && + n === f.autoInsertedLineEnd[0] && + t.substr(e.column) === f.autoInsertedLineEnd + ); + }), + (d.isMaybeInsertedClosing = function (e, t) { + return ( + f.maybeInsertedBrackets > 0 && + e.row === f.maybeInsertedRow && + t.substr(e.column) === f.maybeInsertedLineEnd && + t.substr(0, e.column) == f.maybeInsertedLineStart + ); + }), + (d.popAutoInsertedClosing = function () { + (f.autoInsertedLineEnd = f.autoInsertedLineEnd.substr(1)), + f.autoInsertedBrackets--; + }), + (d.clearMaybeInsertedClosing = function () { + f && ((f.maybeInsertedBrackets = 0), (f.maybeInsertedRow = -1)); + }), + r.inherits(d, i), + (t.CstyleBehaviour = d); + }, + ), + define("ace/unicode", ["require", "exports", "module"], function (e, t, n) { + "use strict"; + var r = [ + 48, 9, 8, 25, 5, 0, 2, 25, 48, 0, 11, 0, 5, 0, 6, 22, 2, 30, 2, 457, 5, 11, 15, 4, + 8, 0, 2, 0, 18, 116, 2, 1, 3, 3, 9, 0, 2, 2, 2, 0, 2, 19, 2, 82, 2, 138, 2, 4, 3, + 155, 12, 37, 3, 0, 8, 38, 10, 44, 2, 0, 2, 1, 2, 1, 2, 0, 9, 26, 6, 2, 30, 10, 7, + 61, 2, 9, 5, 101, 2, 7, 3, 9, 2, 18, 3, 0, 17, 58, 3, 100, 15, 53, 5, 0, 6, 45, 211, + 57, 3, 18, 2, 5, 3, 11, 3, 9, 2, 1, 7, 6, 2, 2, 2, 7, 3, 1, 3, 21, 2, 6, 2, 0, 4, 3, + 3, 8, 3, 1, 3, 3, 9, 0, 5, 1, 2, 4, 3, 11, 16, 2, 2, 5, 5, 1, 3, 21, 2, 6, 2, 1, 2, + 1, 2, 1, 3, 0, 2, 4, 5, 1, 3, 2, 4, 0, 8, 3, 2, 0, 8, 15, 12, 2, 2, 8, 2, 2, 2, 21, + 2, 6, 2, 1, 2, 4, 3, 9, 2, 2, 2, 2, 3, 0, 16, 3, 3, 9, 18, 2, 2, 7, 3, 1, 3, 21, 2, + 6, 2, 1, 2, 4, 3, 8, 3, 1, 3, 2, 9, 1, 5, 1, 2, 4, 3, 9, 2, 0, 17, 1, 2, 5, 4, 2, 2, + 3, 4, 1, 2, 0, 2, 1, 4, 1, 4, 2, 4, 11, 5, 4, 4, 2, 2, 3, 3, 0, 7, 0, 15, 9, 18, 2, + 2, 7, 2, 2, 2, 22, 2, 9, 2, 4, 4, 7, 2, 2, 2, 3, 8, 1, 2, 1, 7, 3, 3, 9, 19, 1, 2, + 7, 2, 2, 2, 22, 2, 9, 2, 4, 3, 8, 2, 2, 2, 3, 8, 1, 8, 0, 2, 3, 3, 9, 19, 1, 2, 7, + 2, 2, 2, 22, 2, 15, 4, 7, 2, 2, 2, 3, 10, 0, 9, 3, 3, 9, 11, 5, 3, 1, 2, 17, 4, 23, + 2, 8, 2, 0, 3, 6, 4, 0, 5, 5, 2, 0, 2, 7, 19, 1, 14, 57, 6, 14, 2, 9, 40, 1, 2, 0, + 3, 1, 2, 0, 3, 0, 7, 3, 2, 6, 2, 2, 2, 0, 2, 0, 3, 1, 2, 12, 2, 2, 3, 4, 2, 0, 2, 5, + 3, 9, 3, 1, 35, 0, 24, 1, 7, 9, 12, 0, 2, 0, 2, 0, 5, 9, 2, 35, 5, 19, 2, 5, 5, 7, + 2, 35, 10, 0, 58, 73, 7, 77, 3, 37, 11, 42, 2, 0, 4, 328, 2, 3, 3, 6, 2, 0, 2, 3, 3, + 40, 2, 3, 3, 32, 2, 3, 3, 6, 2, 0, 2, 3, 3, 14, 2, 56, 2, 3, 3, 66, 5, 0, 33, 15, + 17, 84, 13, 619, 3, 16, 2, 25, 6, 74, 22, 12, 2, 6, 12, 20, 12, 19, 13, 12, 2, 2, 2, + 1, 13, 51, 3, 29, 4, 0, 5, 1, 3, 9, 34, 2, 3, 9, 7, 87, 9, 42, 6, 69, 11, 28, 4, 11, + 5, 11, 11, 39, 3, 4, 12, 43, 5, 25, 7, 10, 38, 27, 5, 62, 2, 28, 3, 10, 7, 9, 14, 0, + 89, 75, 5, 9, 18, 8, 13, 42, 4, 11, 71, 55, 9, 9, 4, 48, 83, 2, 2, 30, 14, 230, 23, + 280, 3, 5, 3, 37, 3, 5, 3, 7, 2, 0, 2, 0, 2, 0, 2, 30, 3, 52, 2, 6, 2, 0, 4, 2, 2, + 6, 4, 3, 3, 5, 5, 12, 6, 2, 2, 6, 67, 1, 20, 0, 29, 0, 14, 0, 17, 4, 60, 12, 5, 0, + 4, 11, 18, 0, 5, 0, 3, 9, 2, 0, 4, 4, 7, 0, 2, 0, 2, 0, 2, 3, 2, 10, 3, 3, 6, 4, 5, + 0, 53, 1, 2684, 46, 2, 46, 2, 132, 7, 6, 15, 37, 11, 53, 10, 0, 17, 22, 10, 6, 2, 6, + 2, 6, 2, 6, 2, 6, 2, 6, 2, 6, 2, 6, 2, 31, 48, 0, 470, 1, 36, 5, 2, 4, 6, 1, 5, 85, + 3, 1, 3, 2, 2, 89, 2, 3, 6, 40, 4, 93, 18, 23, 57, 15, 513, 6581, 75, 20939, 53, + 1164, 68, 45, 3, 268, 4, 27, 21, 31, 3, 13, 13, 1, 2, 24, 9, 69, 11, 1, 38, 8, 3, + 102, 3, 1, 111, 44, 25, 51, 13, 68, 12, 9, 7, 23, 4, 0, 5, 45, 3, 35, 13, 28, 4, 64, + 15, 10, 39, 54, 10, 13, 3, 9, 7, 22, 4, 1, 5, 66, 25, 2, 227, 42, 2, 1, 3, 9, 7, + 11171, 13, 22, 5, 48, 8453, 301, 3, 61, 3, 105, 39, 6, 13, 4, 6, 11, 2, 12, 2, 4, 2, + 0, 2, 1, 2, 1, 2, 107, 34, 362, 19, 63, 3, 53, 41, 11, 5, 15, 17, 6, 13, 1, 25, 2, + 33, 4, 2, 134, 20, 9, 8, 25, 5, 0, 2, 25, 12, 88, 4, 5, 3, 5, 3, 5, 3, 2, + ], + i = 0, + s = []; + for (var o = 0; o < r.length; o += 2) + s.push((i += r[o])), r[o + 1] && s.push(45, (i += r[o + 1])); + t.wordChars = String.fromCharCode.apply(null, s); + }), + define( + "ace/mode/text", + [ + "require", + "exports", + "module", + "ace/config", + "ace/tokenizer", + "ace/mode/text_highlight_rules", + "ace/mode/behaviour/cstyle", + "ace/unicode", + "ace/lib/lang", + "ace/token_iterator", + "ace/range", + ], + function (e, t, n) { + "use strict"; + var r = e("../config"), + i = e("../tokenizer").Tokenizer, + s = e("./text_highlight_rules").TextHighlightRules, + o = e("./behaviour/cstyle").CstyleBehaviour, + u = e("../unicode"), + a = e("../lib/lang"), + f = e("../token_iterator").TokenIterator, + l = e("../range").Range, + c = function () { + this.HighlightRules = s; + }; + (function () { + (this.$defaultBehaviour = new o()), + (this.tokenRe = new RegExp("^[" + u.wordChars + "\\$_]+", "g")), + (this.nonTokenRe = new RegExp("^(?:[^" + u.wordChars + "\\$_]|\\s])+", "g")), + (this.getTokenizer = function () { + return ( + this.$tokenizer || + ((this.$highlightRules = + this.$highlightRules || + new this.HighlightRules(this.$highlightRuleConfig)), + (this.$tokenizer = new i(this.$highlightRules.getRules()))), + this.$tokenizer + ); + }), + (this.lineCommentStart = ""), + (this.blockComment = ""), + (this.toggleCommentLines = function (e, t, n, r) { + function w(e) { + for (var t = n; t <= r; t++) e(i.getLine(t), t); + } + var i = t.doc, + s = !0, + o = !0, + u = Infinity, + f = t.getTabSize(), + l = !1; + if (!this.lineCommentStart) { + if (!this.blockComment) return !1; + var c = this.blockComment.start, + h = this.blockComment.end, + p = new RegExp("^(\\s*)(?:" + a.escapeRegExp(c) + ")"), + d = new RegExp("(?:" + a.escapeRegExp(h) + ")\\s*$"), + v = function (e, t) { + if (g(e, t)) return; + if (!s || /\S/.test(e)) + i.insertInLine({ row: t, column: e.length }, h), + i.insertInLine({ row: t, column: u }, c); + }, + m = function (e, t) { + var n; + (n = e.match(d)) && + i.removeInLine(t, e.length - n[0].length, e.length), + (n = e.match(p)) && + i.removeInLine(t, n[1].length, n[0].length); + }, + g = function (e, n) { + if (p.test(e)) return !0; + var r = t.getTokens(n); + for (var i = 0; i < r.length; i++) + if (r[i].type === "comment") return !0; + }; + } else { + if (Array.isArray(this.lineCommentStart)) + var p = this.lineCommentStart.map(a.escapeRegExp).join("|"), + c = this.lineCommentStart[0]; + else + var p = a.escapeRegExp(this.lineCommentStart), + c = this.lineCommentStart; + (p = new RegExp("^(\\s*)(?:" + p + ") ?")), (l = t.getUseSoftTabs()); + var m = function (e, t) { + var n = e.match(p); + if (!n) return; + var r = n[1].length, + s = n[0].length; + !b(e, r, s) && n[0][s - 1] == " " && s--, + i.removeInLine(t, r, s); + }, + y = c + " ", + v = function (e, t) { + if (!s || /\S/.test(e)) + b(e, u, u) + ? i.insertInLine({ row: t, column: u }, y) + : i.insertInLine({ row: t, column: u }, c); + }, + g = function (e, t) { + return p.test(e); + }, + b = function (e, t, n) { + var r = 0; + while (t-- && e.charAt(t) == " ") r++; + if (r % f != 0) return !1; + var r = 0; + while (e.charAt(n++) == " ") r++; + return f > 2 ? r % f != f - 1 : r % f == 0; + }; + } + var E = Infinity; + w(function (e, t) { + var n = e.search(/\S/); + n !== -1 + ? (n < u && (u = n), o && !g(e, t) && (o = !1)) + : E > e.length && (E = e.length); + }), + u == Infinity && ((u = E), (s = !1), (o = !1)), + l && u % f != 0 && (u = Math.floor(u / f) * f), + w(o ? m : v); + }), + (this.toggleBlockComment = function (e, t, n, r) { + var i = this.blockComment; + if (!i) return; + !i.start && i[0] && (i = i[0]); + var s = new f(t, r.row, r.column), + o = s.getCurrentToken(), + u = t.selection, + a = t.selection.toOrientedRange(), + c, + h; + if (o && /comment/.test(o.type)) { + var p, d; + while (o && /comment/.test(o.type)) { + var v = o.value.indexOf(i.start); + if (v != -1) { + var m = s.getCurrentTokenRow(), + g = s.getCurrentTokenColumn() + v; + p = new l(m, g, m, g + i.start.length); + break; + } + o = s.stepBackward(); + } + var s = new f(t, r.row, r.column), + o = s.getCurrentToken(); + while (o && /comment/.test(o.type)) { + var v = o.value.indexOf(i.end); + if (v != -1) { + var m = s.getCurrentTokenRow(), + g = s.getCurrentTokenColumn() + v; + d = new l(m, g, m, g + i.end.length); + break; + } + o = s.stepForward(); + } + d && t.remove(d), + p && (t.remove(p), (c = p.start.row), (h = -i.start.length)); + } else + (h = i.start.length), + (c = n.start.row), + t.insert(n.end, i.end), + t.insert(n.start, i.start); + a.start.row == c && (a.start.column += h), + a.end.row == c && (a.end.column += h), + t.selection.fromOrientedRange(a); + }), + (this.getNextLineIndent = function (e, t, n) { + return this.$getIndent(t); + }), + (this.checkOutdent = function (e, t, n) { + return !1; + }), + (this.autoOutdent = function (e, t, n) {}), + (this.$getIndent = function (e) { + return e.match(/^\s*/)[0]; + }), + (this.createWorker = function (e) { + return null; + }), + (this.createModeDelegates = function (e) { + (this.$embeds = []), (this.$modes = {}); + for (var t in e) + if (e[t]) { + var n = e[t], + i = n.prototype.$id, + s = r.$modes[i]; + s || (r.$modes[i] = s = new n()), + r.$modes[t] || (r.$modes[t] = s), + this.$embeds.push(t), + (this.$modes[t] = s); + } + var o = [ + "toggleBlockComment", + "toggleCommentLines", + "getNextLineIndent", + "checkOutdent", + "autoOutdent", + "transformAction", + "getCompletions", + ]; + for (var t = 0; t < o.length; t++) + (function (e) { + var n = o[t], + r = e[n]; + e[o[t]] = function () { + return this.$delegator(n, arguments, r); + }; + })(this); + }), + (this.$delegator = function (e, t, n) { + var r = t[0]; + if (typeof r != "string") { + if (Array.isArray(r[2])) { + var i = r[2][r[2].length - 1], + s = this.$modes[i]; + if (s) return s[e].apply(s, [r[1]].concat([].slice.call(t, 1))); + } + r = r[0]; + } + for (var o = 0; o < this.$embeds.length; o++) { + if (!this.$modes[this.$embeds[o]]) continue; + var u = r.split(this.$embeds[o]); + if (!u[0] && u[1]) { + t[0] = u[1]; + var s = this.$modes[this.$embeds[o]]; + return s[e].apply(s, t); + } + } + var a = n.apply(this, t); + return n ? a : undefined; + }), + (this.transformAction = function (e, t, n, r, i) { + if (this.$behaviour) { + var s = this.$behaviour.getBehaviours(); + for (var o in s) + if (s[o][t]) { + var u = s[o][t].apply(this, arguments); + if (u) return u; + } + } + }), + (this.getKeywords = function (e) { + if (!this.completionKeywords) { + var t = this.$tokenizer.rules, + n = []; + for (var r in t) { + var i = t[r]; + for (var s = 0, o = i.length; s < o; s++) + if (typeof i[s].token == "string") + /keyword|support|storage/.test(i[s].token) && + n.push(i[s].regex); + else if (typeof i[s].token == "object") + for (var u = 0, a = i[s].token.length; u < a; u++) + if (/keyword|support|storage/.test(i[s].token[u])) { + var r = i[s].regex.match(/\(.+?\)/g)[u]; + n.push(r.substr(1, r.length - 2)); + } + } + this.completionKeywords = n; + } + return e ? n.concat(this.$keywordList || []) : this.$keywordList; + }), + (this.$createKeywordList = function () { + return ( + this.$highlightRules || this.getTokenizer(), + (this.$keywordList = this.$highlightRules.$keywordList || []) + ); + }), + (this.getCompletions = function (e, t, n, r) { + var i = this.$keywordList || this.$createKeywordList(); + return i.map(function (e) { + return { name: e, value: e, score: 0, meta: "keyword" }; + }); + }), + (this.$id = "ace/mode/text"); + }).call(c.prototype), + (t.Mode = c); + }, + ), + define("ace/apply_delta", ["require", "exports", "module"], function (e, t, n) { + "use strict"; + function r(e, t) { + throw (console.log("Invalid Delta:", e), "Invalid Delta: " + t); + } + function i(e, t) { + return t.row >= 0 && t.row < e.length && t.column >= 0 && t.column <= e[t.row].length; + } + function s(e, t) { + t.action != "insert" && + t.action != "remove" && + r(t, "delta.action must be 'insert' or 'remove'"), + t.lines instanceof Array || r(t, "delta.lines must be an Array"), + (!t.start || !t.end) && r(t, "delta.start/end must be an present"); + var n = t.start; + i(e, t.start) || r(t, "delta.start must be contained in document"); + var s = t.end; + t.action == "remove" && + !i(e, s) && + r(t, "delta.end must contained in document for 'remove' actions"); + var o = s.row - n.row, + u = s.column - (o == 0 ? n.column : 0); + (o != t.lines.length - 1 || t.lines[o].length != u) && + r(t, "delta.range must match delta lines"); + } + t.applyDelta = function (e, t, n) { + var r = t.start.row, + i = t.start.column, + s = e[r] || ""; + switch (t.action) { + case "insert": + var o = t.lines; + if (o.length === 1) e[r] = s.substring(0, i) + t.lines[0] + s.substring(i); + else { + var u = [r, 1].concat(t.lines); + e.splice.apply(e, u), + (e[r] = s.substring(0, i) + e[r]), + (e[r + t.lines.length - 1] += s.substring(i)); + } + break; + case "remove": + var a = t.end.column, + f = t.end.row; + r === f + ? (e[r] = s.substring(0, i) + s.substring(a)) + : e.splice(r, f - r + 1, s.substring(0, i) + e[f].substring(a)); + } + }; + }), + define( + "ace/anchor", + ["require", "exports", "module", "ace/lib/oop", "ace/lib/event_emitter"], + function (e, t, n) { + "use strict"; + var r = e("./lib/oop"), + i = e("./lib/event_emitter").EventEmitter, + s = (t.Anchor = function (e, t, n) { + (this.$onChange = this.onChange.bind(this)), + this.attach(e), + typeof n == "undefined" + ? this.setPosition(t.row, t.column) + : this.setPosition(t, n); + }); + (function () { + function e(e, t, n) { + var r = n ? e.column <= t.column : e.column < t.column; + return e.row < t.row || (e.row == t.row && r); + } + function t(t, n, r) { + var i = t.action == "insert", + s = (i ? 1 : -1) * (t.end.row - t.start.row), + o = (i ? 1 : -1) * (t.end.column - t.start.column), + u = t.start, + a = i ? u : t.end; + return e(n, u, r) + ? { row: n.row, column: n.column } + : e(a, n, !r) + ? { row: n.row + s, column: n.column + (n.row == a.row ? o : 0) } + : { row: u.row, column: u.column }; + } + r.implement(this, i), + (this.getPosition = function () { + return this.$clipPositionToDocument(this.row, this.column); + }), + (this.getDocument = function () { + return this.document; + }), + (this.$insertRight = !1), + (this.onChange = function (e) { + if (e.start.row == e.end.row && e.start.row != this.row) return; + if (e.start.row > this.row) return; + var n = t(e, { row: this.row, column: this.column }, this.$insertRight); + this.setPosition(n.row, n.column, !0); + }), + (this.setPosition = function (e, t, n) { + var r; + n ? (r = { row: e, column: t }) : (r = this.$clipPositionToDocument(e, t)); + if (this.row == r.row && this.column == r.column) return; + var i = { row: this.row, column: this.column }; + (this.row = r.row), + (this.column = r.column), + this._signal("change", { old: i, value: r }); + }), + (this.detach = function () { + this.document.removeEventListener("change", this.$onChange); + }), + (this.attach = function (e) { + (this.document = e || this.document), + this.document.on("change", this.$onChange); + }), + (this.$clipPositionToDocument = function (e, t) { + var n = {}; + return ( + e >= this.document.getLength() + ? ((n.row = Math.max(0, this.document.getLength() - 1)), + (n.column = this.document.getLine(n.row).length)) + : e < 0 + ? ((n.row = 0), (n.column = 0)) + : ((n.row = e), + (n.column = Math.min( + this.document.getLine(n.row).length, + Math.max(0, t), + ))), + t < 0 && (n.column = 0), + n + ); + }); + }).call(s.prototype); + }, + ), + define( + "ace/document", + [ + "require", + "exports", + "module", + "ace/lib/oop", + "ace/apply_delta", + "ace/lib/event_emitter", + "ace/range", + "ace/anchor", + ], + function (e, t, n) { + "use strict"; + var r = e("./lib/oop"), + i = e("./apply_delta").applyDelta, + s = e("./lib/event_emitter").EventEmitter, + o = e("./range").Range, + u = e("./anchor").Anchor, + a = function (e) { + (this.$lines = [""]), + e.length === 0 + ? (this.$lines = [""]) + : Array.isArray(e) + ? this.insertMergedLines({ row: 0, column: 0 }, e) + : this.insert({ row: 0, column: 0 }, e); + }; + (function () { + r.implement(this, s), + (this.setValue = function (e) { + var t = this.getLength() - 1; + this.remove(new o(0, 0, t, this.getLine(t).length)), + this.insert({ row: 0, column: 0 }, e); + }), + (this.getValue = function () { + return this.getAllLines().join(this.getNewLineCharacter()); + }), + (this.createAnchor = function (e, t) { + return new u(this, e, t); + }), + "aaa".split(/a/).length === 0 + ? (this.$split = function (e) { + return e.replace(/\r\n|\r/g, "\n").split("\n"); + }) + : (this.$split = function (e) { + return e.split(/\r\n|\r|\n/); + }), + (this.$detectNewLine = function (e) { + var t = e.match(/^.*?(\r\n|\r|\n)/m); + (this.$autoNewLine = t ? t[1] : "\n"), this._signal("changeNewLineMode"); + }), + (this.getNewLineCharacter = function () { + switch (this.$newLineMode) { + case "windows": + return "\r\n"; + case "unix": + return "\n"; + default: + return this.$autoNewLine || "\n"; + } + }), + (this.$autoNewLine = ""), + (this.$newLineMode = "auto"), + (this.setNewLineMode = function (e) { + if (this.$newLineMode === e) return; + (this.$newLineMode = e), this._signal("changeNewLineMode"); + }), + (this.getNewLineMode = function () { + return this.$newLineMode; + }), + (this.isNewLine = function (e) { + return e == "\r\n" || e == "\r" || e == "\n"; + }), + (this.getLine = function (e) { + return this.$lines[e] || ""; + }), + (this.getLines = function (e, t) { + return this.$lines.slice(e, t + 1); + }), + (this.getAllLines = function () { + return this.getLines(0, this.getLength()); + }), + (this.getLength = function () { + return this.$lines.length; + }), + (this.getTextRange = function (e) { + return this.getLinesForRange(e).join(this.getNewLineCharacter()); + }), + (this.getLinesForRange = function (e) { + var t; + if (e.start.row === e.end.row) + t = [this.getLine(e.start.row).substring(e.start.column, e.end.column)]; + else { + (t = this.getLines(e.start.row, e.end.row)), + (t[0] = (t[0] || "").substring(e.start.column)); + var n = t.length - 1; + e.end.row - e.start.row == n && + (t[n] = t[n].substring(0, e.end.column)); + } + return t; + }), + (this.insertLines = function (e, t) { + return ( + console.warn( + "Use of document.insertLines is deprecated. Use the insertFullLines method instead.", + ), + this.insertFullLines(e, t) + ); + }), + (this.removeLines = function (e, t) { + return ( + console.warn( + "Use of document.removeLines is deprecated. Use the removeFullLines method instead.", + ), + this.removeFullLines(e, t) + ); + }), + (this.insertNewLine = function (e) { + return ( + console.warn( + "Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead.", + ), + this.insertMergedLines(e, ["", ""]) + ); + }), + (this.insert = function (e, t) { + return ( + this.getLength() <= 1 && this.$detectNewLine(t), + this.insertMergedLines(e, this.$split(t)) + ); + }), + (this.insertInLine = function (e, t) { + var n = this.clippedPos(e.row, e.column), + r = this.pos(e.row, e.column + t.length); + return ( + this.applyDelta({ start: n, end: r, action: "insert", lines: [t] }, !0), + this.clonePos(r) + ); + }), + (this.clippedPos = function (e, t) { + var n = this.getLength(); + e === undefined + ? (e = n) + : e < 0 + ? (e = 0) + : e >= n && ((e = n - 1), (t = undefined)); + var r = this.getLine(e); + return ( + t == undefined && (t = r.length), + (t = Math.min(Math.max(t, 0), r.length)), + { row: e, column: t } + ); + }), + (this.clonePos = function (e) { + return { row: e.row, column: e.column }; + }), + (this.pos = function (e, t) { + return { row: e, column: t }; + }), + (this.$clipPosition = function (e) { + var t = this.getLength(); + return ( + e.row >= t + ? ((e.row = Math.max(0, t - 1)), + (e.column = this.getLine(t - 1).length)) + : ((e.row = Math.max(0, e.row)), + (e.column = Math.min( + Math.max(e.column, 0), + this.getLine(e.row).length, + ))), + e + ); + }), + (this.insertFullLines = function (e, t) { + e = Math.min(Math.max(e, 0), this.getLength()); + var n = 0; + e < this.getLength() + ? ((t = t.concat([""])), (n = 0)) + : ((t = [""].concat(t)), e--, (n = this.$lines[e].length)), + this.insertMergedLines({ row: e, column: n }, t); + }), + (this.insertMergedLines = function (e, t) { + var n = this.clippedPos(e.row, e.column), + r = { + row: n.row + t.length - 1, + column: (t.length == 1 ? n.column : 0) + t[t.length - 1].length, + }; + return ( + this.applyDelta({ start: n, end: r, action: "insert", lines: t }), + this.clonePos(r) + ); + }), + (this.remove = function (e) { + var t = this.clippedPos(e.start.row, e.start.column), + n = this.clippedPos(e.end.row, e.end.column); + return ( + this.applyDelta({ + start: t, + end: n, + action: "remove", + lines: this.getLinesForRange({ start: t, end: n }), + }), + this.clonePos(t) + ); + }), + (this.removeInLine = function (e, t, n) { + var r = this.clippedPos(e, t), + i = this.clippedPos(e, n); + return ( + this.applyDelta( + { + start: r, + end: i, + action: "remove", + lines: this.getLinesForRange({ start: r, end: i }), + }, + !0, + ), + this.clonePos(r) + ); + }), + (this.removeFullLines = function (e, t) { + (e = Math.min(Math.max(0, e), this.getLength() - 1)), + (t = Math.min(Math.max(0, t), this.getLength() - 1)); + var n = t == this.getLength() - 1 && e > 0, + r = t < this.getLength() - 1, + i = n ? e - 1 : e, + s = n ? this.getLine(i).length : 0, + u = r ? t + 1 : t, + a = r ? 0 : this.getLine(u).length, + f = new o(i, s, u, a), + l = this.$lines.slice(e, t + 1); + return ( + this.applyDelta({ + start: f.start, + end: f.end, + action: "remove", + lines: this.getLinesForRange(f), + }), + l + ); + }), + (this.removeNewLine = function (e) { + e < this.getLength() - 1 && + e >= 0 && + this.applyDelta({ + start: this.pos(e, this.getLine(e).length), + end: this.pos(e + 1, 0), + action: "remove", + lines: ["", ""], + }); + }), + (this.replace = function (e, t) { + e instanceof o || (e = o.fromPoints(e.start, e.end)); + if (t.length === 0 && e.isEmpty()) return e.start; + if (t == this.getTextRange(e)) return e.end; + this.remove(e); + var n; + return t ? (n = this.insert(e.start, t)) : (n = e.start), n; + }), + (this.applyDeltas = function (e) { + for (var t = 0; t < e.length; t++) this.applyDelta(e[t]); + }), + (this.revertDeltas = function (e) { + for (var t = e.length - 1; t >= 0; t--) this.revertDelta(e[t]); + }), + (this.applyDelta = function (e, t) { + var n = e.action == "insert"; + if ( + n + ? e.lines.length <= 1 && !e.lines[0] + : !o.comparePoints(e.start, e.end) + ) + return; + n && e.lines.length > 2e4 + ? this.$splitAndapplyLargeDelta(e, 2e4) + : (i(this.$lines, e, t), this._signal("change", e)); + }), + (this.$splitAndapplyLargeDelta = function (e, t) { + var n = e.lines, + r = n.length - t + 1, + i = e.start.row, + s = e.start.column; + for (var o = 0, u = 0; o < r; o = u) { + u += t - 1; + var a = n.slice(o, u); + a.push(""), + this.applyDelta( + { + start: this.pos(i + o, s), + end: this.pos(i + u, (s = 0)), + action: e.action, + lines: a, + }, + !0, + ); + } + (e.lines = n.slice(o)), + (e.start.row = i + o), + (e.start.column = s), + this.applyDelta(e, !0); + }), + (this.revertDelta = function (e) { + this.applyDelta({ + start: this.clonePos(e.start), + end: this.clonePos(e.end), + action: e.action == "insert" ? "remove" : "insert", + lines: e.lines.slice(), + }); + }), + (this.indexToPosition = function (e, t) { + var n = this.$lines || this.getAllLines(), + r = this.getNewLineCharacter().length; + for (var i = t || 0, s = n.length; i < s; i++) { + e -= n[i].length + r; + if (e < 0) return { row: i, column: e + n[i].length + r }; + } + return { row: s - 1, column: e + n[s - 1].length + r }; + }), + (this.positionToIndex = function (e, t) { + var n = this.$lines || this.getAllLines(), + r = this.getNewLineCharacter().length, + i = 0, + s = Math.min(e.row, n.length); + for (var o = t || 0; o < s; ++o) i += n[o].length + r; + return i + e.column; + }); + }).call(a.prototype), + (t.Document = a); + }, + ), + define( + "ace/background_tokenizer", + ["require", "exports", "module", "ace/lib/oop", "ace/lib/event_emitter"], + function (e, t, n) { + "use strict"; + var r = e("./lib/oop"), + i = e("./lib/event_emitter").EventEmitter, + s = function (e, t) { + (this.running = !1), + (this.lines = []), + (this.states = []), + (this.currentLine = 0), + (this.tokenizer = e); + var n = this; + this.$worker = function () { + if (!n.running) return; + var e = new Date(), + t = n.currentLine, + r = -1, + i = n.doc, + s = t; + while (n.lines[t]) t++; + var o = i.getLength(), + u = 0; + n.running = !1; + while (t < o) { + n.$tokenizeRow(t), (r = t); + do t++; + while (n.lines[t]); + u++; + if (u % 5 === 0 && new Date() - e > 20) { + n.running = setTimeout(n.$worker, 20); + break; + } + } + (n.currentLine = t), r == -1 && (r = t), s <= r && n.fireUpdateEvent(s, r); + }; + }; + (function () { + r.implement(this, i), + (this.setTokenizer = function (e) { + (this.tokenizer = e), (this.lines = []), (this.states = []), this.start(0); + }), + (this.setDocument = function (e) { + (this.doc = e), (this.lines = []), (this.states = []), this.stop(); + }), + (this.fireUpdateEvent = function (e, t) { + var n = { first: e, last: t }; + this._signal("update", { data: n }); + }), + (this.start = function (e) { + (this.currentLine = Math.min( + e || 0, + this.currentLine, + this.doc.getLength(), + )), + this.lines.splice(this.currentLine, this.lines.length), + this.states.splice(this.currentLine, this.states.length), + this.stop(), + (this.running = setTimeout(this.$worker, 700)); + }), + (this.scheduleStart = function () { + this.running || (this.running = setTimeout(this.$worker, 700)); + }), + (this.$updateOnChange = function (e) { + var t = e.start.row, + n = e.end.row - t; + if (n === 0) this.lines[t] = null; + else if (e.action == "remove") + this.lines.splice(t, n + 1, null), this.states.splice(t, n + 1, null); + else { + var r = Array(n + 1); + r.unshift(t, 1), + this.lines.splice.apply(this.lines, r), + this.states.splice.apply(this.states, r); + } + (this.currentLine = Math.min(t, this.currentLine, this.doc.getLength())), + this.stop(); + }), + (this.stop = function () { + this.running && clearTimeout(this.running), (this.running = !1); + }), + (this.getTokens = function (e) { + return this.lines[e] || this.$tokenizeRow(e); + }), + (this.getState = function (e) { + return ( + this.currentLine == e && this.$tokenizeRow(e), this.states[e] || "start" + ); + }), + (this.$tokenizeRow = function (e) { + var t = this.doc.getLine(e), + n = this.states[e - 1], + r = this.tokenizer.getLineTokens(t, n, e); + return ( + this.states[e] + "" != r.state + "" + ? ((this.states[e] = r.state), + (this.lines[e + 1] = null), + this.currentLine > e + 1 && (this.currentLine = e + 1)) + : this.currentLine == e && (this.currentLine = e + 1), + (this.lines[e] = r.tokens) + ); + }); + }).call(s.prototype), + (t.BackgroundTokenizer = s); + }, + ), + define( + "ace/search_highlight", + ["require", "exports", "module", "ace/lib/lang", "ace/lib/oop", "ace/range"], + function (e, t, n) { + "use strict"; + var r = e("./lib/lang"), + i = e("./lib/oop"), + s = e("./range").Range, + o = function (e, t, n) { + this.setRegexp(e), (this.clazz = t), (this.type = n || "text"); + }; + (function () { + (this.MAX_RANGES = 500), + (this.setRegexp = function (e) { + if (this.regExp + "" == e + "") return; + (this.regExp = e), (this.cache = []); + }), + (this.update = function (e, t, n, i) { + if (!this.regExp) return; + var o = i.firstRow, + u = i.lastRow; + for (var a = o; a <= u; a++) { + var f = this.cache[a]; + f == null && + ((f = r.getMatchOffsets(n.getLine(a), this.regExp)), + f.length > this.MAX_RANGES && (f = f.slice(0, this.MAX_RANGES)), + (f = f.map(function (e) { + return new s(a, e.offset, a, e.offset + e.length); + })), + (this.cache[a] = f.length ? f : "")); + for (var l = f.length; l--; ) + t.drawSingleLineMarker(e, f[l].toScreenRange(n), this.clazz, i); + } + }); + }).call(o.prototype), + (t.SearchHighlight = o); + }, + ), + define( + "ace/edit_session/fold_line", + ["require", "exports", "module", "ace/range"], + function (e, t, n) { + "use strict"; + function i(e, t) { + (this.foldData = e), Array.isArray(t) ? (this.folds = t) : (t = this.folds = [t]); + var n = t[t.length - 1]; + (this.range = new r(t[0].start.row, t[0].start.column, n.end.row, n.end.column)), + (this.start = this.range.start), + (this.end = this.range.end), + this.folds.forEach(function (e) { + e.setFoldLine(this); + }, this); + } + var r = e("../range").Range; + (function () { + (this.shiftRow = function (e) { + (this.start.row += e), + (this.end.row += e), + this.folds.forEach(function (t) { + (t.start.row += e), (t.end.row += e); + }); + }), + (this.addFold = function (e) { + if (e.sameRow) { + if (e.start.row < this.startRow || e.endRow > this.endRow) + throw new Error( + "Can't add a fold to this FoldLine as it has no connection", + ); + this.folds.push(e), + this.folds.sort(function (e, t) { + return -e.range.compareEnd(t.start.row, t.start.column); + }), + this.range.compareEnd(e.start.row, e.start.column) > 0 + ? ((this.end.row = e.end.row), (this.end.column = e.end.column)) + : this.range.compareStart(e.end.row, e.end.column) < 0 && + ((this.start.row = e.start.row), + (this.start.column = e.start.column)); + } else if (e.start.row == this.end.row) + this.folds.push(e), + (this.end.row = e.end.row), + (this.end.column = e.end.column); + else { + if (e.end.row != this.start.row) + throw new Error( + "Trying to add fold to FoldRow that doesn't have a matching row", + ); + this.folds.unshift(e), + (this.start.row = e.start.row), + (this.start.column = e.start.column); + } + e.foldLine = this; + }), + (this.containsRow = function (e) { + return e >= this.start.row && e <= this.end.row; + }), + (this.walk = function (e, t, n) { + var r = 0, + i = this.folds, + s, + o, + u, + a = !0; + t == null && ((t = this.end.row), (n = this.end.column)); + for (var f = 0; f < i.length; f++) { + (s = i[f]), (o = s.range.compareStart(t, n)); + if (o == -1) { + e(null, t, n, r, a); + return; + } + (u = e(null, s.start.row, s.start.column, r, a)), + (u = !u && e(s.placeholder, s.start.row, s.start.column, r)); + if (u || o === 0) return; + (a = !s.sameRow), (r = s.end.column); + } + e(null, t, n, r, a); + }), + (this.getNextFoldTo = function (e, t) { + var n, r; + for (var i = 0; i < this.folds.length; i++) { + (n = this.folds[i]), (r = n.range.compareEnd(e, t)); + if (r == -1) return { fold: n, kind: "after" }; + if (r === 0) return { fold: n, kind: "inside" }; + } + return null; + }), + (this.addRemoveChars = function (e, t, n) { + var r = this.getNextFoldTo(e, t), + i, + s; + if (r) { + i = r.fold; + if (r.kind == "inside" && i.start.column != t && i.start.row != e) + window.console && window.console.log(e, t, i); + else if (i.start.row == e) { + s = this.folds; + var o = s.indexOf(i); + o === 0 && (this.start.column += n); + for (o; o < s.length; o++) { + (i = s[o]), (i.start.column += n); + if (!i.sameRow) return; + i.end.column += n; + } + this.end.column += n; + } + } + }), + (this.split = function (e, t) { + var n = this.getNextFoldTo(e, t); + if (!n || n.kind == "inside") return null; + var r = n.fold, + s = this.folds, + o = this.foldData, + u = s.indexOf(r), + a = s[u - 1]; + (this.end.row = a.end.row), + (this.end.column = a.end.column), + (s = s.splice(u, s.length - u)); + var f = new i(o, s); + return o.splice(o.indexOf(this) + 1, 0, f), f; + }), + (this.merge = function (e) { + var t = e.folds; + for (var n = 0; n < t.length; n++) this.addFold(t[n]); + var r = this.foldData; + r.splice(r.indexOf(e), 1); + }), + (this.toString = function () { + var e = [this.range.toString() + ": ["]; + return ( + this.folds.forEach(function (t) { + e.push(" " + t.toString()); + }), + e.push("]"), + e.join("\n") + ); + }), + (this.idxToPosition = function (e) { + var t = 0; + for (var n = 0; n < this.folds.length; n++) { + var r = this.folds[n]; + e -= r.start.column - t; + if (e < 0) return { row: r.start.row, column: r.start.column + e }; + e -= r.placeholder.length; + if (e < 0) return r.start; + t = r.end.column; + } + return { row: this.end.row, column: this.end.column + e }; + }); + }).call(i.prototype), + (t.FoldLine = i); + }, + ), + define("ace/range_list", ["require", "exports", "module", "ace/range"], function (e, t, n) { + "use strict"; + var r = e("./range").Range, + i = r.comparePoints, + s = function () { + this.ranges = []; + }; + (function () { + (this.comparePoints = i), + (this.pointIndex = function (e, t, n) { + var r = this.ranges; + for (var s = n || 0; s < r.length; s++) { + var o = r[s], + u = i(e, o.end); + if (u > 0) continue; + var a = i(e, o.start); + return u === 0 + ? t && a !== 0 + ? -s - 2 + : s + : a > 0 || (a === 0 && !t) + ? s + : -s - 1; + } + return -s - 1; + }), + (this.add = function (e) { + var t = !e.isEmpty(), + n = this.pointIndex(e.start, t); + n < 0 && (n = -n - 1); + var r = this.pointIndex(e.end, t, n); + return r < 0 ? (r = -r - 1) : r++, this.ranges.splice(n, r - n, e); + }), + (this.addList = function (e) { + var t = []; + for (var n = e.length; n--; ) t.push.apply(t, this.add(e[n])); + return t; + }), + (this.substractPoint = function (e) { + var t = this.pointIndex(e); + if (t >= 0) return this.ranges.splice(t, 1); + }), + (this.merge = function () { + var e = [], + t = this.ranges; + t = t.sort(function (e, t) { + return i(e.start, t.start); + }); + var n = t[0], + r; + for (var s = 1; s < t.length; s++) { + (r = n), (n = t[s]); + var o = i(r.end, n.start); + if (o < 0) continue; + if (o == 0 && !r.isEmpty() && !n.isEmpty()) continue; + i(r.end, n.end) < 0 && + ((r.end.row = n.end.row), (r.end.column = n.end.column)), + t.splice(s, 1), + e.push(n), + (n = r), + s--; + } + return (this.ranges = t), e; + }), + (this.contains = function (e, t) { + return this.pointIndex({ row: e, column: t }) >= 0; + }), + (this.containsPoint = function (e) { + return this.pointIndex(e) >= 0; + }), + (this.rangeAtPoint = function (e) { + var t = this.pointIndex(e); + if (t >= 0) return this.ranges[t]; + }), + (this.clipRows = function (e, t) { + var n = this.ranges; + if (n[0].start.row > t || n[n.length - 1].start.row < e) return []; + var r = this.pointIndex({ row: e, column: 0 }); + r < 0 && (r = -r - 1); + var i = this.pointIndex({ row: t, column: 0 }, r); + i < 0 && (i = -i - 1); + var s = []; + for (var o = r; o < i; o++) s.push(n[o]); + return s; + }), + (this.removeAll = function () { + return this.ranges.splice(0, this.ranges.length); + }), + (this.attach = function (e) { + this.session && this.detach(), + (this.session = e), + (this.onChange = this.$onChange.bind(this)), + this.session.on("change", this.onChange); + }), + (this.detach = function () { + if (!this.session) return; + this.session.removeListener("change", this.onChange), (this.session = null); + }), + (this.$onChange = function (e) { + var t = e.start, + n = e.end, + r = t.row, + i = n.row, + s = this.ranges; + for (var o = 0, u = s.length; o < u; o++) { + var a = s[o]; + if (a.end.row >= r) break; + } + if (e.action == "insert") { + var f = i - r, + l = -t.column + n.column; + for (; o < u; o++) { + var a = s[o]; + if (a.start.row > r) break; + a.start.row == r && + a.start.column >= t.column && + (a.start.column != t.column || !this.$insertRight) && + ((a.start.column += l), (a.start.row += f)); + if (a.end.row == r && a.end.column >= t.column) { + if (a.end.column == t.column && this.$insertRight) continue; + a.end.column == t.column && + l > 0 && + o < u - 1 && + a.end.column > a.start.column && + a.end.column == s[o + 1].start.column && + (a.end.column -= l), + (a.end.column += l), + (a.end.row += f); + } + } + } else { + var f = r - i, + l = t.column - n.column; + for (; o < u; o++) { + var a = s[o]; + if (a.start.row > i) break; + a.end.row < i && ((a.end.row = r), (a.end.column = t.column)); + if (a.start.row < i || (a.start.row == i && a.start.column <= n.colum)) + (a.start.row = r), (a.start.column = t.column); + if (a.end.row == i) + if (a.end.column <= n.column) { + if (f || a.end.column > t.column) + (a.end.column = t.column), (a.end.row = t.row); + } else (a.end.column += l), (a.end.row += f); + if (a.start.row == i) + if (a.start.column <= n.column) { + if (f || a.start.column > t.column) + (a.start.column = t.column), (a.start.row = t.row); + } else (a.start.column += l), (a.start.row += f); + } + } + if (f != 0 && o < u) + for (; o < u; o++) { + var a = s[o]; + (a.start.row += f), (a.end.row += f); + } + }); + }).call(s.prototype), + (t.RangeList = s); + }), + define( + "ace/edit_session/fold", + ["require", "exports", "module", "ace/range", "ace/range_list", "ace/lib/oop"], + function (e, t, n) { + "use strict"; + function u(e, t) { + (e.row -= t.row), e.row == 0 && (e.column -= t.column); + } + function a(e, t) { + u(e.start, t), u(e.end, t); + } + function f(e, t) { + e.row == 0 && (e.column += t.column), (e.row += t.row); + } + function l(e, t) { + f(e.start, t), f(e.end, t); + } + var r = e("../range").Range, + i = e("../range_list").RangeList, + s = e("../lib/oop"), + o = (t.Fold = function (e, t) { + (this.foldLine = null), + (this.placeholder = t), + (this.range = e), + (this.start = e.start), + (this.end = e.end), + (this.sameRow = e.start.row == e.end.row), + (this.subFolds = this.ranges = []); + }); + s.inherits(o, i), + function () { + (this.toString = function () { + return '"' + this.placeholder + '" ' + this.range.toString(); + }), + (this.setFoldLine = function (e) { + (this.foldLine = e), + this.subFolds.forEach(function (t) { + t.setFoldLine(e); + }); + }), + (this.clone = function () { + var e = this.range.clone(), + t = new o(e, this.placeholder); + return ( + this.subFolds.forEach(function (e) { + t.subFolds.push(e.clone()); + }), + (t.collapseChildren = this.collapseChildren), + t + ); + }), + (this.addSubFold = function (e) { + if (this.range.isEqual(e)) return; + if (!this.range.containsRange(e)) + throw new Error( + "A fold can't intersect already existing fold" + + e.range + + this.range, + ); + a(e, this.start); + var t = e.start.row, + n = e.start.column; + for (var r = 0, i = -1; r < this.subFolds.length; r++) { + i = this.subFolds[r].range.compare(t, n); + if (i != 1) break; + } + var s = this.subFolds[r]; + if (i == 0) return s.addSubFold(e); + var t = e.range.end.row, + n = e.range.end.column; + for (var o = r, i = -1; o < this.subFolds.length; o++) { + i = this.subFolds[o].range.compare(t, n); + if (i != 1) break; + } + var u = this.subFolds[o]; + if (i == 0) + throw new Error( + "A fold can't intersect already existing fold" + + e.range + + this.range, + ); + var f = this.subFolds.splice(r, o - r, e); + return e.setFoldLine(this.foldLine), e; + }), + (this.restoreRange = function (e) { + return l(e, this.start); + }); + }.call(o.prototype); + }, + ), + define( + "ace/edit_session/folding", + [ + "require", + "exports", + "module", + "ace/range", + "ace/edit_session/fold_line", + "ace/edit_session/fold", + "ace/token_iterator", + ], + function (e, t, n) { + "use strict"; + function u() { + (this.getFoldAt = function (e, t, n) { + var r = this.getFoldLine(e); + if (!r) return null; + var i = r.folds; + for (var s = 0; s < i.length; s++) { + var o = i[s]; + if (o.range.contains(e, t)) { + if (n == 1 && o.range.isEnd(e, t)) continue; + if (n == -1 && o.range.isStart(e, t)) continue; + return o; + } + } + }), + (this.getFoldsInRange = function (e) { + var t = e.start, + n = e.end, + r = this.$foldData, + i = []; + (t.column += 1), (n.column -= 1); + for (var s = 0; s < r.length; s++) { + var o = r[s].range.compareRange(e); + if (o == 2) continue; + if (o == -2) break; + var u = r[s].folds; + for (var a = 0; a < u.length; a++) { + var f = u[a]; + o = f.range.compareRange(e); + if (o == -2) break; + if (o == 2) continue; + if (o == 42) break; + i.push(f); + } + } + return (t.column -= 1), (n.column += 1), i; + }), + (this.getFoldsInRangeList = function (e) { + if (Array.isArray(e)) { + var t = []; + e.forEach(function (e) { + t = t.concat(this.getFoldsInRange(e)); + }, this); + } else var t = this.getFoldsInRange(e); + return t; + }), + (this.getAllFolds = function () { + var e = [], + t = this.$foldData; + for (var n = 0; n < t.length; n++) + for (var r = 0; r < t[n].folds.length; r++) e.push(t[n].folds[r]); + return e; + }), + (this.getFoldStringAt = function (e, t, n, r) { + r = r || this.getFoldLine(e); + if (!r) return null; + var i = { end: { column: 0 } }, + s, + o; + for (var u = 0; u < r.folds.length; u++) { + o = r.folds[u]; + var a = o.range.compareEnd(e, t); + if (a == -1) { + s = this.getLine(o.start.row).substring( + i.end.column, + o.start.column, + ); + break; + } + if (a === 0) return null; + i = o; + } + return ( + s || (s = this.getLine(o.start.row).substring(i.end.column)), + n == -1 + ? s.substring(0, t - i.end.column) + : n == 1 + ? s.substring(t - i.end.column) + : s + ); + }), + (this.getFoldLine = function (e, t) { + var n = this.$foldData, + r = 0; + t && (r = n.indexOf(t)), r == -1 && (r = 0); + for (r; r < n.length; r++) { + var i = n[r]; + if (i.start.row <= e && i.end.row >= e) return i; + if (i.end.row > e) return null; + } + return null; + }), + (this.getNextFoldLine = function (e, t) { + var n = this.$foldData, + r = 0; + t && (r = n.indexOf(t)), r == -1 && (r = 0); + for (r; r < n.length; r++) { + var i = n[r]; + if (i.end.row >= e) return i; + } + return null; + }), + (this.getFoldedRowCount = function (e, t) { + var n = this.$foldData, + r = t - e + 1; + for (var i = 0; i < n.length; i++) { + var s = n[i], + o = s.end.row, + u = s.start.row; + if (o >= t) { + u < t && (u >= e ? (r -= t - u) : (r = 0)); + break; + } + o >= e && (u >= e ? (r -= o - u) : (r -= o - e + 1)); + } + return r; + }), + (this.$addFoldLine = function (e) { + return ( + this.$foldData.push(e), + this.$foldData.sort(function (e, t) { + return e.start.row - t.start.row; + }), + e + ); + }), + (this.addFold = function (e, t) { + var n = this.$foldData, + r = !1, + o; + e instanceof s + ? (o = e) + : ((o = new s(t, e)), (o.collapseChildren = t.collapseChildren)), + this.$clipRangeToDocument(o.range); + var u = o.start.row, + a = o.start.column, + f = o.end.row, + l = o.end.column; + if (u < f || (u == f && a <= l - 2)) { + var c = this.getFoldAt(u, a, 1), + h = this.getFoldAt(f, l, -1); + if (c && h == c) return c.addSubFold(o); + c && !c.range.isStart(u, a) && this.removeFold(c), + h && !h.range.isEnd(f, l) && this.removeFold(h); + var p = this.getFoldsInRange(o.range); + p.length > 0 && + (this.removeFolds(p), + p.forEach(function (e) { + o.addSubFold(e); + })); + for (var d = 0; d < n.length; d++) { + var v = n[d]; + if (f == v.start.row) { + v.addFold(o), (r = !0); + break; + } + if (u == v.end.row) { + v.addFold(o), (r = !0); + if (!o.sameRow) { + var m = n[d + 1]; + if (m && m.start.row == f) { + v.merge(m); + break; + } + } + break; + } + if (f <= v.start.row) break; + } + return ( + r || (v = this.$addFoldLine(new i(this.$foldData, o))), + this.$useWrapMode + ? this.$updateWrapData(v.start.row, v.start.row) + : this.$updateRowLengthCache(v.start.row, v.start.row), + (this.$modified = !0), + this._signal("changeFold", { data: o, action: "add" }), + o + ); + } + throw new Error("The range has to be at least 2 characters width"); + }), + (this.addFolds = function (e) { + e.forEach(function (e) { + this.addFold(e); + }, this); + }), + (this.removeFold = function (e) { + var t = e.foldLine, + n = t.start.row, + r = t.end.row, + i = this.$foldData, + s = t.folds; + if (s.length == 1) i.splice(i.indexOf(t), 1); + else if (t.range.isEnd(e.end.row, e.end.column)) + s.pop(), + (t.end.row = s[s.length - 1].end.row), + (t.end.column = s[s.length - 1].end.column); + else if (t.range.isStart(e.start.row, e.start.column)) + s.shift(), + (t.start.row = s[0].start.row), + (t.start.column = s[0].start.column); + else if (e.sameRow) s.splice(s.indexOf(e), 1); + else { + var o = t.split(e.start.row, e.start.column); + (s = o.folds), + s.shift(), + (o.start.row = s[0].start.row), + (o.start.column = s[0].start.column); + } + this.$updating || + (this.$useWrapMode + ? this.$updateWrapData(n, r) + : this.$updateRowLengthCache(n, r)), + (this.$modified = !0), + this._signal("changeFold", { data: e, action: "remove" }); + }), + (this.removeFolds = function (e) { + var t = []; + for (var n = 0; n < e.length; n++) t.push(e[n]); + t.forEach(function (e) { + this.removeFold(e); + }, this), + (this.$modified = !0); + }), + (this.expandFold = function (e) { + this.removeFold(e), + e.subFolds.forEach(function (t) { + e.restoreRange(t), this.addFold(t); + }, this), + e.collapseChildren > 0 && + this.foldAll(e.start.row + 1, e.end.row, e.collapseChildren - 1), + (e.subFolds = []); + }), + (this.expandFolds = function (e) { + e.forEach(function (e) { + this.expandFold(e); + }, this); + }), + (this.unfold = function (e, t) { + var n, i; + e == null + ? ((n = new r(0, 0, this.getLength(), 0)), (t = !0)) + : typeof e == "number" + ? (n = new r(e, 0, e, this.getLine(e).length)) + : "row" in e + ? (n = r.fromPoints(e, e)) + : (n = e), + (i = this.getFoldsInRangeList(n)); + if (t) this.removeFolds(i); + else { + var s = i; + while (s.length) this.expandFolds(s), (s = this.getFoldsInRangeList(n)); + } + if (i.length) return i; + }), + (this.isRowFolded = function (e, t) { + return !!this.getFoldLine(e, t); + }), + (this.getRowFoldEnd = function (e, t) { + var n = this.getFoldLine(e, t); + return n ? n.end.row : e; + }), + (this.getRowFoldStart = function (e, t) { + var n = this.getFoldLine(e, t); + return n ? n.start.row : e; + }), + (this.getFoldDisplayLine = function (e, t, n, r, i) { + r == null && (r = e.start.row), + i == null && (i = 0), + t == null && (t = e.end.row), + n == null && (n = this.getLine(t).length); + var s = this.doc, + o = ""; + return ( + e.walk( + function (e, t, n, u) { + if (t < r) return; + if (t == r) { + if (n < i) return; + u = Math.max(i, u); + } + e != null ? (o += e) : (o += s.getLine(t).substring(u, n)); + }, + t, + n, + ), + o + ); + }), + (this.getDisplayLine = function (e, t, n, r) { + var i = this.getFoldLine(e); + if (!i) { + var s; + return (s = this.doc.getLine(e)), s.substring(r || 0, t || s.length); + } + return this.getFoldDisplayLine(i, e, t, n, r); + }), + (this.$cloneFoldData = function () { + var e = []; + return ( + (e = this.$foldData.map(function (t) { + var n = t.folds.map(function (e) { + return e.clone(); + }); + return new i(e, n); + })), + e + ); + }), + (this.toggleFold = function (e) { + var t = this.selection, + n = t.getRange(), + r, + i; + if (n.isEmpty()) { + var s = n.start; + r = this.getFoldAt(s.row, s.column); + if (r) { + this.expandFold(r); + return; + } + (i = this.findMatchingBracket(s)) + ? n.comparePoint(i) == 1 + ? (n.end = i) + : ((n.start = i), n.start.column++, n.end.column--) + : (i = this.findMatchingBracket({ + row: s.row, + column: s.column + 1, + })) + ? (n.comparePoint(i) == 1 ? (n.end = i) : (n.start = i), + n.start.column++) + : (n = this.getCommentFoldRange(s.row, s.column) || n); + } else { + var o = this.getFoldsInRange(n); + if (e && o.length) { + this.expandFolds(o); + return; + } + o.length == 1 && (r = o[0]); + } + r || (r = this.getFoldAt(n.start.row, n.start.column)); + if (r && r.range.toString() == n.toString()) { + this.expandFold(r); + return; + } + var u = "..."; + if (!n.isMultiLine()) { + u = this.getTextRange(n); + if (u.length < 4) return; + u = u.trim().substring(0, 2) + ".."; + } + this.addFold(u, n); + }), + (this.getCommentFoldRange = function (e, t, n) { + var i = new o(this, e, t), + s = i.getCurrentToken(), + u = s.type; + if (s && /^comment|string/.test(u)) { + (u = u.match(/comment|string/)[0]), + u == "comment" && (u += "|doc-start"); + var a = new RegExp(u), + f = new r(); + if (n != 1) { + do s = i.stepBackward(); + while (s && a.test(s.type)); + i.stepForward(); + } + (f.start.row = i.getCurrentTokenRow()), + (f.start.column = i.getCurrentTokenColumn() + 2), + (i = new o(this, e, t)); + if (n != -1) { + var l = -1; + do { + s = i.stepForward(); + if (l == -1) { + var c = this.getState(i.$row); + a.test(c) || (l = i.$row); + } else if (i.$row > l) break; + } while (s && a.test(s.type)); + s = i.stepBackward(); + } else s = i.getCurrentToken(); + return ( + (f.end.row = i.getCurrentTokenRow()), + (f.end.column = i.getCurrentTokenColumn() + s.value.length - 2), + f + ); + } + }), + (this.foldAll = function (e, t, n) { + n == undefined && (n = 1e5); + var r = this.foldWidgets; + if (!r) return; + (t = t || this.getLength()), (e = e || 0); + for (var i = e; i < t; i++) { + r[i] == null && (r[i] = this.getFoldWidget(i)); + if (r[i] != "start") continue; + var s = this.getFoldWidgetRange(i); + if (s && s.isMultiLine() && s.end.row <= t && s.start.row >= e) { + i = s.end.row; + try { + var o = this.addFold("...", s); + o && (o.collapseChildren = n); + } catch (u) {} + } + } + }), + (this.$foldStyles = { manual: 1, markbegin: 1, markbeginend: 1 }), + (this.$foldStyle = "markbegin"), + (this.setFoldStyle = function (e) { + if (!this.$foldStyles[e]) + throw new Error( + "invalid fold style: " + + e + + "[" + + Object.keys(this.$foldStyles).join(", ") + + "]", + ); + if (this.$foldStyle == e) return; + (this.$foldStyle = e), e == "manual" && this.unfold(); + var t = this.$foldMode; + this.$setFolding(null), this.$setFolding(t); + }), + (this.$setFolding = function (e) { + if (this.$foldMode == e) return; + (this.$foldMode = e), + this.off("change", this.$updateFoldWidgets), + this.off("tokenizerUpdate", this.$tokenizerUpdateFoldWidgets), + this._signal("changeAnnotation"); + if (!e || this.$foldStyle == "manual") { + this.foldWidgets = null; + return; + } + (this.foldWidgets = []), + (this.getFoldWidget = e.getFoldWidget.bind(e, this, this.$foldStyle)), + (this.getFoldWidgetRange = e.getFoldWidgetRange.bind( + e, + this, + this.$foldStyle, + )), + (this.$updateFoldWidgets = this.updateFoldWidgets.bind(this)), + (this.$tokenizerUpdateFoldWidgets = + this.tokenizerUpdateFoldWidgets.bind(this)), + this.on("change", this.$updateFoldWidgets), + this.on("tokenizerUpdate", this.$tokenizerUpdateFoldWidgets); + }), + (this.getParentFoldRangeData = function (e, t) { + var n = this.foldWidgets; + if (!n || (t && n[e])) return {}; + var r = e - 1, + i; + while (r >= 0) { + var s = n[r]; + s == null && (s = n[r] = this.getFoldWidget(r)); + if (s == "start") { + var o = this.getFoldWidgetRange(r); + i || (i = o); + if (o && o.end.row >= e) break; + } + r--; + } + return { range: r !== -1 && o, firstRange: i }; + }), + (this.onFoldWidgetClick = function (e, t) { + t = t.domEvent; + var n = { + children: t.shiftKey, + all: t.ctrlKey || t.metaKey, + siblings: t.altKey, + }, + r = this.$toggleFoldWidget(e, n); + if (!r) { + var i = t.target || t.srcElement; + i && + /ace_fold-widget/.test(i.className) && + (i.className += " ace_invalid"); + } + }), + (this.$toggleFoldWidget = function (e, t) { + if (!this.getFoldWidget) return; + var n = this.getFoldWidget(e), + r = this.getLine(e), + i = n === "end" ? -1 : 1, + s = this.getFoldAt(e, i === -1 ? 0 : r.length, i); + if (s) + return t.children || t.all ? this.removeFold(s) : this.expandFold(s), s; + var o = this.getFoldWidgetRange(e, !0); + if (o && !o.isMultiLine()) { + s = this.getFoldAt(o.start.row, o.start.column, 1); + if (s && o.isEqual(s.range)) return this.removeFold(s), s; + } + if (t.siblings) { + var u = this.getParentFoldRangeData(e); + if (u.range) + var a = u.range.start.row + 1, + f = u.range.end.row; + this.foldAll(a, f, t.all ? 1e4 : 0); + } else + t.children + ? ((f = o ? o.end.row : this.getLength()), + this.foldAll(e + 1, f, t.all ? 1e4 : 0)) + : o && + (t.all && (o.collapseChildren = 1e4), this.addFold("...", o)); + return o; + }), + (this.toggleFoldWidget = function (e) { + var t = this.selection.getCursor().row; + t = this.getRowFoldStart(t); + var n = this.$toggleFoldWidget(t, {}); + if (n) return; + var r = this.getParentFoldRangeData(t, !0); + n = r.range || r.firstRange; + if (n) { + t = n.start.row; + var i = this.getFoldAt(t, this.getLine(t).length, 1); + i ? this.removeFold(i) : this.addFold("...", n); + } + }), + (this.updateFoldWidgets = function (e) { + var t = e.start.row, + n = e.end.row - t; + if (n === 0) this.foldWidgets[t] = null; + else if (e.action == "remove") this.foldWidgets.splice(t, n + 1, null); + else { + var r = Array(n + 1); + r.unshift(t, 1), this.foldWidgets.splice.apply(this.foldWidgets, r); + } + }), + (this.tokenizerUpdateFoldWidgets = function (e) { + var t = e.data; + t.first != t.last && + this.foldWidgets.length > t.first && + this.foldWidgets.splice(t.first, this.foldWidgets.length); + }); + } + var r = e("../range").Range, + i = e("./fold_line").FoldLine, + s = e("./fold").Fold, + o = e("../token_iterator").TokenIterator; + t.Folding = u; + }, + ), + define( + "ace/edit_session/bracket_match", + ["require", "exports", "module", "ace/token_iterator", "ace/range"], + function (e, t, n) { + "use strict"; + function s() { + (this.findMatchingBracket = function (e, t) { + if (e.column == 0) return null; + var n = t || this.getLine(e.row).charAt(e.column - 1); + if (n == "") return null; + var r = n.match(/([\(\[\{])|([\)\]\}])/); + return r + ? r[1] + ? this.$findClosingBracket(r[1], e) + : this.$findOpeningBracket(r[2], e) + : null; + }), + (this.getBracketRange = function (e) { + var t = this.getLine(e.row), + n = !0, + r, + s = t.charAt(e.column - 1), + o = s && s.match(/([\(\[\{])|([\)\]\}])/); + o || + ((s = t.charAt(e.column)), + (e = { row: e.row, column: e.column + 1 }), + (o = s && s.match(/([\(\[\{])|([\)\]\}])/)), + (n = !1)); + if (!o) return null; + if (o[1]) { + var u = this.$findClosingBracket(o[1], e); + if (!u) return null; + (r = i.fromPoints(e, u)), + n || (r.end.column++, r.start.column--), + (r.cursor = r.end); + } else { + var u = this.$findOpeningBracket(o[2], e); + if (!u) return null; + (r = i.fromPoints(u, e)), + n || (r.start.column++, r.end.column--), + (r.cursor = r.start); + } + return r; + }), + (this.$brackets = { + ")": "(", + "(": ")", + "]": "[", + "[": "]", + "{": "}", + "}": "{", + }), + (this.$findOpeningBracket = function (e, t, n) { + var i = this.$brackets[e], + s = 1, + o = new r(this, t.row, t.column), + u = o.getCurrentToken(); + u || (u = o.stepForward()); + if (!u) return; + n || + (n = new RegExp( + "(\\.?" + + u.type + .replace(".", "\\.") + .replace("rparen", ".paren") + .replace(/\b(?:end)\b/, "(?:start|begin|end)") + + ")+", + )); + var a = t.column - o.getCurrentTokenColumn() - 2, + f = u.value; + for (;;) { + while (a >= 0) { + var l = f.charAt(a); + if (l == i) { + s -= 1; + if (s == 0) + return { + row: o.getCurrentTokenRow(), + column: a + o.getCurrentTokenColumn(), + }; + } else l == e && (s += 1); + a -= 1; + } + do u = o.stepBackward(); + while (u && !n.test(u.type)); + if (u == null) break; + (f = u.value), (a = f.length - 1); + } + return null; + }), + (this.$findClosingBracket = function (e, t, n) { + var i = this.$brackets[e], + s = 1, + o = new r(this, t.row, t.column), + u = o.getCurrentToken(); + u || (u = o.stepForward()); + if (!u) return; + n || + (n = new RegExp( + "(\\.?" + + u.type + .replace(".", "\\.") + .replace("lparen", ".paren") + .replace(/\b(?:start|begin)\b/, "(?:start|begin|end)") + + ")+", + )); + var a = t.column - o.getCurrentTokenColumn(); + for (;;) { + var f = u.value, + l = f.length; + while (a < l) { + var c = f.charAt(a); + if (c == i) { + s -= 1; + if (s == 0) + return { + row: o.getCurrentTokenRow(), + column: a + o.getCurrentTokenColumn(), + }; + } else c == e && (s += 1); + a += 1; + } + do u = o.stepForward(); + while (u && !n.test(u.type)); + if (u == null) break; + a = 0; + } + return null; + }); + } + var r = e("../token_iterator").TokenIterator, + i = e("../range").Range; + t.BracketMatch = s; + }, + ), + define( + "ace/edit_session", + [ + "require", + "exports", + "module", + "ace/lib/oop", + "ace/lib/lang", + "ace/bidihandler", + "ace/config", + "ace/lib/event_emitter", + "ace/selection", + "ace/mode/text", + "ace/range", + "ace/document", + "ace/background_tokenizer", + "ace/search_highlight", + "ace/edit_session/folding", + "ace/edit_session/bracket_match", + ], + function (e, t, n) { + "use strict"; + var r = e("./lib/oop"), + i = e("./lib/lang"), + s = e("./bidihandler").BidiHandler, + o = e("./config"), + u = e("./lib/event_emitter").EventEmitter, + a = e("./selection").Selection, + f = e("./mode/text").Mode, + l = e("./range").Range, + c = e("./document").Document, + h = e("./background_tokenizer").BackgroundTokenizer, + p = e("./search_highlight").SearchHighlight, + d = function (e, t) { + (this.$breakpoints = []), + (this.$decorations = []), + (this.$frontMarkers = {}), + (this.$backMarkers = {}), + (this.$markerId = 1), + (this.$undoSelect = !0), + (this.$foldData = []), + (this.id = "session" + ++d.$uid), + (this.$foldData.toString = function () { + return this.join("\n"); + }), + this.on("changeFold", this.onChangeFold.bind(this)), + (this.$onChange = this.onChange.bind(this)); + if (typeof e != "object" || !e.getLine) e = new c(e); + this.setDocument(e), + (this.selection = new a(this)), + (this.$bidiHandler = new s(this)), + o.resetOptions(this), + this.setMode(t), + o._signal("session", this); + }; + (d.$uid = 0), + function () { + function m(e) { + return e < 4352 + ? !1 + : (e >= 4352 && e <= 4447) || + (e >= 4515 && e <= 4519) || + (e >= 4602 && e <= 4607) || + (e >= 9001 && e <= 9002) || + (e >= 11904 && e <= 11929) || + (e >= 11931 && e <= 12019) || + (e >= 12032 && e <= 12245) || + (e >= 12272 && e <= 12283) || + (e >= 12288 && e <= 12350) || + (e >= 12353 && e <= 12438) || + (e >= 12441 && e <= 12543) || + (e >= 12549 && e <= 12589) || + (e >= 12593 && e <= 12686) || + (e >= 12688 && e <= 12730) || + (e >= 12736 && e <= 12771) || + (e >= 12784 && e <= 12830) || + (e >= 12832 && e <= 12871) || + (e >= 12880 && e <= 13054) || + (e >= 13056 && e <= 19903) || + (e >= 19968 && e <= 42124) || + (e >= 42128 && e <= 42182) || + (e >= 43360 && e <= 43388) || + (e >= 44032 && e <= 55203) || + (e >= 55216 && e <= 55238) || + (e >= 55243 && e <= 55291) || + (e >= 63744 && e <= 64255) || + (e >= 65040 && e <= 65049) || + (e >= 65072 && e <= 65106) || + (e >= 65108 && e <= 65126) || + (e >= 65128 && e <= 65131) || + (e >= 65281 && e <= 65376) || + (e >= 65504 && e <= 65510); + } + r.implement(this, u), + (this.setDocument = function (e) { + this.doc && this.doc.removeListener("change", this.$onChange), + (this.doc = e), + e.on("change", this.$onChange), + this.bgTokenizer && + this.bgTokenizer.setDocument(this.getDocument()), + this.resetCaches(); + }), + (this.getDocument = function () { + return this.doc; + }), + (this.$resetRowCache = function (e) { + if (!e) { + (this.$docRowCache = []), (this.$screenRowCache = []); + return; + } + var t = this.$docRowCache.length, + n = this.$getRowCacheIndex(this.$docRowCache, e) + 1; + t > n && + (this.$docRowCache.splice(n, t), this.$screenRowCache.splice(n, t)); + }), + (this.$getRowCacheIndex = function (e, t) { + var n = 0, + r = e.length - 1; + while (n <= r) { + var i = (n + r) >> 1, + s = e[i]; + if (t > s) n = i + 1; + else { + if (!(t < s)) return i; + r = i - 1; + } + } + return n - 1; + }), + (this.resetCaches = function () { + (this.$modified = !0), + (this.$wrapData = []), + (this.$rowLengthCache = []), + this.$resetRowCache(0), + this.bgTokenizer && this.bgTokenizer.start(0); + }), + (this.onChangeFold = function (e) { + var t = e.data; + this.$resetRowCache(t.start.row); + }), + (this.onChange = function (e) { + (this.$modified = !0), + this.$bidiHandler.onChange(e), + this.$resetRowCache(e.start.row); + var t = this.$updateInternalDataOnChange(e); + !this.$fromUndo && + this.$undoManager && + (t && + t.length && + (this.$undoManager.add( + { action: "removeFolds", folds: t }, + this.mergeUndoDeltas, + ), + (this.mergeUndoDeltas = !0)), + this.$undoManager.add(e, this.mergeUndoDeltas), + (this.mergeUndoDeltas = !0), + this.$informUndoManager.schedule()), + this.bgTokenizer && this.bgTokenizer.$updateOnChange(e), + this._signal("change", e); + }), + (this.setValue = function (e) { + this.doc.setValue(e), + this.selection.moveTo(0, 0), + this.$resetRowCache(0), + this.setUndoManager(this.$undoManager), + this.getUndoManager().reset(); + }), + (this.getValue = this.toString = + function () { + return this.doc.getValue(); + }), + (this.getSelection = function () { + return this.selection; + }), + (this.getState = function (e) { + return this.bgTokenizer.getState(e); + }), + (this.getTokens = function (e) { + return this.bgTokenizer.getTokens(e); + }), + (this.getTokenAt = function (e, t) { + var n = this.bgTokenizer.getTokens(e), + r, + i = 0; + if (t == null) { + var s = n.length - 1; + i = this.getLine(e).length; + } else + for (var s = 0; s < n.length; s++) { + i += n[s].value.length; + if (i >= t) break; + } + return ( + (r = n[s]), + r ? ((r.index = s), (r.start = i - r.value.length), r) : null + ); + }), + (this.setUndoManager = function (e) { + (this.$undoManager = e), + this.$informUndoManager && this.$informUndoManager.cancel(); + if (e) { + var t = this; + e.addSession(this), + (this.$syncInformUndoManager = function () { + t.$informUndoManager.cancel(), (t.mergeUndoDeltas = !1); + }), + (this.$informUndoManager = i.delayedCall( + this.$syncInformUndoManager, + )); + } else this.$syncInformUndoManager = function () {}; + }), + (this.markUndoGroup = function () { + this.$syncInformUndoManager && this.$syncInformUndoManager(); + }), + (this.$defaultUndoManager = { + undo: function () {}, + redo: function () {}, + reset: function () {}, + add: function () {}, + addSelection: function () {}, + startNewGroup: function () {}, + addSession: function () {}, + }), + (this.getUndoManager = function () { + return this.$undoManager || this.$defaultUndoManager; + }), + (this.getTabString = function () { + return this.getUseSoftTabs() + ? i.stringRepeat(" ", this.getTabSize()) + : " "; + }), + (this.setUseSoftTabs = function (e) { + this.setOption("useSoftTabs", e); + }), + (this.getUseSoftTabs = function () { + return this.$useSoftTabs && !this.$mode.$indentWithTabs; + }), + (this.setTabSize = function (e) { + this.setOption("tabSize", e); + }), + (this.getTabSize = function () { + return this.$tabSize; + }), + (this.isTabStop = function (e) { + return this.$useSoftTabs && e.column % this.$tabSize === 0; + }), + (this.setNavigateWithinSoftTabs = function (e) { + this.setOption("navigateWithinSoftTabs", e); + }), + (this.getNavigateWithinSoftTabs = function () { + return this.$navigateWithinSoftTabs; + }), + (this.$overwrite = !1), + (this.setOverwrite = function (e) { + this.setOption("overwrite", e); + }), + (this.getOverwrite = function () { + return this.$overwrite; + }), + (this.toggleOverwrite = function () { + this.setOverwrite(!this.$overwrite); + }), + (this.addGutterDecoration = function (e, t) { + this.$decorations[e] || (this.$decorations[e] = ""), + (this.$decorations[e] += " " + t), + this._signal("changeBreakpoint", {}); + }), + (this.removeGutterDecoration = function (e, t) { + (this.$decorations[e] = (this.$decorations[e] || "").replace( + " " + t, + "", + )), + this._signal("changeBreakpoint", {}); + }), + (this.getBreakpoints = function () { + return this.$breakpoints; + }), + (this.setBreakpoints = function (e) { + this.$breakpoints = []; + for (var t = 0; t < e.length; t++) + this.$breakpoints[e[t]] = "ace_breakpoint"; + this._signal("changeBreakpoint", {}); + }), + (this.clearBreakpoints = function () { + (this.$breakpoints = []), this._signal("changeBreakpoint", {}); + }), + (this.setBreakpoint = function (e, t) { + t === undefined && (t = "ace_breakpoint"), + t ? (this.$breakpoints[e] = t) : delete this.$breakpoints[e], + this._signal("changeBreakpoint", {}); + }), + (this.clearBreakpoint = function (e) { + delete this.$breakpoints[e], this._signal("changeBreakpoint", {}); + }), + (this.addMarker = function (e, t, n, r) { + var i = this.$markerId++, + s = { + range: e, + type: n || "line", + renderer: typeof n == "function" ? n : null, + clazz: t, + inFront: !!r, + id: i, + }; + return ( + r + ? ((this.$frontMarkers[i] = s), + this._signal("changeFrontMarker")) + : ((this.$backMarkers[i] = s), + this._signal("changeBackMarker")), + i + ); + }), + (this.addDynamicMarker = function (e, t) { + if (!e.update) return; + var n = this.$markerId++; + return ( + (e.id = n), + (e.inFront = !!t), + t + ? ((this.$frontMarkers[n] = e), + this._signal("changeFrontMarker")) + : ((this.$backMarkers[n] = e), + this._signal("changeBackMarker")), + e + ); + }), + (this.removeMarker = function (e) { + var t = this.$frontMarkers[e] || this.$backMarkers[e]; + if (!t) return; + var n = t.inFront ? this.$frontMarkers : this.$backMarkers; + delete n[e], + this._signal(t.inFront ? "changeFrontMarker" : "changeBackMarker"); + }), + (this.getMarkers = function (e) { + return e ? this.$frontMarkers : this.$backMarkers; + }), + (this.highlight = function (e) { + if (!this.$searchHighlight) { + var t = new p(null, "ace_selected-word", "text"); + this.$searchHighlight = this.addDynamicMarker(t); + } + this.$searchHighlight.setRegexp(e); + }), + (this.highlightLines = function (e, t, n, r) { + typeof t != "number" && ((n = t), (t = e)), n || (n = "ace_step"); + var i = new l(e, 0, t, Infinity); + return (i.id = this.addMarker(i, n, "fullLine", r)), i; + }), + (this.setAnnotations = function (e) { + (this.$annotations = e), this._signal("changeAnnotation", {}); + }), + (this.getAnnotations = function () { + return this.$annotations || []; + }), + (this.clearAnnotations = function () { + this.setAnnotations([]); + }), + (this.$detectNewLine = function (e) { + var t = e.match(/^.*?(\r?\n)/m); + t ? (this.$autoNewLine = t[1]) : (this.$autoNewLine = "\n"); + }), + (this.getWordRange = function (e, t) { + var n = this.getLine(e), + r = !1; + t > 0 && (r = !!n.charAt(t - 1).match(this.tokenRe)), + r || (r = !!n.charAt(t).match(this.tokenRe)); + if (r) var i = this.tokenRe; + else if (/^\s+$/.test(n.slice(t - 1, t + 1))) var i = /\s/; + else var i = this.nonTokenRe; + var s = t; + if (s > 0) { + do s--; + while (s >= 0 && n.charAt(s).match(i)); + s++; + } + var o = t; + while (o < n.length && n.charAt(o).match(i)) o++; + return new l(e, s, e, o); + }), + (this.getAWordRange = function (e, t) { + var n = this.getWordRange(e, t), + r = this.getLine(n.end.row); + while (r.charAt(n.end.column).match(/[ \t]/)) n.end.column += 1; + return n; + }), + (this.setNewLineMode = function (e) { + this.doc.setNewLineMode(e); + }), + (this.getNewLineMode = function () { + return this.doc.getNewLineMode(); + }), + (this.setUseWorker = function (e) { + this.setOption("useWorker", e); + }), + (this.getUseWorker = function () { + return this.$useWorker; + }), + (this.onReloadTokenizer = function (e) { + var t = e.data; + this.bgTokenizer.start(t.first), this._signal("tokenizerUpdate", e); + }), + (this.$modes = o.$modes), + (this.$mode = null), + (this.$modeId = null), + (this.setMode = function (e, t) { + if (e && typeof e == "object") { + if (e.getTokenizer) return this.$onChangeMode(e); + var n = e, + r = n.path; + } else r = e || "ace/mode/text"; + this.$modes["ace/mode/text"] || + (this.$modes["ace/mode/text"] = new f()); + if (this.$modes[r] && !n) { + this.$onChangeMode(this.$modes[r]), t && t(); + return; + } + (this.$modeId = r), + o.loadModule( + ["mode", r], + function (e) { + if (this.$modeId !== r) return t && t(); + this.$modes[r] && !n + ? this.$onChangeMode(this.$modes[r]) + : e && + e.Mode && + ((e = new e.Mode(n)), + n || ((this.$modes[r] = e), (e.$id = r)), + this.$onChangeMode(e)), + t && t(); + }.bind(this), + ), + this.$mode || this.$onChangeMode(this.$modes["ace/mode/text"], !0); + }), + (this.$onChangeMode = function (e, t) { + t || (this.$modeId = e.$id); + if (this.$mode === e) return; + (this.$mode = e), + this.$stopWorker(), + this.$useWorker && this.$startWorker(); + var n = e.getTokenizer(); + if (n.addEventListener !== undefined) { + var r = this.onReloadTokenizer.bind(this); + n.addEventListener("update", r); + } + if (!this.bgTokenizer) { + this.bgTokenizer = new h(n); + var i = this; + this.bgTokenizer.addEventListener("update", function (e) { + i._signal("tokenizerUpdate", e); + }); + } else this.bgTokenizer.setTokenizer(n); + this.bgTokenizer.setDocument(this.getDocument()), + (this.tokenRe = e.tokenRe), + (this.nonTokenRe = e.nonTokenRe), + t || + (e.attachToSession && e.attachToSession(this), + this.$options.wrapMethod.set.call(this, this.$wrapMethod), + this.$setFolding(e.foldingRules), + this.bgTokenizer.start(0), + this._emit("changeMode")); + }), + (this.$stopWorker = function () { + this.$worker && (this.$worker.terminate(), (this.$worker = null)); + }), + (this.$startWorker = function () { + try { + this.$worker = this.$mode.createWorker(this); + } catch (e) { + o.warn("Could not load worker", e), (this.$worker = null); + } + }), + (this.getMode = function () { + return this.$mode; + }), + (this.$scrollTop = 0), + (this.setScrollTop = function (e) { + if (this.$scrollTop === e || isNaN(e)) return; + (this.$scrollTop = e), this._signal("changeScrollTop", e); + }), + (this.getScrollTop = function () { + return this.$scrollTop; + }), + (this.$scrollLeft = 0), + (this.setScrollLeft = function (e) { + if (this.$scrollLeft === e || isNaN(e)) return; + (this.$scrollLeft = e), this._signal("changeScrollLeft", e); + }), + (this.getScrollLeft = function () { + return this.$scrollLeft; + }), + (this.getScreenWidth = function () { + return ( + this.$computeWidth(), + this.lineWidgets + ? Math.max(this.getLineWidgetMaxWidth(), this.screenWidth) + : this.screenWidth + ); + }), + (this.getLineWidgetMaxWidth = function () { + if (this.lineWidgetsWidth != null) return this.lineWidgetsWidth; + var e = 0; + return ( + this.lineWidgets.forEach(function (t) { + t && t.screenWidth > e && (e = t.screenWidth); + }), + (this.lineWidgetWidth = e) + ); + }), + (this.$computeWidth = function (e) { + if (this.$modified || e) { + this.$modified = !1; + if (this.$useWrapMode) return (this.screenWidth = this.$wrapLimit); + var t = this.doc.getAllLines(), + n = this.$rowLengthCache, + r = 0, + i = 0, + s = this.$foldData[i], + o = s ? s.start.row : Infinity, + u = t.length; + for (var a = 0; a < u; a++) { + if (a > o) { + a = s.end.row + 1; + if (a >= u) break; + (s = this.$foldData[i++]), (o = s ? s.start.row : Infinity); + } + n[a] == null && (n[a] = this.$getStringScreenWidth(t[a])[0]), + n[a] > r && (r = n[a]); + } + this.screenWidth = r; + } + }), + (this.getLine = function (e) { + return this.doc.getLine(e); + }), + (this.getLines = function (e, t) { + return this.doc.getLines(e, t); + }), + (this.getLength = function () { + return this.doc.getLength(); + }), + (this.getTextRange = function (e) { + return this.doc.getTextRange(e || this.selection.getRange()); + }), + (this.insert = function (e, t) { + return this.doc.insert(e, t); + }), + (this.remove = function (e) { + return this.doc.remove(e); + }), + (this.removeFullLines = function (e, t) { + return this.doc.removeFullLines(e, t); + }), + (this.undoChanges = function (e, t) { + if (!e.length) return; + this.$fromUndo = !0; + for (var n = e.length - 1; n != -1; n--) { + var r = e[n]; + r.action == "insert" || r.action == "remove" + ? this.doc.revertDelta(r) + : r.folds && this.addFolds(r.folds); + } + !t && + this.$undoSelect && + (e.selectionBefore + ? this.selection.fromJSON(e.selectionBefore) + : this.selection.setRange(this.$getUndoSelection(e, !0))), + (this.$fromUndo = !1); + }), + (this.redoChanges = function (e, t) { + if (!e.length) return; + this.$fromUndo = !0; + for (var n = 0; n < e.length; n++) { + var r = e[n]; + (r.action == "insert" || r.action == "remove") && + this.doc.applyDelta(r); + } + !t && + this.$undoSelect && + (e.selectionAfter + ? this.selection.fromJSON(e.selectionAfter) + : this.selection.setRange(this.$getUndoSelection(e, !1))), + (this.$fromUndo = !1); + }), + (this.setUndoSelect = function (e) { + this.$undoSelect = e; + }), + (this.$getUndoSelection = function (e, t) { + function n(e) { + return t ? e.action !== "insert" : e.action === "insert"; + } + var r, i, s; + for (var o = 0; o < e.length; o++) { + var u = e[o]; + if (!u.start) continue; + if (!r) { + n(u) + ? ((r = l.fromPoints(u.start, u.end)), (s = !0)) + : ((r = l.fromPoints(u.start, u.start)), (s = !1)); + continue; + } + n(u) + ? ((i = u.start), + r.compare(i.row, i.column) == -1 && r.setStart(i), + (i = u.end), + r.compare(i.row, i.column) == 1 && r.setEnd(i), + (s = !0)) + : ((i = u.start), + r.compare(i.row, i.column) == -1 && + (r = l.fromPoints(u.start, u.start)), + (s = !1)); + } + return r; + }), + (this.replace = function (e, t) { + return this.doc.replace(e, t); + }), + (this.moveText = function (e, t, n) { + var r = this.getTextRange(e), + i = this.getFoldsInRange(e), + s = l.fromPoints(t, t); + if (!n) { + this.remove(e); + var o = e.start.row - e.end.row, + u = o ? -e.end.column : e.start.column - e.end.column; + u && + (s.start.row == e.end.row && + s.start.column > e.end.column && + (s.start.column += u), + s.end.row == e.end.row && + s.end.column > e.end.column && + (s.end.column += u)), + o && + s.start.row >= e.end.row && + ((s.start.row += o), (s.end.row += o)); + } + s.end = this.insert(s.start, r); + if (i.length) { + var a = e.start, + f = s.start, + o = f.row - a.row, + u = f.column - a.column; + this.addFolds( + i.map(function (e) { + return ( + (e = e.clone()), + e.start.row == a.row && (e.start.column += u), + e.end.row == a.row && (e.end.column += u), + (e.start.row += o), + (e.end.row += o), + e + ); + }), + ); + } + return s; + }), + (this.indentRows = function (e, t, n) { + n = n.replace(/\t/g, this.getTabString()); + for (var r = e; r <= t; r++) + this.doc.insertInLine({ row: r, column: 0 }, n); + }), + (this.outdentRows = function (e) { + var t = e.collapseRows(), + n = new l(0, 0, 0, 0), + r = this.getTabSize(); + for (var i = t.start.row; i <= t.end.row; ++i) { + var s = this.getLine(i); + (n.start.row = i), (n.end.row = i); + for (var o = 0; o < r; ++o) if (s.charAt(o) != " ") break; + o < r && s.charAt(o) == " " + ? ((n.start.column = o), (n.end.column = o + 1)) + : ((n.start.column = 0), (n.end.column = o)), + this.remove(n); + } + }), + (this.$moveLines = function (e, t, n) { + (e = this.getRowFoldStart(e)), (t = this.getRowFoldEnd(t)); + if (n < 0) { + var r = this.getRowFoldStart(e + n); + if (r < 0) return 0; + var i = r - e; + } else if (n > 0) { + var r = this.getRowFoldEnd(t + n); + if (r > this.doc.getLength() - 1) return 0; + var i = r - t; + } else { + (e = this.$clipRowToDocument(e)), (t = this.$clipRowToDocument(t)); + var i = t - e + 1; + } + var s = new l(e, 0, t, Number.MAX_VALUE), + o = this.getFoldsInRange(s).map(function (e) { + return (e = e.clone()), (e.start.row += i), (e.end.row += i), e; + }), + u = + n == 0 + ? this.doc.getLines(e, t) + : this.doc.removeFullLines(e, t); + return ( + this.doc.insertFullLines(e + i, u), o.length && this.addFolds(o), i + ); + }), + (this.moveLinesUp = function (e, t) { + return this.$moveLines(e, t, -1); + }), + (this.moveLinesDown = function (e, t) { + return this.$moveLines(e, t, 1); + }), + (this.duplicateLines = function (e, t) { + return this.$moveLines(e, t, 0); + }), + (this.$clipRowToDocument = function (e) { + return Math.max(0, Math.min(e, this.doc.getLength() - 1)); + }), + (this.$clipColumnToRow = function (e, t) { + return t < 0 ? 0 : Math.min(this.doc.getLine(e).length, t); + }), + (this.$clipPositionToDocument = function (e, t) { + t = Math.max(0, t); + if (e < 0) (e = 0), (t = 0); + else { + var n = this.doc.getLength(); + e >= n + ? ((e = n - 1), (t = this.doc.getLine(n - 1).length)) + : (t = Math.min(this.doc.getLine(e).length, t)); + } + return { row: e, column: t }; + }), + (this.$clipRangeToDocument = function (e) { + e.start.row < 0 + ? ((e.start.row = 0), (e.start.column = 0)) + : (e.start.column = this.$clipColumnToRow( + e.start.row, + e.start.column, + )); + var t = this.doc.getLength() - 1; + return ( + e.end.row > t + ? ((e.end.row = t), (e.end.column = this.doc.getLine(t).length)) + : (e.end.column = this.$clipColumnToRow( + e.end.row, + e.end.column, + )), + e + ); + }), + (this.$wrapLimit = 80), + (this.$useWrapMode = !1), + (this.$wrapLimitRange = { min: null, max: null }), + (this.setUseWrapMode = function (e) { + if (e != this.$useWrapMode) { + (this.$useWrapMode = e), + (this.$modified = !0), + this.$resetRowCache(0); + if (e) { + var t = this.getLength(); + (this.$wrapData = Array(t)), this.$updateWrapData(0, t - 1); + } + this._signal("changeWrapMode"); + } + }), + (this.getUseWrapMode = function () { + return this.$useWrapMode; + }), + (this.setWrapLimitRange = function (e, t) { + if (this.$wrapLimitRange.min !== e || this.$wrapLimitRange.max !== t) + (this.$wrapLimitRange = { min: e, max: t }), + (this.$modified = !0), + this.$bidiHandler.markAsDirty(), + this.$useWrapMode && this._signal("changeWrapMode"); + }), + (this.adjustWrapLimit = function (e, t) { + var n = this.$wrapLimitRange; + n.max < 0 && (n = { min: t, max: t }); + var r = this.$constrainWrapLimit(e, n.min, n.max); + return r != this.$wrapLimit && r > 1 + ? ((this.$wrapLimit = r), + (this.$modified = !0), + this.$useWrapMode && + (this.$updateWrapData(0, this.getLength() - 1), + this.$resetRowCache(0), + this._signal("changeWrapLimit")), + !0) + : !1; + }), + (this.$constrainWrapLimit = function (e, t, n) { + return t && (e = Math.max(t, e)), n && (e = Math.min(n, e)), e; + }), + (this.getWrapLimit = function () { + return this.$wrapLimit; + }), + (this.setWrapLimit = function (e) { + this.setWrapLimitRange(e, e); + }), + (this.getWrapLimitRange = function () { + return { min: this.$wrapLimitRange.min, max: this.$wrapLimitRange.max }; + }), + (this.$updateInternalDataOnChange = function (e) { + var t = this.$useWrapMode, + n = e.action, + r = e.start, + i = e.end, + s = r.row, + o = i.row, + u = o - s, + a = null; + this.$updating = !0; + if (u != 0) + if (n === "remove") { + this[t ? "$wrapData" : "$rowLengthCache"].splice(s, u); + var f = this.$foldData; + (a = this.getFoldsInRange(e)), this.removeFolds(a); + var l = this.getFoldLine(i.row), + c = 0; + if (l) { + l.addRemoveChars(i.row, i.column, r.column - i.column), + l.shiftRow(-u); + var h = this.getFoldLine(s); + h && h !== l && (h.merge(l), (l = h)), + (c = f.indexOf(l) + 1); + } + for (c; c < f.length; c++) { + var l = f[c]; + l.start.row >= i.row && l.shiftRow(-u); + } + o = s; + } else { + var p = Array(u); + p.unshift(s, 0); + var d = t ? this.$wrapData : this.$rowLengthCache; + d.splice.apply(d, p); + var f = this.$foldData, + l = this.getFoldLine(s), + c = 0; + if (l) { + var v = l.range.compareInside(r.row, r.column); + v == 0 + ? ((l = l.split(r.row, r.column)), + l && + (l.shiftRow(u), + l.addRemoveChars(o, 0, i.column - r.column))) + : v == -1 && + (l.addRemoveChars(s, 0, i.column - r.column), + l.shiftRow(u)), + (c = f.indexOf(l) + 1); + } + for (c; c < f.length; c++) { + var l = f[c]; + l.start.row >= s && l.shiftRow(u); + } + } + else { + (u = Math.abs(e.start.column - e.end.column)), + n === "remove" && + ((a = this.getFoldsInRange(e)), + this.removeFolds(a), + (u = -u)); + var l = this.getFoldLine(s); + l && l.addRemoveChars(s, r.column, u); + } + return ( + t && + this.$wrapData.length != this.doc.getLength() && + console.error( + "doc.getLength() and $wrapData.length have to be the same!", + ), + (this.$updating = !1), + t ? this.$updateWrapData(s, o) : this.$updateRowLengthCache(s, o), + a + ); + }), + (this.$updateRowLengthCache = function (e, t, n) { + (this.$rowLengthCache[e] = null), (this.$rowLengthCache[t] = null); + }), + (this.$updateWrapData = function (e, t) { + var r = this.doc.getAllLines(), + i = this.getTabSize(), + o = this.$wrapData, + u = this.$wrapLimit, + a, + f, + l = e; + t = Math.min(t, r.length - 1); + while (l <= t) + (f = this.getFoldLine(l, f)), + f + ? ((a = []), + f.walk( + function (e, t, i, o) { + var u; + if (e != null) { + (u = this.$getDisplayTokens(e, a.length)), + (u[0] = n); + for (var f = 1; f < u.length; f++) u[f] = s; + } else + u = this.$getDisplayTokens( + r[t].substring(o, i), + a.length, + ); + a = a.concat(u); + }.bind(this), + f.end.row, + r[f.end.row].length + 1, + ), + (o[f.start.row] = this.$computeWrapSplits(a, u, i)), + (l = f.end.row + 1)) + : ((a = this.$getDisplayTokens(r[l])), + (o[l] = this.$computeWrapSplits(a, u, i)), + l++); + }); + var e = 1, + t = 2, + n = 3, + s = 4, + a = 9, + c = 10, + d = 11, + v = 12; + (this.$computeWrapSplits = function (e, r, i) { + function g() { + var t = 0; + if (m === 0) return t; + if (p) + for (var n = 0; n < e.length; n++) { + var r = e[n]; + if (r == c) t += 1; + else { + if (r != d) { + if (r == v) continue; + break; + } + t += i; + } + } + return h && p !== !1 && (t += i), Math.min(t, m); + } + function y(t) { + var n = t - f; + for (var r = f; r < t; r++) { + var i = e[r]; + if (i === 12 || i === 2) n -= 1; + } + o.length || ((b = g()), (o.indent = b)), (l += n), o.push(l), (f = t); + } + if (e.length == 0) return []; + var o = [], + u = e.length, + f = 0, + l = 0, + h = this.$wrapAsCode, + p = this.$indentedSoftWrap, + m = r <= Math.max(2 * i, 8) || p === !1 ? 0 : Math.floor(r / 2), + b = 0; + while (u - f > r - b) { + var w = f + r - b; + if (e[w - 1] >= c && e[w] >= c) { + y(w); + continue; + } + if (e[w] == n || e[w] == s) { + for (w; w != f - 1; w--) if (e[w] == n) break; + if (w > f) { + y(w); + continue; + } + w = f + r; + for (w; w < e.length; w++) if (e[w] != s) break; + if (w == e.length) break; + y(w); + continue; + } + var E = Math.max(w - (r - (r >> 2)), f - 1); + while (w > E && e[w] < n) w--; + if (h) { + while (w > E && e[w] < n) w--; + while (w > E && e[w] == a) w--; + } else while (w > E && e[w] < c) w--; + if (w > E) { + y(++w); + continue; + } + (w = f + r), e[w] == t && w--, y(w - b); + } + return o; + }), + (this.$getDisplayTokens = function (n, r) { + var i = [], + s; + r = r || 0; + for (var o = 0; o < n.length; o++) { + var u = n.charCodeAt(o); + if (u == 9) { + (s = this.getScreenTabSize(i.length + r)), i.push(d); + for (var f = 1; f < s; f++) i.push(v); + } else + u == 32 + ? i.push(c) + : (u > 39 && u < 48) || (u > 57 && u < 64) + ? i.push(a) + : u >= 4352 && m(u) + ? i.push(e, t) + : i.push(e); + } + return i; + }), + (this.$getStringScreenWidth = function (e, t, n) { + if (t == 0) return [0, 0]; + t == null && (t = Infinity), (n = n || 0); + var r, i; + for (i = 0; i < e.length; i++) { + (r = e.charCodeAt(i)), + r == 9 + ? (n += this.getScreenTabSize(n)) + : r >= 4352 && m(r) + ? (n += 2) + : (n += 1); + if (n > t) break; + } + return [n, i]; + }), + (this.lineWidgets = null), + (this.getRowLength = function (e) { + if (this.lineWidgets) + var t = (this.lineWidgets[e] && this.lineWidgets[e].rowCount) || 0; + else t = 0; + return !this.$useWrapMode || !this.$wrapData[e] + ? 1 + t + : this.$wrapData[e].length + 1 + t; + }), + (this.getRowLineCount = function (e) { + return !this.$useWrapMode || !this.$wrapData[e] + ? 1 + : this.$wrapData[e].length + 1; + }), + (this.getRowWrapIndent = function (e) { + if (this.$useWrapMode) { + var t = this.screenToDocumentPosition(e, Number.MAX_VALUE), + n = this.$wrapData[t.row]; + return n.length && n[0] < t.column ? n.indent : 0; + } + return 0; + }), + (this.getScreenLastRowColumn = function (e) { + var t = this.screenToDocumentPosition(e, Number.MAX_VALUE); + return this.documentToScreenColumn(t.row, t.column); + }), + (this.getDocumentLastRowColumn = function (e, t) { + var n = this.documentToScreenRow(e, t); + return this.getScreenLastRowColumn(n); + }), + (this.getDocumentLastRowColumnPosition = function (e, t) { + var n = this.documentToScreenRow(e, t); + return this.screenToDocumentPosition(n, Number.MAX_VALUE / 10); + }), + (this.getRowSplitData = function (e) { + return this.$useWrapMode ? this.$wrapData[e] : undefined; + }), + (this.getScreenTabSize = function (e) { + return this.$tabSize - (e % this.$tabSize); + }), + (this.screenToDocumentRow = function (e, t) { + return this.screenToDocumentPosition(e, t).row; + }), + (this.screenToDocumentColumn = function (e, t) { + return this.screenToDocumentPosition(e, t).column; + }), + (this.screenToDocumentPosition = function (e, t, n) { + if (e < 0) return { row: 0, column: 0 }; + var r, + i = 0, + s = 0, + o, + u = 0, + a = 0, + f = this.$screenRowCache, + l = this.$getRowCacheIndex(f, e), + c = f.length; + if (c && l >= 0) + var u = f[l], + i = this.$docRowCache[l], + h = e > f[c - 1]; + else var h = !c; + var p = this.getLength() - 1, + d = this.getNextFoldLine(i), + v = d ? d.start.row : Infinity; + while (u <= e) { + a = this.getRowLength(i); + if (u + a > e || i >= p) break; + (u += a), + i++, + i > v && + ((i = d.end.row + 1), + (d = this.getNextFoldLine(i, d)), + (v = d ? d.start.row : Infinity)), + h && (this.$docRowCache.push(i), this.$screenRowCache.push(u)); + } + if (d && d.start.row <= i) + (r = this.getFoldDisplayLine(d)), (i = d.start.row); + else { + if (u + a <= e || i > p) + return { row: p, column: this.getLine(p).length }; + (r = this.getLine(i)), (d = null); + } + var m = 0, + g = Math.floor(e - u); + if (this.$useWrapMode) { + var y = this.$wrapData[i]; + y && + ((o = y[g]), + g > 0 && + y.length && + ((m = y.indent), + (s = y[g - 1] || y[y.length - 1]), + (r = r.substring(s)))); + } + return ( + n !== undefined && + this.$bidiHandler.isBidiRow(u + g, i, g) && + (t = this.$bidiHandler.offsetToCol(n)), + (s += this.$getStringScreenWidth(r, t - m)[1]), + this.$useWrapMode && s >= o && (s = o - 1), + d ? d.idxToPosition(s) : { row: i, column: s } + ); + }), + (this.documentToScreenPosition = function (e, t) { + if (typeof t == "undefined") + var n = this.$clipPositionToDocument(e.row, e.column); + else n = this.$clipPositionToDocument(e, t); + (e = n.row), (t = n.column); + var r = 0, + i = null, + s = null; + (s = this.getFoldAt(e, t, 1)), + s && ((e = s.start.row), (t = s.start.column)); + var o, + u = 0, + a = this.$docRowCache, + f = this.$getRowCacheIndex(a, e), + l = a.length; + if (l && f >= 0) + var u = a[f], + r = this.$screenRowCache[f], + c = e > a[l - 1]; + else var c = !l; + var h = this.getNextFoldLine(u), + p = h ? h.start.row : Infinity; + while (u < e) { + if (u >= p) { + o = h.end.row + 1; + if (o > e) break; + (h = this.getNextFoldLine(o, h)), + (p = h ? h.start.row : Infinity); + } else o = u + 1; + (r += this.getRowLength(u)), + (u = o), + c && (this.$docRowCache.push(u), this.$screenRowCache.push(r)); + } + var d = ""; + h && u >= p + ? ((d = this.getFoldDisplayLine(h, e, t)), (i = h.start.row)) + : ((d = this.getLine(e).substring(0, t)), (i = e)); + var v = 0; + if (this.$useWrapMode) { + var m = this.$wrapData[i]; + if (m) { + var g = 0; + while (d.length >= m[g]) r++, g++; + (d = d.substring(m[g - 1] || 0, d.length)), + (v = g > 0 ? m.indent : 0); + } + } + return { row: r, column: v + this.$getStringScreenWidth(d)[0] }; + }), + (this.documentToScreenColumn = function (e, t) { + return this.documentToScreenPosition(e, t).column; + }), + (this.documentToScreenRow = function (e, t) { + return this.documentToScreenPosition(e, t).row; + }), + (this.getScreenLength = function () { + var e = 0, + t = null; + if (!this.$useWrapMode) { + e = this.getLength(); + var n = this.$foldData; + for (var r = 0; r < n.length; r++) + (t = n[r]), (e -= t.end.row - t.start.row); + } else { + var i = this.$wrapData.length, + s = 0, + r = 0, + t = this.$foldData[r++], + o = t ? t.start.row : Infinity; + while (s < i) { + var u = this.$wrapData[s]; + (e += u ? u.length + 1 : 1), + s++, + s > o && + ((s = t.end.row + 1), + (t = this.$foldData[r++]), + (o = t ? t.start.row : Infinity)); + } + } + return this.lineWidgets && (e += this.$getWidgetScreenLength()), e; + }), + (this.$setFontMetrics = function (e) { + if (!this.$enableVarChar) return; + this.$getStringScreenWidth = function (t, n, r) { + if (n === 0) return [0, 0]; + n || (n = Infinity), (r = r || 0); + var i, s; + for (s = 0; s < t.length; s++) { + (i = t.charAt(s)), + i === " " + ? (r += this.getScreenTabSize(r)) + : (r += e.getCharacterWidth(i)); + if (r > n) break; + } + return [r, s]; + }; + }), + (this.destroy = function () { + this.bgTokenizer && + (this.bgTokenizer.setDocument(null), (this.bgTokenizer = null)), + this.$stopWorker(); + }), + (this.isFullWidth = m); + }.call(d.prototype), + e("./edit_session/folding").Folding.call(d.prototype), + e("./edit_session/bracket_match").BracketMatch.call(d.prototype), + o.defineOptions(d.prototype, "session", { + wrap: { + set: function (e) { + !e || e == "off" + ? (e = !1) + : e == "free" + ? (e = !0) + : e == "printMargin" + ? (e = -1) + : typeof e == "string" && (e = parseInt(e, 10) || !1); + if (this.$wrap == e) return; + this.$wrap = e; + if (!e) this.setUseWrapMode(!1); + else { + var t = typeof e == "number" ? e : null; + this.setWrapLimitRange(t, t), this.setUseWrapMode(!0); + } + }, + get: function () { + return this.getUseWrapMode() + ? this.$wrap == -1 + ? "printMargin" + : this.getWrapLimitRange().min + ? this.$wrap + : "free" + : "off"; + }, + handlesSet: !0, + }, + wrapMethod: { + set: function (e) { + (e = e == "auto" ? this.$mode.type != "text" : e != "text"), + e != this.$wrapAsCode && + ((this.$wrapAsCode = e), + this.$useWrapMode && + ((this.$useWrapMode = !1), this.setUseWrapMode(!0))); + }, + initialValue: "auto", + }, + indentedSoftWrap: { + set: function () { + this.$useWrapMode && + ((this.$useWrapMode = !1), this.setUseWrapMode(!0)); + }, + initialValue: !0, + }, + firstLineNumber: { + set: function () { + this._signal("changeBreakpoint"); + }, + initialValue: 1, + }, + useWorker: { + set: function (e) { + (this.$useWorker = e), this.$stopWorker(), e && this.$startWorker(); + }, + initialValue: !0, + }, + useSoftTabs: { initialValue: !0 }, + tabSize: { + set: function (e) { + if (isNaN(e) || this.$tabSize === e) return; + (this.$modified = !0), + (this.$rowLengthCache = []), + (this.$tabSize = e), + this._signal("changeTabSize"); + }, + initialValue: 4, + handlesSet: !0, + }, + navigateWithinSoftTabs: { initialValue: !1 }, + foldStyle: { + set: function (e) { + this.setFoldStyle(e); + }, + handlesSet: !0, + }, + overwrite: { + set: function (e) { + this._signal("changeOverwrite"); + }, + initialValue: !1, + }, + newLineMode: { + set: function (e) { + this.doc.setNewLineMode(e); + }, + get: function () { + return this.doc.getNewLineMode(); + }, + handlesSet: !0, + }, + mode: { + set: function (e) { + this.setMode(e); + }, + get: function () { + return this.$modeId; + }, + handlesSet: !0, + }, + }), + (t.EditSession = d); + }, + ), + define( + "ace/search", + ["require", "exports", "module", "ace/lib/lang", "ace/lib/oop", "ace/range"], + function (e, t, n) { + "use strict"; + function u(e, t) { + function n(e) { + return /\w/.test(e) || t.regExp ? "\\b" : ""; + } + return n(e[0]) + e + n(e[e.length - 1]); + } + var r = e("./lib/lang"), + i = e("./lib/oop"), + s = e("./range").Range, + o = function () { + this.$options = {}; + }; + (function () { + (this.set = function (e) { + return i.mixin(this.$options, e), this; + }), + (this.getOptions = function () { + return r.copyObject(this.$options); + }), + (this.setOptions = function (e) { + this.$options = e; + }), + (this.find = function (e) { + var t = this.$options, + n = this.$matchIterator(e, t); + if (!n) return !1; + var r = null; + return ( + n.forEach(function (e, n, i, o) { + return ( + (r = new s(e, n, i, o)), + n == o && + t.start && + t.start.start && + t.skipCurrent != 0 && + r.isEqual(t.start) + ? ((r = null), !1) + : !0 + ); + }), + r + ); + }), + (this.findAll = function (e) { + var t = this.$options; + if (!t.needle) return []; + this.$assembleRegExp(t); + var n = t.range, + i = n ? e.getLines(n.start.row, n.end.row) : e.doc.getAllLines(), + o = [], + u = t.re; + if (t.$isMultiLine) { + var a = u.length, + f = i.length - a, + l; + e: for (var c = u.offset || 0; c <= f; c++) { + for (var h = 0; h < a; h++) + if (i[c + h].search(u[h]) == -1) continue e; + var p = i[c], + d = i[c + a - 1], + v = p.length - p.match(u[0])[0].length, + m = d.match(u[a - 1])[0].length; + if (l && l.end.row === c && l.end.column > v) continue; + o.push((l = new s(c, v, c + a - 1, m))), a > 2 && (c = c + a - 2); + } + } else + for (var g = 0; g < i.length; g++) { + var y = r.getMatchOffsets(i[g], u); + for (var h = 0; h < y.length; h++) { + var b = y[h]; + o.push(new s(g, b.offset, g, b.offset + b.length)); + } + } + if (n) { + var w = n.start.column, + E = n.start.column, + g = 0, + h = o.length - 1; + while (g < h && o[g].start.column < w && o[g].start.row == n.start.row) + g++; + while (g < h && o[h].end.column > E && o[h].end.row == n.end.row) h--; + o = o.slice(g, h + 1); + for (g = 0, h = o.length; g < h; g++) + (o[g].start.row += n.start.row), (o[g].end.row += n.start.row); + } + return o; + }), + (this.replace = function (e, t) { + var n = this.$options, + r = this.$assembleRegExp(n); + if (n.$isMultiLine) return t; + if (!r) return; + var i = r.exec(e); + if (!i || i[0].length != e.length) return null; + t = e.replace(r, t); + if (n.preserveCase) { + t = t.split(""); + for (var s = Math.min(e.length, e.length); s--; ) { + var o = e[s]; + o && o.toLowerCase() != o + ? (t[s] = t[s].toUpperCase()) + : (t[s] = t[s].toLowerCase()); + } + t = t.join(""); + } + return t; + }), + (this.$assembleRegExp = function (e, t) { + if (e.needle instanceof RegExp) return (e.re = e.needle); + var n = e.needle; + if (!e.needle) return (e.re = !1); + e.regExp || (n = r.escapeRegExp(n)), e.wholeWord && (n = u(n, e)); + var i = e.caseSensitive ? "gm" : "gmi"; + e.$isMultiLine = !t && /[\n\r]/.test(n); + if (e.$isMultiLine) return (e.re = this.$assembleMultilineRegExp(n, i)); + try { + var s = new RegExp(n, i); + } catch (o) { + s = !1; + } + return (e.re = s); + }), + (this.$assembleMultilineRegExp = function (e, t) { + var n = e.replace(/\r\n|\r|\n/g, "$\n^").split("\n"), + r = []; + for (var i = 0; i < n.length; i++) + try { + r.push(new RegExp(n[i], t)); + } catch (s) { + return !1; + } + return r; + }), + (this.$matchIterator = function (e, t) { + var n = this.$assembleRegExp(t); + if (!n) return !1; + var r = t.backwards == 1, + i = t.skipCurrent != 0, + s = t.range, + o = t.start; + o || (o = s ? s[r ? "end" : "start"] : e.selection.getRange()), + o.start && (o = o[i != r ? "end" : "start"]); + var u = s ? s.start.row : 0, + a = s ? s.end.row : e.getLength() - 1; + if (r) + var f = function (e) { + var n = o.row; + if (c(n, o.column, e)) return; + for (n--; n >= u; n--) if (c(n, Number.MAX_VALUE, e)) return; + if (t.wrap == 0) return; + for (n = a, u = o.row; n >= u; n--) + if (c(n, Number.MAX_VALUE, e)) return; + }; + else + var f = function (e) { + var n = o.row; + if (c(n, o.column, e)) return; + for (n += 1; n <= a; n++) if (c(n, 0, e)) return; + if (t.wrap == 0) return; + for (n = u, a = o.row; n <= a; n++) if (c(n, 0, e)) return; + }; + if (t.$isMultiLine) + var l = n.length, + c = function (t, i, s) { + var o = r ? t - l + 1 : t; + if (o < 0) return; + var u = e.getLine(o), + a = u.search(n[0]); + if ((!r && a < i) || a === -1) return; + for (var f = 1; f < l; f++) { + u = e.getLine(o + f); + if (u.search(n[f]) == -1) return; + } + var c = u.match(n[l - 1])[0].length; + if (r && c > i) return; + if (s(o, a, o + l - 1, c)) return !0; + }; + else if (r) + var c = function (t, r, i) { + var s = e.getLine(t), + o = [], + u, + a = 0; + n.lastIndex = 0; + while ((u = n.exec(s))) { + var f = u[0].length; + a = u.index; + if (!f) { + if (a >= s.length) break; + n.lastIndex = a += 1; + } + if (u.index + f > r) break; + o.push(u.index, f); + } + for (var l = o.length - 1; l >= 0; l -= 2) { + var c = o[l - 1], + f = o[l]; + if (i(t, c, t, c + f)) return !0; + } + }; + else + var c = function (t, r, i) { + var s = e.getLine(t), + o, + u; + n.lastIndex = r; + while ((u = n.exec(s))) { + var a = u[0].length; + o = u.index; + if (i(t, o, t, o + a)) return !0; + if (!a) { + n.lastIndex = o += 1; + if (o >= s.length) return !1; + } + } + }; + return { forEach: f }; + }); + }).call(o.prototype), + (t.Search = o); + }, + ), + define( + "ace/keyboard/hash_handler", + ["require", "exports", "module", "ace/lib/keys", "ace/lib/useragent"], + function (e, t, n) { + "use strict"; + function o(e, t) { + (this.platform = t || (i.isMac ? "mac" : "win")), + (this.commands = {}), + (this.commandKeyBinding = {}), + this.addCommands(e), + (this.$singleCommand = !0); + } + function u(e, t) { + o.call(this, e, t), (this.$singleCommand = !1); + } + var r = e("../lib/keys"), + i = e("../lib/useragent"), + s = r.KEY_MODS; + (u.prototype = o.prototype), + function () { + function e(e) { + return ( + (typeof e == "object" && e.bindKey && e.bindKey.position) || + (e.isDefault ? -100 : 0) + ); + } + (this.addCommand = function (e) { + this.commands[e.name] && this.removeCommand(e), + (this.commands[e.name] = e), + e.bindKey && this._buildKeyHash(e); + }), + (this.removeCommand = function (e, t) { + var n = e && (typeof e == "string" ? e : e.name); + (e = this.commands[n]), t || delete this.commands[n]; + var r = this.commandKeyBinding; + for (var i in r) { + var s = r[i]; + if (s == e) delete r[i]; + else if (Array.isArray(s)) { + var o = s.indexOf(e); + o != -1 && (s.splice(o, 1), s.length == 1 && (r[i] = s[0])); + } + } + }), + (this.bindKey = function (e, t, n) { + typeof e == "object" && + e && + (n == undefined && (n = e.position), (e = e[this.platform])); + if (!e) return; + if (typeof t == "function") + return this.addCommand({ exec: t, bindKey: e, name: t.name || e }); + e.split("|").forEach(function (e) { + var r = ""; + if (e.indexOf(" ") != -1) { + var i = e.split(/\s+/); + (e = i.pop()), + i.forEach(function (e) { + var t = this.parseKeys(e), + n = s[t.hashId] + t.key; + (r += (r ? " " : "") + n), + this._addCommandToBinding(r, "chainKeys"); + }, this), + (r += " "); + } + var o = this.parseKeys(e), + u = s[o.hashId] + o.key; + this._addCommandToBinding(r + u, t, n); + }, this); + }), + (this._addCommandToBinding = function (t, n, r) { + var i = this.commandKeyBinding, + s; + if (!n) delete i[t]; + else if (!i[t] || this.$singleCommand) i[t] = n; + else { + Array.isArray(i[t]) + ? (s = i[t].indexOf(n)) != -1 && i[t].splice(s, 1) + : (i[t] = [i[t]]), + typeof r != "number" && (r = e(n)); + var o = i[t]; + for (s = 0; s < o.length; s++) { + var u = o[s], + a = e(u); + if (a > r) break; + } + o.splice(s, 0, n); + } + }), + (this.addCommands = function (e) { + e && + Object.keys(e).forEach(function (t) { + var n = e[t]; + if (!n) return; + if (typeof n == "string") return this.bindKey(n, t); + typeof n == "function" && (n = { exec: n }); + if (typeof n != "object") return; + n.name || (n.name = t), this.addCommand(n); + }, this); + }), + (this.removeCommands = function (e) { + Object.keys(e).forEach(function (t) { + this.removeCommand(e[t]); + }, this); + }), + (this.bindKeys = function (e) { + Object.keys(e).forEach(function (t) { + this.bindKey(t, e[t]); + }, this); + }), + (this._buildKeyHash = function (e) { + this.bindKey(e.bindKey, e); + }), + (this.parseKeys = function (e) { + var t = e + .toLowerCase() + .split(/[\-\+]([\-\+])?/) + .filter(function (e) { + return e; + }), + n = t.pop(), + i = r[n]; + if (r.FUNCTION_KEYS[i]) n = r.FUNCTION_KEYS[i].toLowerCase(); + else { + if (!t.length) return { key: n, hashId: -1 }; + if (t.length == 1 && t[0] == "shift") + return { key: n.toUpperCase(), hashId: -1 }; + } + var s = 0; + for (var o = t.length; o--; ) { + var u = r.KEY_MODS[t[o]]; + if (u == null) + return ( + typeof console != "undefined" && + console.error("invalid modifier " + t[o] + " in " + e), + !1 + ); + s |= u; + } + return { key: n, hashId: s }; + }), + (this.findKeyCommand = function (t, n) { + var r = s[t] + n; + return this.commandKeyBinding[r]; + }), + (this.handleKeyboard = function (e, t, n, r) { + if (r < 0) return; + var i = s[t] + n, + o = this.commandKeyBinding[i]; + e.$keyChain && + ((e.$keyChain += " " + i), + (o = this.commandKeyBinding[e.$keyChain] || o)); + if (o) + if (o == "chainKeys" || o[o.length - 1] == "chainKeys") + return (e.$keyChain = e.$keyChain || i), { command: "null" }; + if (e.$keyChain) + if ((!!t && t != 4) || n.length != 1) { + if (t == -1 || r > 0) e.$keyChain = ""; + } else e.$keyChain = e.$keyChain.slice(0, -i.length - 1); + return { command: o }; + }), + (this.getStatusText = function (e, t) { + return t.$keyChain || ""; + }); + }.call(o.prototype), + (t.HashHandler = o), + (t.MultiHashHandler = u); + }, + ), + define( + "ace/commands/command_manager", + [ + "require", + "exports", + "module", + "ace/lib/oop", + "ace/keyboard/hash_handler", + "ace/lib/event_emitter", + ], + function (e, t, n) { + "use strict"; + var r = e("../lib/oop"), + i = e("../keyboard/hash_handler").MultiHashHandler, + s = e("../lib/event_emitter").EventEmitter, + o = function (e, t) { + i.call(this, t, e), + (this.byName = this.commands), + this.setDefaultHandler("exec", function (e) { + return e.command.exec(e.editor, e.args || {}); + }); + }; + r.inherits(o, i), + function () { + r.implement(this, s), + (this.exec = function (e, t, n) { + if (Array.isArray(e)) { + for (var r = e.length; r--; ) if (this.exec(e[r], t, n)) return !0; + return !1; + } + typeof e == "string" && (e = this.commands[e]); + if (!e) return !1; + if (t && t.$readOnly && !e.readOnly) return !1; + if (this.$checkCommandState != 0 && e.isAvailable && !e.isAvailable(t)) + return !1; + var i = { editor: t, command: e, args: n }; + return ( + (i.returnValue = this._emit("exec", i)), + this._signal("afterExec", i), + i.returnValue === !1 ? !1 : !0 + ); + }), + (this.toggleRecording = function (e) { + if (this.$inReplay) return; + return ( + e && e._emit("changeStatus"), + this.recording + ? (this.macro.pop(), + this.removeEventListener("exec", this.$addCommandToMacro), + this.macro.length || (this.macro = this.oldMacro), + (this.recording = !1)) + : (this.$addCommandToMacro || + (this.$addCommandToMacro = function (e) { + this.macro.push([e.command, e.args]); + }.bind(this)), + (this.oldMacro = this.macro), + (this.macro = []), + this.on("exec", this.$addCommandToMacro), + (this.recording = !0)) + ); + }), + (this.replay = function (e) { + if (this.$inReplay || !this.macro) return; + if (this.recording) return this.toggleRecording(e); + try { + (this.$inReplay = !0), + this.macro.forEach(function (t) { + typeof t == "string" + ? this.exec(t, e) + : this.exec(t[0], e, t[1]); + }, this); + } finally { + this.$inReplay = !1; + } + }), + (this.trimMacro = function (e) { + return e.map(function (e) { + return ( + typeof e[0] != "string" && (e[0] = e[0].name), + e[1] || (e = e[0]), + e + ); + }); + }); + }.call(o.prototype), + (t.CommandManager = o); + }, + ), + define( + "ace/commands/default_commands", + ["require", "exports", "module", "ace/lib/lang", "ace/config", "ace/range"], + function (e, t, n) { + "use strict"; + function o(e, t) { + return { win: e, mac: t }; + } + var r = e("../lib/lang"), + i = e("../config"), + s = e("../range").Range; + t.commands = [ + { + name: "showSettingsMenu", + bindKey: o("Ctrl-,", "Command-,"), + exec: function (e) { + i.loadModule("ace/ext/settings_menu", function (t) { + t.init(e), e.showSettingsMenu(); + }); + }, + readOnly: !0, + }, + { + name: "goToNextError", + bindKey: o("Alt-E", "F4"), + exec: function (e) { + i.loadModule("./ext/error_marker", function (t) { + t.showErrorMarker(e, 1); + }); + }, + scrollIntoView: "animate", + readOnly: !0, + }, + { + name: "goToPreviousError", + bindKey: o("Alt-Shift-E", "Shift-F4"), + exec: function (e) { + i.loadModule("./ext/error_marker", function (t) { + t.showErrorMarker(e, -1); + }); + }, + scrollIntoView: "animate", + readOnly: !0, + }, + { + name: "selectall", + bindKey: o("Ctrl-A", "Command-A"), + exec: function (e) { + e.selectAll(); + }, + readOnly: !0, + }, + { + name: "centerselection", + bindKey: o(null, "Ctrl-L"), + exec: function (e) { + e.centerSelection(); + }, + readOnly: !0, + }, + { + name: "gotoline", + bindKey: o("Ctrl-L", "Command-L"), + exec: function (e, t) { + typeof t != "number" && (t = parseInt(prompt("Enter line number:"), 10)), + isNaN(t) || e.gotoLine(t); + }, + readOnly: !0, + }, + { + name: "fold", + bindKey: o("Alt-L|Ctrl-F1", "Command-Alt-L|Command-F1"), + exec: function (e) { + e.session.toggleFold(!1); + }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: !0, + }, + { + name: "unfold", + bindKey: o("Alt-Shift-L|Ctrl-Shift-F1", "Command-Alt-Shift-L|Command-Shift-F1"), + exec: function (e) { + e.session.toggleFold(!0); + }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: !0, + }, + { + name: "toggleFoldWidget", + bindKey: o("F2", "F2"), + exec: function (e) { + e.session.toggleFoldWidget(); + }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: !0, + }, + { + name: "toggleParentFoldWidget", + bindKey: o("Alt-F2", "Alt-F2"), + exec: function (e) { + e.session.toggleFoldWidget(!0); + }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: !0, + }, + { + name: "foldall", + bindKey: o(null, "Ctrl-Command-Option-0"), + exec: function (e) { + e.session.foldAll(); + }, + scrollIntoView: "center", + readOnly: !0, + }, + { + name: "foldOther", + bindKey: o("Alt-0", "Command-Option-0"), + exec: function (e) { + e.session.foldAll(), e.session.unfold(e.selection.getAllRanges()); + }, + scrollIntoView: "center", + readOnly: !0, + }, + { + name: "unfoldall", + bindKey: o("Alt-Shift-0", "Command-Option-Shift-0"), + exec: function (e) { + e.session.unfold(); + }, + scrollIntoView: "center", + readOnly: !0, + }, + { + name: "findnext", + bindKey: o("Ctrl-K", "Command-G"), + exec: function (e) { + e.findNext(); + }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: !0, + }, + { + name: "findprevious", + bindKey: o("Ctrl-Shift-K", "Command-Shift-G"), + exec: function (e) { + e.findPrevious(); + }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: !0, + }, + { + name: "selectOrFindNext", + bindKey: o("Alt-K", "Ctrl-G"), + exec: function (e) { + e.selection.isEmpty() ? e.selection.selectWord() : e.findNext(); + }, + readOnly: !0, + }, + { + name: "selectOrFindPrevious", + bindKey: o("Alt-Shift-K", "Ctrl-Shift-G"), + exec: function (e) { + e.selection.isEmpty() ? e.selection.selectWord() : e.findPrevious(); + }, + readOnly: !0, + }, + { + name: "find", + bindKey: o("Ctrl-F", "Command-F"), + exec: function (e) { + i.loadModule("ace/ext/searchbox", function (t) { + t.Search(e); + }); + }, + readOnly: !0, + }, + { + name: "overwrite", + bindKey: "Insert", + exec: function (e) { + e.toggleOverwrite(); + }, + readOnly: !0, + }, + { + name: "selecttostart", + bindKey: o("Ctrl-Shift-Home", "Command-Shift-Home|Command-Shift-Up"), + exec: function (e) { + e.getSelection().selectFileStart(); + }, + multiSelectAction: "forEach", + readOnly: !0, + scrollIntoView: "animate", + aceCommandGroup: "fileJump", + }, + { + name: "gotostart", + bindKey: o("Ctrl-Home", "Command-Home|Command-Up"), + exec: function (e) { + e.navigateFileStart(); + }, + multiSelectAction: "forEach", + readOnly: !0, + scrollIntoView: "animate", + aceCommandGroup: "fileJump", + }, + { + name: "selectup", + bindKey: o("Shift-Up", "Shift-Up|Ctrl-Shift-P"), + exec: function (e) { + e.getSelection().selectUp(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "golineup", + bindKey: o("Up", "Up|Ctrl-P"), + exec: function (e, t) { + e.navigateUp(t.times); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "selecttoend", + bindKey: o("Ctrl-Shift-End", "Command-Shift-End|Command-Shift-Down"), + exec: function (e) { + e.getSelection().selectFileEnd(); + }, + multiSelectAction: "forEach", + readOnly: !0, + scrollIntoView: "animate", + aceCommandGroup: "fileJump", + }, + { + name: "gotoend", + bindKey: o("Ctrl-End", "Command-End|Command-Down"), + exec: function (e) { + e.navigateFileEnd(); + }, + multiSelectAction: "forEach", + readOnly: !0, + scrollIntoView: "animate", + aceCommandGroup: "fileJump", + }, + { + name: "selectdown", + bindKey: o("Shift-Down", "Shift-Down|Ctrl-Shift-N"), + exec: function (e) { + e.getSelection().selectDown(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "golinedown", + bindKey: o("Down", "Down|Ctrl-N"), + exec: function (e, t) { + e.navigateDown(t.times); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "selectwordleft", + bindKey: o("Ctrl-Shift-Left", "Option-Shift-Left"), + exec: function (e) { + e.getSelection().selectWordLeft(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "gotowordleft", + bindKey: o("Ctrl-Left", "Option-Left"), + exec: function (e) { + e.navigateWordLeft(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "selecttolinestart", + bindKey: o("Alt-Shift-Left", "Command-Shift-Left|Ctrl-Shift-A"), + exec: function (e) { + e.getSelection().selectLineStart(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "gotolinestart", + bindKey: o("Alt-Left|Home", "Command-Left|Home|Ctrl-A"), + exec: function (e) { + e.navigateLineStart(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "selectleft", + bindKey: o("Shift-Left", "Shift-Left|Ctrl-Shift-B"), + exec: function (e) { + e.getSelection().selectLeft(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "gotoleft", + bindKey: o("Left", "Left|Ctrl-B"), + exec: function (e, t) { + e.navigateLeft(t.times); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "selectwordright", + bindKey: o("Ctrl-Shift-Right", "Option-Shift-Right"), + exec: function (e) { + e.getSelection().selectWordRight(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "gotowordright", + bindKey: o("Ctrl-Right", "Option-Right"), + exec: function (e) { + e.navigateWordRight(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "selecttolineend", + bindKey: o("Alt-Shift-Right", "Command-Shift-Right|Shift-End|Ctrl-Shift-E"), + exec: function (e) { + e.getSelection().selectLineEnd(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "gotolineend", + bindKey: o("Alt-Right|End", "Command-Right|End|Ctrl-E"), + exec: function (e) { + e.navigateLineEnd(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "selectright", + bindKey: o("Shift-Right", "Shift-Right"), + exec: function (e) { + e.getSelection().selectRight(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "gotoright", + bindKey: o("Right", "Right|Ctrl-F"), + exec: function (e, t) { + e.navigateRight(t.times); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "selectpagedown", + bindKey: "Shift-PageDown", + exec: function (e) { + e.selectPageDown(); + }, + readOnly: !0, + }, + { + name: "pagedown", + bindKey: o(null, "Option-PageDown"), + exec: function (e) { + e.scrollPageDown(); + }, + readOnly: !0, + }, + { + name: "gotopagedown", + bindKey: o("PageDown", "PageDown|Ctrl-V"), + exec: function (e) { + e.gotoPageDown(); + }, + readOnly: !0, + }, + { + name: "selectpageup", + bindKey: "Shift-PageUp", + exec: function (e) { + e.selectPageUp(); + }, + readOnly: !0, + }, + { + name: "pageup", + bindKey: o(null, "Option-PageUp"), + exec: function (e) { + e.scrollPageUp(); + }, + readOnly: !0, + }, + { + name: "gotopageup", + bindKey: "PageUp", + exec: function (e) { + e.gotoPageUp(); + }, + readOnly: !0, + }, + { + name: "scrollup", + bindKey: o("Ctrl-Up", null), + exec: function (e) { + e.renderer.scrollBy(0, -2 * e.renderer.layerConfig.lineHeight); + }, + readOnly: !0, + }, + { + name: "scrolldown", + bindKey: o("Ctrl-Down", null), + exec: function (e) { + e.renderer.scrollBy(0, 2 * e.renderer.layerConfig.lineHeight); + }, + readOnly: !0, + }, + { + name: "selectlinestart", + bindKey: "Shift-Home", + exec: function (e) { + e.getSelection().selectLineStart(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "selectlineend", + bindKey: "Shift-End", + exec: function (e) { + e.getSelection().selectLineEnd(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "togglerecording", + bindKey: o("Ctrl-Alt-E", "Command-Option-E"), + exec: function (e) { + e.commands.toggleRecording(e); + }, + readOnly: !0, + }, + { + name: "replaymacro", + bindKey: o("Ctrl-Shift-E", "Command-Shift-E"), + exec: function (e) { + e.commands.replay(e); + }, + readOnly: !0, + }, + { + name: "jumptomatching", + bindKey: o("Ctrl-P", "Ctrl-P"), + exec: function (e) { + e.jumpToMatching(); + }, + multiSelectAction: "forEach", + scrollIntoView: "animate", + readOnly: !0, + }, + { + name: "selecttomatching", + bindKey: o("Ctrl-Shift-P", "Ctrl-Shift-P"), + exec: function (e) { + e.jumpToMatching(!0); + }, + multiSelectAction: "forEach", + scrollIntoView: "animate", + readOnly: !0, + }, + { + name: "expandToMatching", + bindKey: o("Ctrl-Shift-M", "Ctrl-Shift-M"), + exec: function (e) { + e.jumpToMatching(!0, !0); + }, + multiSelectAction: "forEach", + scrollIntoView: "animate", + readOnly: !0, + }, + { + name: "passKeysToBrowser", + bindKey: o(null, null), + exec: function () {}, + passEvent: !0, + readOnly: !0, + }, + { name: "copy", exec: function (e) {}, readOnly: !0 }, + { + name: "cut", + exec: function (e) { + var t = e.$copyWithEmptySelection && e.selection.isEmpty(), + n = t ? e.selection.getLineRange() : e.selection.getRange(); + e._emit("cut", n), n.isEmpty() || e.session.remove(n), e.clearSelection(); + }, + scrollIntoView: "cursor", + multiSelectAction: "forEach", + }, + { + name: "paste", + exec: function (e, t) { + e.$handlePaste(t); + }, + scrollIntoView: "cursor", + }, + { + name: "removeline", + bindKey: o("Ctrl-D", "Command-D"), + exec: function (e) { + e.removeLines(); + }, + scrollIntoView: "cursor", + multiSelectAction: "forEachLine", + }, + { + name: "duplicateSelection", + bindKey: o("Ctrl-Shift-D", "Command-Shift-D"), + exec: function (e) { + e.duplicateSelection(); + }, + scrollIntoView: "cursor", + multiSelectAction: "forEach", + }, + { + name: "sortlines", + bindKey: o("Ctrl-Alt-S", "Command-Alt-S"), + exec: function (e) { + e.sortLines(); + }, + scrollIntoView: "selection", + multiSelectAction: "forEachLine", + }, + { + name: "togglecomment", + bindKey: o("Ctrl-/", "Command-/"), + exec: function (e) { + e.toggleCommentLines(); + }, + multiSelectAction: "forEachLine", + scrollIntoView: "selectionPart", + }, + { + name: "toggleBlockComment", + bindKey: o("Ctrl-Shift-/", "Command-Shift-/"), + exec: function (e) { + e.toggleBlockComment(); + }, + multiSelectAction: "forEach", + scrollIntoView: "selectionPart", + }, + { + name: "modifyNumberUp", + bindKey: o("Ctrl-Shift-Up", "Alt-Shift-Up"), + exec: function (e) { + e.modifyNumber(1); + }, + scrollIntoView: "cursor", + multiSelectAction: "forEach", + }, + { + name: "modifyNumberDown", + bindKey: o("Ctrl-Shift-Down", "Alt-Shift-Down"), + exec: function (e) { + e.modifyNumber(-1); + }, + scrollIntoView: "cursor", + multiSelectAction: "forEach", + }, + { + name: "replace", + bindKey: o("Ctrl-H", "Command-Option-F"), + exec: function (e) { + i.loadModule("ace/ext/searchbox", function (t) { + t.Search(e, !0); + }); + }, + }, + { + name: "undo", + bindKey: o("Ctrl-Z", "Command-Z"), + exec: function (e) { + e.undo(); + }, + }, + { + name: "redo", + bindKey: o("Ctrl-Shift-Z|Ctrl-Y", "Command-Shift-Z|Command-Y"), + exec: function (e) { + e.redo(); + }, + }, + { + name: "copylinesup", + bindKey: o("Alt-Shift-Up", "Command-Option-Up"), + exec: function (e) { + e.copyLinesUp(); + }, + scrollIntoView: "cursor", + }, + { + name: "movelinesup", + bindKey: o("Alt-Up", "Option-Up"), + exec: function (e) { + e.moveLinesUp(); + }, + scrollIntoView: "cursor", + }, + { + name: "copylinesdown", + bindKey: o("Alt-Shift-Down", "Command-Option-Down"), + exec: function (e) { + e.copyLinesDown(); + }, + scrollIntoView: "cursor", + }, + { + name: "movelinesdown", + bindKey: o("Alt-Down", "Option-Down"), + exec: function (e) { + e.moveLinesDown(); + }, + scrollIntoView: "cursor", + }, + { + name: "del", + bindKey: o("Delete", "Delete|Ctrl-D|Shift-Delete"), + exec: function (e) { + e.remove("right"); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + }, + { + name: "backspace", + bindKey: o( + "Shift-Backspace|Backspace", + "Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H", + ), + exec: function (e) { + e.remove("left"); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + }, + { + name: "cut_or_delete", + bindKey: o("Shift-Delete", null), + exec: function (e) { + if (!e.selection.isEmpty()) return !1; + e.remove("left"); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + }, + { + name: "removetolinestart", + bindKey: o("Alt-Backspace", "Command-Backspace"), + exec: function (e) { + e.removeToLineStart(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + }, + { + name: "removetolineend", + bindKey: o("Alt-Delete", "Ctrl-K|Command-Delete"), + exec: function (e) { + e.removeToLineEnd(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + }, + { + name: "removetolinestarthard", + bindKey: o("Ctrl-Shift-Backspace", null), + exec: function (e) { + var t = e.selection.getRange(); + (t.start.column = 0), e.session.remove(t); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + }, + { + name: "removetolineendhard", + bindKey: o("Ctrl-Shift-Delete", null), + exec: function (e) { + var t = e.selection.getRange(); + (t.end.column = Number.MAX_VALUE), e.session.remove(t); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + }, + { + name: "removewordleft", + bindKey: o("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"), + exec: function (e) { + e.removeWordLeft(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + }, + { + name: "removewordright", + bindKey: o("Ctrl-Delete", "Alt-Delete"), + exec: function (e) { + e.removeWordRight(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + }, + { + name: "outdent", + bindKey: o("Shift-Tab", "Shift-Tab"), + exec: function (e) { + e.blockOutdent(); + }, + multiSelectAction: "forEach", + scrollIntoView: "selectionPart", + }, + { + name: "indent", + bindKey: o("Tab", "Tab"), + exec: function (e) { + e.indent(); + }, + multiSelectAction: "forEach", + scrollIntoView: "selectionPart", + }, + { + name: "blockoutdent", + bindKey: o("Ctrl-[", "Ctrl-["), + exec: function (e) { + e.blockOutdent(); + }, + multiSelectAction: "forEachLine", + scrollIntoView: "selectionPart", + }, + { + name: "blockindent", + bindKey: o("Ctrl-]", "Ctrl-]"), + exec: function (e) { + e.blockIndent(); + }, + multiSelectAction: "forEachLine", + scrollIntoView: "selectionPart", + }, + { + name: "insertstring", + exec: function (e, t) { + e.insert(t); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + }, + { + name: "inserttext", + exec: function (e, t) { + e.insert(r.stringRepeat(t.text || "", t.times || 1)); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + }, + { + name: "splitline", + bindKey: o(null, "Ctrl-O"), + exec: function (e) { + e.splitLine(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + }, + { + name: "transposeletters", + bindKey: o("Alt-Shift-X", "Ctrl-T"), + exec: function (e) { + e.transposeLetters(); + }, + multiSelectAction: function (e) { + e.transposeSelections(1); + }, + scrollIntoView: "cursor", + }, + { + name: "touppercase", + bindKey: o("Ctrl-U", "Ctrl-U"), + exec: function (e) { + e.toUpperCase(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + }, + { + name: "tolowercase", + bindKey: o("Ctrl-Shift-U", "Ctrl-Shift-U"), + exec: function (e) { + e.toLowerCase(); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + }, + { + name: "expandtoline", + bindKey: o("Ctrl-Shift-L", "Command-Shift-L"), + exec: function (e) { + var t = e.selection.getRange(); + (t.start.column = t.end.column = 0), + t.end.row++, + e.selection.setRange(t, !1); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "joinlines", + bindKey: o(null, null), + exec: function (e) { + var t = e.selection.isBackwards(), + n = t + ? e.selection.getSelectionLead() + : e.selection.getSelectionAnchor(), + i = t + ? e.selection.getSelectionAnchor() + : e.selection.getSelectionLead(), + o = e.session.doc.getLine(n.row).length, + u = e.session.doc.getTextRange(e.selection.getRange()), + a = u.replace(/\n\s*/, " ").length, + f = e.session.doc.getLine(n.row); + for (var l = n.row + 1; l <= i.row + 1; l++) { + var c = r.stringTrimLeft(r.stringTrimRight(e.session.doc.getLine(l))); + c.length !== 0 && (c = " " + c), (f += c); + } + i.row + 1 < e.session.doc.getLength() - 1 && + (f += e.session.doc.getNewLineCharacter()), + e.clearSelection(), + e.session.doc.replace(new s(n.row, 0, i.row + 2, 0), f), + a > 0 + ? (e.selection.moveCursorTo(n.row, n.column), + e.selection.selectTo(n.row, n.column + a)) + : ((o = e.session.doc.getLine(n.row).length > o ? o + 1 : o), + e.selection.moveCursorTo(n.row, o)); + }, + multiSelectAction: "forEach", + readOnly: !0, + }, + { + name: "invertSelection", + bindKey: o(null, null), + exec: function (e) { + var t = e.session.doc.getLength() - 1, + n = e.session.doc.getLine(t).length, + r = e.selection.rangeList.ranges, + i = []; + r.length < 1 && (r = [e.selection.getRange()]); + for (var o = 0; o < r.length; o++) + o == r.length - 1 && + (r[o].end.row !== t || r[o].end.column !== n) && + i.push(new s(r[o].end.row, r[o].end.column, t, n)), + o === 0 + ? (r[o].start.row !== 0 || r[o].start.column !== 0) && + i.push(new s(0, 0, r[o].start.row, r[o].start.column)) + : i.push( + new s( + r[o - 1].end.row, + r[o - 1].end.column, + r[o].start.row, + r[o].start.column, + ), + ); + e.exitMultiSelectMode(), e.clearSelection(); + for (var o = 0; o < i.length; o++) e.selection.addRange(i[o], !1); + }, + readOnly: !0, + scrollIntoView: "none", + }, + ]; + }, + ), + define("ace/clipboard", ["require", "exports", "module"], function (e, t, n) { + "use strict"; + n.exports = { lineMode: !1 }; + }), + define( + "ace/editor", + [ + "require", + "exports", + "module", + "ace/lib/fixoldbrowsers", + "ace/lib/oop", + "ace/lib/dom", + "ace/lib/lang", + "ace/lib/useragent", + "ace/keyboard/textinput", + "ace/mouse/mouse_handler", + "ace/mouse/fold_handler", + "ace/keyboard/keybinding", + "ace/edit_session", + "ace/search", + "ace/range", + "ace/lib/event_emitter", + "ace/commands/command_manager", + "ace/commands/default_commands", + "ace/config", + "ace/token_iterator", + "ace/clipboard", + ], + function (e, t, n) { + "use strict"; + e("./lib/fixoldbrowsers"); + var r = e("./lib/oop"), + i = e("./lib/dom"), + s = e("./lib/lang"), + o = e("./lib/useragent"), + u = e("./keyboard/textinput").TextInput, + a = e("./mouse/mouse_handler").MouseHandler, + f = e("./mouse/fold_handler").FoldHandler, + l = e("./keyboard/keybinding").KeyBinding, + c = e("./edit_session").EditSession, + h = e("./search").Search, + p = e("./range").Range, + d = e("./lib/event_emitter").EventEmitter, + v = e("./commands/command_manager").CommandManager, + m = e("./commands/default_commands").commands, + g = e("./config"), + y = e("./token_iterator").TokenIterator, + b = e("./clipboard"), + w = function (e, t, n) { + var r = e.getContainerElement(); + (this.container = r), + (this.renderer = e), + (this.id = "editor" + ++w.$uid), + (this.commands = new v(o.isMac ? "mac" : "win", m)), + typeof document == "object" && + ((this.textInput = new u(e.getTextAreaContainer(), this)), + (this.renderer.textarea = this.textInput.getElement()), + (this.$mouseHandler = new a(this)), + new f(this)), + (this.keyBinding = new l(this)), + (this.$search = new h().set({ wrap: !0 })), + (this.$historyTracker = this.$historyTracker.bind(this)), + this.commands.on("exec", this.$historyTracker), + this.$initOperationListeners(), + (this._$emitInputEvent = s.delayedCall( + function () { + this._signal("input", {}), + this.session && + this.session.bgTokenizer && + this.session.bgTokenizer.scheduleStart(); + }.bind(this), + )), + this.on("change", function (e, t) { + t._$emitInputEvent.schedule(31); + }), + this.setSession(t || (n && n.session) || new c("")), + g.resetOptions(this), + n && this.setOptions(n), + g._signal("editor", this); + }; + (w.$uid = 0), + function () { + r.implement(this, d), + (this.$initOperationListeners = function () { + this.commands.on("exec", this.startOperation.bind(this), !0), + this.commands.on("afterExec", this.endOperation.bind(this), !0), + (this.$opResetTimer = s.delayedCall( + this.endOperation.bind(this, !0), + )), + this.on( + "change", + function () { + this.curOp || + (this.startOperation(), + (this.curOp.selectionBefore = this.$lastSel)), + (this.curOp.docChanged = !0); + }.bind(this), + !0, + ), + this.on( + "changeSelection", + function () { + this.curOp || + (this.startOperation(), + (this.curOp.selectionBefore = this.$lastSel)), + (this.curOp.selectionChanged = !0); + }.bind(this), + !0, + ); + }), + (this.curOp = null), + (this.prevOp = {}), + (this.startOperation = function (e) { + if (this.curOp) { + if (!e || this.curOp.command) return; + this.prevOp = this.curOp; + } + e || ((this.previousCommand = null), (e = {})), + this.$opResetTimer.schedule(), + (this.curOp = this.session.curOp = + { + command: e.command || {}, + args: e.args, + scrollTop: this.renderer.scrollTop, + }), + (this.curOp.selectionBefore = this.selection.toJSON()); + }), + (this.endOperation = function (e) { + if (this.curOp) { + if (e && e.returnValue === !1) return (this.curOp = null); + if ( + e == 1 && + this.curOp.command && + this.curOp.command.name == "mouse" + ) + return; + this._signal("beforeEndOperation"); + if (!this.curOp) return; + var t = this.curOp.command, + n = t && t.scrollIntoView; + if (n) { + switch (n) { + case "center-animate": + n = "animate"; + case "center": + this.renderer.scrollCursorIntoView(null, 0.5); + break; + case "animate": + case "cursor": + this.renderer.scrollCursorIntoView(); + break; + case "selectionPart": + var r = this.selection.getRange(), + i = this.renderer.layerConfig; + (r.start.row >= i.lastRow || r.end.row <= i.firstRow) && + this.renderer.scrollSelectionIntoView( + this.selection.anchor, + this.selection.lead, + ); + break; + default: + } + n == "animate" && + this.renderer.animateScrolling(this.curOp.scrollTop); + } + var s = this.selection.toJSON(); + (this.curOp.selectionAfter = s), + (this.$lastSel = this.selection.toJSON()), + this.session.getUndoManager().addSelection(s), + (this.prevOp = this.curOp), + (this.curOp = null); + } + }), + (this.$mergeableCommands = ["backspace", "del", "insertstring"]), + (this.$historyTracker = function (e) { + if (!this.$mergeUndoDeltas) return; + var t = this.prevOp, + n = this.$mergeableCommands, + r = t.command && e.command.name == t.command.name; + if (e.command.name == "insertstring") { + var i = e.args; + this.mergeNextCommand === undefined && (this.mergeNextCommand = !0), + (r = + r && + this.mergeNextCommand && + (!/\s/.test(i) || /\s/.test(t.args))), + (this.mergeNextCommand = !0); + } else r = r && n.indexOf(e.command.name) !== -1; + this.$mergeUndoDeltas != "always" && + Date.now() - this.sequenceStartTime > 2e3 && + (r = !1), + r + ? (this.session.mergeUndoDeltas = !0) + : n.indexOf(e.command.name) !== -1 && + (this.sequenceStartTime = Date.now()); + }), + (this.setKeyboardHandler = function (e, t) { + if (e && typeof e == "string" && e != "ace") { + this.$keybindingId = e; + var n = this; + g.loadModule(["keybinding", e], function (r) { + n.$keybindingId == e && + n.keyBinding.setKeyboardHandler(r && r.handler), + t && t(); + }); + } else + (this.$keybindingId = null), + this.keyBinding.setKeyboardHandler(e), + t && t(); + }), + (this.getKeyboardHandler = function () { + return this.keyBinding.getKeyboardHandler(); + }), + (this.setSession = function (e) { + if (this.session == e) return; + this.curOp && this.endOperation(), (this.curOp = {}); + var t = this.session; + if (t) { + this.session.off("change", this.$onDocumentChange), + this.session.off("changeMode", this.$onChangeMode), + this.session.off("tokenizerUpdate", this.$onTokenizerUpdate), + this.session.off("changeTabSize", this.$onChangeTabSize), + this.session.off("changeWrapLimit", this.$onChangeWrapLimit), + this.session.off("changeWrapMode", this.$onChangeWrapMode), + this.session.off("changeFold", this.$onChangeFold), + this.session.off( + "changeFrontMarker", + this.$onChangeFrontMarker, + ), + this.session.off("changeBackMarker", this.$onChangeBackMarker), + this.session.off("changeBreakpoint", this.$onChangeBreakpoint), + this.session.off("changeAnnotation", this.$onChangeAnnotation), + this.session.off("changeOverwrite", this.$onCursorChange), + this.session.off("changeScrollTop", this.$onScrollTopChange), + this.session.off("changeScrollLeft", this.$onScrollLeftChange); + var n = this.session.getSelection(); + n.off("changeCursor", this.$onCursorChange), + n.off("changeSelection", this.$onSelectionChange); + } + (this.session = e), + e + ? ((this.$onDocumentChange = this.onDocumentChange.bind(this)), + e.on("change", this.$onDocumentChange), + this.renderer.setSession(e), + (this.$onChangeMode = this.onChangeMode.bind(this)), + e.on("changeMode", this.$onChangeMode), + (this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this)), + e.on("tokenizerUpdate", this.$onTokenizerUpdate), + (this.$onChangeTabSize = this.renderer.onChangeTabSize.bind( + this.renderer, + )), + e.on("changeTabSize", this.$onChangeTabSize), + (this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this)), + e.on("changeWrapLimit", this.$onChangeWrapLimit), + (this.$onChangeWrapMode = this.onChangeWrapMode.bind(this)), + e.on("changeWrapMode", this.$onChangeWrapMode), + (this.$onChangeFold = this.onChangeFold.bind(this)), + e.on("changeFold", this.$onChangeFold), + (this.$onChangeFrontMarker = + this.onChangeFrontMarker.bind(this)), + this.session.on( + "changeFrontMarker", + this.$onChangeFrontMarker, + ), + (this.$onChangeBackMarker = + this.onChangeBackMarker.bind(this)), + this.session.on("changeBackMarker", this.$onChangeBackMarker), + (this.$onChangeBreakpoint = + this.onChangeBreakpoint.bind(this)), + this.session.on("changeBreakpoint", this.$onChangeBreakpoint), + (this.$onChangeAnnotation = + this.onChangeAnnotation.bind(this)), + this.session.on("changeAnnotation", this.$onChangeAnnotation), + (this.$onCursorChange = this.onCursorChange.bind(this)), + this.session.on("changeOverwrite", this.$onCursorChange), + (this.$onScrollTopChange = this.onScrollTopChange.bind(this)), + this.session.on("changeScrollTop", this.$onScrollTopChange), + (this.$onScrollLeftChange = + this.onScrollLeftChange.bind(this)), + this.session.on("changeScrollLeft", this.$onScrollLeftChange), + (this.selection = e.getSelection()), + this.selection.on("changeCursor", this.$onCursorChange), + (this.$onSelectionChange = this.onSelectionChange.bind(this)), + this.selection.on("changeSelection", this.$onSelectionChange), + this.onChangeMode(), + this.onCursorChange(), + this.onScrollTopChange(), + this.onScrollLeftChange(), + this.onSelectionChange(), + this.onChangeFrontMarker(), + this.onChangeBackMarker(), + this.onChangeBreakpoint(), + this.onChangeAnnotation(), + this.session.getUseWrapMode() && + this.renderer.adjustWrapLimit(), + this.renderer.updateFull()) + : ((this.selection = null), this.renderer.setSession(e)), + this._signal("changeSession", { session: e, oldSession: t }), + (this.curOp = null), + t && t._signal("changeEditor", { oldEditor: this }), + e && e._signal("changeEditor", { editor: this }), + e && e.bgTokenizer && e.bgTokenizer.scheduleStart(); + }), + (this.getSession = function () { + return this.session; + }), + (this.setValue = function (e, t) { + return ( + this.session.doc.setValue(e), + t + ? t == 1 + ? this.navigateFileEnd() + : t == -1 && this.navigateFileStart() + : this.selectAll(), + e + ); + }), + (this.getValue = function () { + return this.session.getValue(); + }), + (this.getSelection = function () { + return this.selection; + }), + (this.resize = function (e) { + this.renderer.onResize(e); + }), + (this.setTheme = function (e, t) { + this.renderer.setTheme(e, t); + }), + (this.getTheme = function () { + return this.renderer.getTheme(); + }), + (this.setStyle = function (e) { + this.renderer.setStyle(e); + }), + (this.unsetStyle = function (e) { + this.renderer.unsetStyle(e); + }), + (this.getFontSize = function () { + return ( + this.getOption("fontSize") || + i.computedStyle(this.container).fontSize + ); + }), + (this.setFontSize = function (e) { + this.setOption("fontSize", e); + }), + (this.$highlightBrackets = function () { + this.session.$bracketHighlight && + (this.session.removeMarker(this.session.$bracketHighlight), + (this.session.$bracketHighlight = null)); + if (this.$highlightPending) return; + var e = this; + (this.$highlightPending = !0), + setTimeout(function () { + e.$highlightPending = !1; + var t = e.session; + if (!t || !t.bgTokenizer) return; + var n = t.findMatchingBracket(e.getCursorPosition()); + if (n) var r = new p(n.row, n.column, n.row, n.column + 1); + else if (t.$mode.getMatching) + var r = t.$mode.getMatching(e.session); + r && + (t.$bracketHighlight = t.addMarker( + r, + "ace_bracket", + "text", + )); + }, 50); + }), + (this.$highlightTags = function () { + if (this.$highlightTagPending) return; + var e = this; + (this.$highlightTagPending = !0), + setTimeout(function () { + e.$highlightTagPending = !1; + var t = e.session; + if (!t || !t.bgTokenizer) return; + var n = e.getCursorPosition(), + r = new y(e.session, n.row, n.column), + i = r.getCurrentToken(); + if (!i || !/\b(?:tag-open|tag-name)/.test(i.type)) { + t.removeMarker(t.$tagHighlight), (t.$tagHighlight = null); + return; + } + if (i.type.indexOf("tag-open") != -1) { + i = r.stepForward(); + if (!i) return; + } + var s = i.value, + o = 0, + u = r.stepBackward(); + if (u.value == "<") { + do + (u = i), + (i = r.stepForward()), + i && + i.value === s && + i.type.indexOf("tag-name") !== -1 && + (u.value === "<" + ? o++ + : u.value === "= 0); + } else { + do + (i = u), + (u = r.stepBackward()), + i && + i.value === s && + i.type.indexOf("tag-name") !== -1 && + (u.value === "<" + ? o++ + : u.value === " 1) && + (t = !1); + } + if (e.$highlightLineMarker && !t) + e.removeMarker(e.$highlightLineMarker.id), + (e.$highlightLineMarker = null); + else if (!e.$highlightLineMarker && t) { + var n = new p(t.row, t.column, t.row, Infinity); + (n.id = e.addMarker(n, "ace_active-line", "screenLine")), + (e.$highlightLineMarker = n); + } else + t && + ((e.$highlightLineMarker.start.row = t.row), + (e.$highlightLineMarker.end.row = t.row), + (e.$highlightLineMarker.start.column = t.column), + e._signal("changeBackMarker")); + }), + (this.onSelectionChange = function (e) { + var t = this.session; + t.$selectionMarker && t.removeMarker(t.$selectionMarker), + (t.$selectionMarker = null); + if (!this.selection.isEmpty()) { + var n = this.selection.getRange(), + r = this.getSelectionStyle(); + t.$selectionMarker = t.addMarker(n, "ace_selection", r); + } else this.$updateHighlightActiveLine(); + var i = + this.$highlightSelectedWord && this.$getSelectionHighLightRegexp(); + this.session.highlight(i), this._signal("changeSelection"); + }), + (this.$getSelectionHighLightRegexp = function () { + var e = this.session, + t = this.getSelectionRange(); + if (t.isEmpty() || t.isMultiLine()) return; + var n = t.start.column, + r = t.end.column, + i = e.getLine(t.start.row), + s = i.substring(n, r); + if (s.length > 5e3 || !/[\w\d]/.test(s)) return; + var o = this.$search.$assembleRegExp({ + wholeWord: !0, + caseSensitive: !0, + needle: s, + }), + u = i.substring(n - 1, r + 1); + if (!o.test(u)) return; + return o; + }), + (this.onChangeFrontMarker = function () { + this.renderer.updateFrontMarkers(); + }), + (this.onChangeBackMarker = function () { + this.renderer.updateBackMarkers(); + }), + (this.onChangeBreakpoint = function () { + this.renderer.updateBreakpoints(); + }), + (this.onChangeAnnotation = function () { + this.renderer.setAnnotations(this.session.getAnnotations()); + }), + (this.onChangeMode = function (e) { + this.renderer.updateText(), this._emit("changeMode", e); + }), + (this.onChangeWrapLimit = function () { + this.renderer.updateFull(); + }), + (this.onChangeWrapMode = function () { + this.renderer.onResize(!0); + }), + (this.onChangeFold = function () { + this.$updateHighlightActiveLine(), this.renderer.updateFull(); + }), + (this.getSelectedText = function () { + return this.session.getTextRange(this.getSelectionRange()); + }), + (this.getCopyText = function () { + var e = this.getSelectedText(), + t = this.session.doc.getNewLineCharacter(), + n = !1; + if (!e && this.$copyWithEmptySelection) { + n = !0; + var r = this.selection.getAllRanges(); + for (var i = 0; i < r.length; i++) { + var s = r[i]; + if (i && r[i - 1].start.row == s.start.row) continue; + e += this.session.getLine(s.start.row) + t; + } + } + var o = { text: e }; + return this._signal("copy", o), (b.lineMode = n ? o.text : ""), o.text; + }), + (this.onCopy = function () { + this.commands.exec("copy", this); + }), + (this.onCut = function () { + this.commands.exec("cut", this); + }), + (this.onPaste = function (e, t) { + var n = { text: e, event: t }; + this.commands.exec("paste", this, n); + }), + (this.$handlePaste = function (e) { + typeof e == "string" && (e = { text: e }), this._signal("paste", e); + var t = e.text, + n = t == b.lineMode, + r = this.session; + if (!this.inMultiSelectMode || this.inVirtualSelectionMode) + n + ? r.insert({ row: this.selection.lead.row, column: 0 }, t) + : this.insert(t); + else if (n) + this.selection.rangeList.ranges.forEach(function (e) { + r.insert({ row: e.start.row, column: 0 }, t); + }); + else { + var i = t.split(/\r\n|\r|\n/), + s = this.selection.rangeList.ranges; + if (i.length > s.length || i.length < 2 || !i[1]) + return this.commands.exec("insertstring", this, t); + for (var o = s.length; o--; ) { + var u = s[o]; + u.isEmpty() || r.remove(u), r.insert(u.start, i[o]); + } + } + }), + (this.execCommand = function (e, t) { + return this.commands.exec(e, this, t); + }), + (this.insert = function (e, t) { + var n = this.session, + r = n.getMode(), + i = this.getCursorPosition(); + if (this.getBehavioursEnabled() && !t) { + var s = r.transformAction( + n.getState(i.row), + "insertion", + this, + n, + e, + ); + s && + (e !== s.text && + (this.inVirtualSelectionMode || + ((this.session.mergeUndoDeltas = !1), + (this.mergeNextCommand = !1))), + (e = s.text)); + } + e == " " && (e = this.session.getTabString()); + if (!this.selection.isEmpty()) { + var o = this.getSelectionRange(); + (i = this.session.remove(o)), this.clearSelection(); + } else if (this.session.getOverwrite() && e.indexOf("\n") == -1) { + var o = new p.fromPoints(i, i); + (o.end.column += e.length), this.session.remove(o); + } + if (e == "\n" || e == "\r\n") { + var u = n.getLine(i.row); + if (i.column > u.search(/\S|$/)) { + var a = u.substr(i.column).search(/\S|$/); + n.doc.removeInLine(i.row, i.column, i.column + a); + } + } + this.clearSelection(); + var f = i.column, + l = n.getState(i.row), + u = n.getLine(i.row), + c = r.checkOutdent(l, u, e), + h = n.insert(i, e); + s && + s.selection && + (s.selection.length == 2 + ? this.selection.setSelectionRange( + new p( + i.row, + f + s.selection[0], + i.row, + f + s.selection[1], + ), + ) + : this.selection.setSelectionRange( + new p( + i.row + s.selection[0], + s.selection[1], + i.row + s.selection[2], + s.selection[3], + ), + )); + if (n.getDocument().isNewLine(e)) { + var d = r.getNextLineIndent( + l, + u.slice(0, i.column), + n.getTabString(), + ); + n.insert({ row: i.row + 1, column: 0 }, d); + } + c && r.autoOutdent(l, n, i.row); + }), + (this.onTextInput = function (e, t) { + if (!t) return this.keyBinding.onTextInput(e); + this.startOperation({ command: { name: "insertstring" } }); + var n = this.applyComposition.bind(this, e, t); + this.selection.rangeCount ? this.forEachSelection(n) : n(), + this.endOperation(); + }), + (this.applyComposition = function (e, t) { + if (t.extendLeft || t.extendRight) { + var n = this.selection.getRange(); + (n.start.column -= t.extendLeft), + (n.end.column += t.extendRight), + this.selection.setRange(n), + !e && !n.isEmpty() && this.remove(); + } + (e || !this.selection.isEmpty()) && this.insert(e, !0); + if (t.restoreStart || t.restoreEnd) { + var n = this.selection.getRange(); + (n.start.column -= t.restoreStart), + (n.end.column -= t.restoreEnd), + this.selection.setRange(n); + } + }), + (this.onCommandKey = function (e, t, n) { + this.keyBinding.onCommandKey(e, t, n); + }), + (this.setOverwrite = function (e) { + this.session.setOverwrite(e); + }), + (this.getOverwrite = function () { + return this.session.getOverwrite(); + }), + (this.toggleOverwrite = function () { + this.session.toggleOverwrite(); + }), + (this.setScrollSpeed = function (e) { + this.setOption("scrollSpeed", e); + }), + (this.getScrollSpeed = function () { + return this.getOption("scrollSpeed"); + }), + (this.setDragDelay = function (e) { + this.setOption("dragDelay", e); + }), + (this.getDragDelay = function () { + return this.getOption("dragDelay"); + }), + (this.setSelectionStyle = function (e) { + this.setOption("selectionStyle", e); + }), + (this.getSelectionStyle = function () { + return this.getOption("selectionStyle"); + }), + (this.setHighlightActiveLine = function (e) { + this.setOption("highlightActiveLine", e); + }), + (this.getHighlightActiveLine = function () { + return this.getOption("highlightActiveLine"); + }), + (this.setHighlightGutterLine = function (e) { + this.setOption("highlightGutterLine", e); + }), + (this.getHighlightGutterLine = function () { + return this.getOption("highlightGutterLine"); + }), + (this.setHighlightSelectedWord = function (e) { + this.setOption("highlightSelectedWord", e); + }), + (this.getHighlightSelectedWord = function () { + return this.$highlightSelectedWord; + }), + (this.setAnimatedScroll = function (e) { + this.renderer.setAnimatedScroll(e); + }), + (this.getAnimatedScroll = function () { + return this.renderer.getAnimatedScroll(); + }), + (this.setShowInvisibles = function (e) { + this.renderer.setShowInvisibles(e); + }), + (this.getShowInvisibles = function () { + return this.renderer.getShowInvisibles(); + }), + (this.setDisplayIndentGuides = function (e) { + this.renderer.setDisplayIndentGuides(e); + }), + (this.getDisplayIndentGuides = function () { + return this.renderer.getDisplayIndentGuides(); + }), + (this.setShowPrintMargin = function (e) { + this.renderer.setShowPrintMargin(e); + }), + (this.getShowPrintMargin = function () { + return this.renderer.getShowPrintMargin(); + }), + (this.setPrintMarginColumn = function (e) { + this.renderer.setPrintMarginColumn(e); + }), + (this.getPrintMarginColumn = function () { + return this.renderer.getPrintMarginColumn(); + }), + (this.setReadOnly = function (e) { + this.setOption("readOnly", e); + }), + (this.getReadOnly = function () { + return this.getOption("readOnly"); + }), + (this.setBehavioursEnabled = function (e) { + this.setOption("behavioursEnabled", e); + }), + (this.getBehavioursEnabled = function () { + return this.getOption("behavioursEnabled"); + }), + (this.setWrapBehavioursEnabled = function (e) { + this.setOption("wrapBehavioursEnabled", e); + }), + (this.getWrapBehavioursEnabled = function () { + return this.getOption("wrapBehavioursEnabled"); + }), + (this.setShowFoldWidgets = function (e) { + this.setOption("showFoldWidgets", e); + }), + (this.getShowFoldWidgets = function () { + return this.getOption("showFoldWidgets"); + }), + (this.setFadeFoldWidgets = function (e) { + this.setOption("fadeFoldWidgets", e); + }), + (this.getFadeFoldWidgets = function () { + return this.getOption("fadeFoldWidgets"); + }), + (this.remove = function (e) { + this.selection.isEmpty() && + (e == "left" + ? this.selection.selectLeft() + : this.selection.selectRight()); + var t = this.getSelectionRange(); + if (this.getBehavioursEnabled()) { + var n = this.session, + r = n.getState(t.start.row), + i = n.getMode().transformAction(r, "deletion", this, n, t); + if (t.end.column === 0) { + var s = n.getTextRange(t); + if (s[s.length - 1] == "\n") { + var o = n.getLine(t.end.row); + /^\s+$/.test(o) && (t.end.column = o.length); + } + } + i && (t = i); + } + this.session.remove(t), this.clearSelection(); + }), + (this.removeWordRight = function () { + this.selection.isEmpty() && this.selection.selectWordRight(), + this.session.remove(this.getSelectionRange()), + this.clearSelection(); + }), + (this.removeWordLeft = function () { + this.selection.isEmpty() && this.selection.selectWordLeft(), + this.session.remove(this.getSelectionRange()), + this.clearSelection(); + }), + (this.removeToLineStart = function () { + this.selection.isEmpty() && this.selection.selectLineStart(), + this.session.remove(this.getSelectionRange()), + this.clearSelection(); + }), + (this.removeToLineEnd = function () { + this.selection.isEmpty() && this.selection.selectLineEnd(); + var e = this.getSelectionRange(); + e.start.column == e.end.column && + e.start.row == e.end.row && + ((e.end.column = 0), e.end.row++), + this.session.remove(e), + this.clearSelection(); + }), + (this.splitLine = function () { + this.selection.isEmpty() || + (this.session.remove(this.getSelectionRange()), + this.clearSelection()); + var e = this.getCursorPosition(); + this.insert("\n"), this.moveCursorToPosition(e); + }), + (this.transposeLetters = function () { + if (!this.selection.isEmpty()) return; + var e = this.getCursorPosition(), + t = e.column; + if (t === 0) return; + var n = this.session.getLine(e.row), + r, + i; + t < n.length + ? ((r = n.charAt(t) + n.charAt(t - 1)), + (i = new p(e.row, t - 1, e.row, t + 1))) + : ((r = n.charAt(t - 1) + n.charAt(t - 2)), + (i = new p(e.row, t - 2, e.row, t))), + this.session.replace(i, r), + this.session.selection.moveToPosition(i.end); + }), + (this.toLowerCase = function () { + var e = this.getSelectionRange(); + this.selection.isEmpty() && this.selection.selectWord(); + var t = this.getSelectionRange(), + n = this.session.getTextRange(t); + this.session.replace(t, n.toLowerCase()), + this.selection.setSelectionRange(e); + }), + (this.toUpperCase = function () { + var e = this.getSelectionRange(); + this.selection.isEmpty() && this.selection.selectWord(); + var t = this.getSelectionRange(), + n = this.session.getTextRange(t); + this.session.replace(t, n.toUpperCase()), + this.selection.setSelectionRange(e); + }), + (this.indent = function () { + var e = this.session, + t = this.getSelectionRange(); + if (t.start.row < t.end.row) { + var n = this.$getSelectedRows(); + e.indentRows(n.first, n.last, " "); + return; + } + if (t.start.column < t.end.column) { + var r = e.getTextRange(t); + if (!/^\s+$/.test(r)) { + var n = this.$getSelectedRows(); + e.indentRows(n.first, n.last, " "); + return; + } + } + var i = e.getLine(t.start.row), + o = t.start, + u = e.getTabSize(), + a = e.documentToScreenColumn(o.row, o.column); + if (this.session.getUseSoftTabs()) + var f = u - (a % u), + l = s.stringRepeat(" ", f); + else { + var f = a % u; + while (i[t.start.column - 1] == " " && f) t.start.column--, f--; + this.selection.setSelectionRange(t), (l = " "); + } + return this.insert(l); + }), + (this.blockIndent = function () { + var e = this.$getSelectedRows(); + this.session.indentRows(e.first, e.last, " "); + }), + (this.blockOutdent = function () { + var e = this.session.getSelection(); + this.session.outdentRows(e.getRange()); + }), + (this.sortLines = function () { + var e = this.$getSelectedRows(), + t = this.session, + n = []; + for (var r = e.first; r <= e.last; r++) n.push(t.getLine(r)); + n.sort(function (e, t) { + return e.toLowerCase() < t.toLowerCase() + ? -1 + : e.toLowerCase() > t.toLowerCase() + ? 1 + : 0; + }); + var i = new p(0, 0, 0, 0); + for (var r = e.first; r <= e.last; r++) { + var s = t.getLine(r); + (i.start.row = r), + (i.end.row = r), + (i.end.column = s.length), + t.replace(i, n[r - e.first]); + } + }), + (this.toggleCommentLines = function () { + var e = this.session.getState(this.getCursorPosition().row), + t = this.$getSelectedRows(); + this.session + .getMode() + .toggleCommentLines(e, this.session, t.first, t.last); + }), + (this.toggleBlockComment = function () { + var e = this.getCursorPosition(), + t = this.session.getState(e.row), + n = this.getSelectionRange(); + this.session.getMode().toggleBlockComment(t, this.session, n, e); + }), + (this.getNumberAt = function (e, t) { + var n = /[\-]?[0-9]+(?:\.[0-9]+)?/g; + n.lastIndex = 0; + var r = this.session.getLine(e); + while (n.lastIndex < t) { + var i = n.exec(r); + if (i.index <= t && i.index + i[0].length >= t) { + var s = { + value: i[0], + start: i.index, + end: i.index + i[0].length, + }; + return s; + } + } + return null; + }), + (this.modifyNumber = function (e) { + var t = this.selection.getCursor().row, + n = this.selection.getCursor().column, + r = new p(t, n - 1, t, n), + i = this.session.getTextRange(r); + if (!isNaN(parseFloat(i)) && isFinite(i)) { + var s = this.getNumberAt(t, n); + if (s) { + var o = + s.value.indexOf(".") >= 0 + ? s.start + s.value.indexOf(".") + 1 + : s.end, + u = s.start + s.value.length - o, + a = parseFloat(s.value); + (a *= Math.pow(10, u)), + o !== s.end && n < o + ? (e *= Math.pow(10, s.end - n - 1)) + : (e *= Math.pow(10, s.end - n)), + (a += e), + (a /= Math.pow(10, u)); + var f = a.toFixed(u), + l = new p(t, s.start, t, s.end); + this.session.replace(l, f), + this.moveCursorTo( + t, + Math.max(s.start + 1, n + f.length - s.value.length), + ); + } + } else this.toggleWord(); + }), + (this.$toggleWordPairs = [ + ["first", "last"], + ["true", "false"], + ["yes", "no"], + ["width", "height"], + ["top", "bottom"], + ["right", "left"], + ["on", "off"], + ["x", "y"], + ["get", "set"], + ["max", "min"], + ["horizontal", "vertical"], + ["show", "hide"], + ["add", "remove"], + ["up", "down"], + ["before", "after"], + ["even", "odd"], + ["inside", "outside"], + ["next", "previous"], + ["increase", "decrease"], + ["attach", "detach"], + ["&&", "||"], + ["==", "!="], + ]), + (this.toggleWord = function () { + var e = this.selection.getCursor().row, + t = this.selection.getCursor().column; + this.selection.selectWord(); + var n = this.getSelectedText(), + r = this.selection.getWordRange().start.column, + i = n.replace(/([a-z]+|[A-Z]+)(?=[A-Z_]|$)/g, "$1 ").split(/\s/), + o = t - r - 1; + o < 0 && (o = 0); + var u = 0, + a = 0, + f = this; + n.match(/[A-Za-z0-9_]+/) && + i.forEach(function (t, i) { + (a = u + t.length), + o >= u && + o <= a && + ((n = t), + f.selection.clearSelection(), + f.moveCursorTo(e, u + r), + f.selection.selectTo(e, a + r)), + (u = a); + }); + var l = this.$toggleWordPairs, + c; + for (var h = 0; h < l.length; h++) { + var p = l[h]; + for (var d = 0; d <= 1; d++) { + var v = +!d, + m = n.match( + new RegExp( + "^\\s?_?(" + s.escapeRegExp(p[d]) + ")\\s?$", + "i", + ), + ); + if (m) { + var g = n.match( + new RegExp( + "([_]|^|\\s)(" + s.escapeRegExp(m[1]) + ")($|\\s)", + "g", + ), + ); + g && + ((c = n.replace( + new RegExp(s.escapeRegExp(p[d]), "i"), + function (e) { + var t = p[v]; + return ( + e.toUpperCase() == e + ? (t = t.toUpperCase()) + : e.charAt(0).toUpperCase() == + e.charAt(0) && + (t = + t.substr(0, 0) + + p[v].charAt(0).toUpperCase() + + t.substr(1)), + t + ); + }, + )), + this.insert(c), + (c = "")); + } + } + } + }), + (this.removeLines = function () { + var e = this.$getSelectedRows(); + this.session.removeFullLines(e.first, e.last), this.clearSelection(); + }), + (this.duplicateSelection = function () { + var e = this.selection, + t = this.session, + n = e.getRange(), + r = e.isBackwards(); + if (n.isEmpty()) { + var i = n.start.row; + t.duplicateLines(i, i); + } else { + var s = r ? n.start : n.end, + o = t.insert(s, t.getTextRange(n), !1); + (n.start = s), (n.end = o), e.setSelectionRange(n, r); + } + }), + (this.moveLinesDown = function () { + this.$moveLines(1, !1); + }), + (this.moveLinesUp = function () { + this.$moveLines(-1, !1); + }), + (this.moveText = function (e, t, n) { + return this.session.moveText(e, t, n); + }), + (this.copyLinesUp = function () { + this.$moveLines(-1, !0); + }), + (this.copyLinesDown = function () { + this.$moveLines(1, !0); + }), + (this.$moveLines = function (e, t) { + var n, + r, + i = this.selection; + if (!i.inMultiSelectMode || this.inVirtualSelectionMode) { + var s = i.toOrientedRange(); + (n = this.$getSelectedRows(s)), + (r = this.session.$moveLines(n.first, n.last, t ? 0 : e)), + t && e == -1 && (r = 0), + s.moveBy(r, 0), + i.fromOrientedRange(s); + } else { + var o = i.rangeList.ranges; + i.rangeList.detach(this.session), + (this.inVirtualSelectionMode = !0); + var u = 0, + a = 0, + f = o.length; + for (var l = 0; l < f; l++) { + var c = l; + o[l].moveBy(u, 0), (n = this.$getSelectedRows(o[l])); + var h = n.first, + p = n.last; + while (++l < f) { + a && o[l].moveBy(a, 0); + var d = this.$getSelectedRows(o[l]); + if (t && d.first != p) break; + if (!t && d.first > p + 1) break; + p = d.last; + } + l--, + (u = this.session.$moveLines(h, p, t ? 0 : e)), + t && e == -1 && (c = l + 1); + while (c <= l) o[c].moveBy(u, 0), c++; + t || (u = 0), (a += u); + } + i.fromOrientedRange(i.ranges[0]), + i.rangeList.attach(this.session), + (this.inVirtualSelectionMode = !1); + } + }), + (this.$getSelectedRows = function (e) { + return ( + (e = (e || this.getSelectionRange()).collapseRows()), + { + first: this.session.getRowFoldStart(e.start.row), + last: this.session.getRowFoldEnd(e.end.row), + } + ); + }), + (this.onCompositionStart = function (e) { + this.renderer.showComposition(e); + }), + (this.onCompositionUpdate = function (e) { + this.renderer.setCompositionText(e); + }), + (this.onCompositionEnd = function () { + this.renderer.hideComposition(); + }), + (this.getFirstVisibleRow = function () { + return this.renderer.getFirstVisibleRow(); + }), + (this.getLastVisibleRow = function () { + return this.renderer.getLastVisibleRow(); + }), + (this.isRowVisible = function (e) { + return e >= this.getFirstVisibleRow() && e <= this.getLastVisibleRow(); + }), + (this.isRowFullyVisible = function (e) { + return ( + e >= this.renderer.getFirstFullyVisibleRow() && + e <= this.renderer.getLastFullyVisibleRow() + ); + }), + (this.$getVisibleRowCount = function () { + return ( + this.renderer.getScrollBottomRow() - + this.renderer.getScrollTopRow() + + 1 + ); + }), + (this.$moveByPage = function (e, t) { + var n = this.renderer, + r = this.renderer.layerConfig, + i = e * Math.floor(r.height / r.lineHeight); + t === !0 + ? this.selection.$moveSelection(function () { + this.moveCursorBy(i, 0); + }) + : t === !1 && + (this.selection.moveCursorBy(i, 0), + this.selection.clearSelection()); + var s = n.scrollTop; + n.scrollBy(0, i * r.lineHeight), + t != null && n.scrollCursorIntoView(null, 0.5), + n.animateScrolling(s); + }), + (this.selectPageDown = function () { + this.$moveByPage(1, !0); + }), + (this.selectPageUp = function () { + this.$moveByPage(-1, !0); + }), + (this.gotoPageDown = function () { + this.$moveByPage(1, !1); + }), + (this.gotoPageUp = function () { + this.$moveByPage(-1, !1); + }), + (this.scrollPageDown = function () { + this.$moveByPage(1); + }), + (this.scrollPageUp = function () { + this.$moveByPage(-1); + }), + (this.scrollToRow = function (e) { + this.renderer.scrollToRow(e); + }), + (this.scrollToLine = function (e, t, n, r) { + this.renderer.scrollToLine(e, t, n, r); + }), + (this.centerSelection = function () { + var e = this.getSelectionRange(), + t = { + row: Math.floor(e.start.row + (e.end.row - e.start.row) / 2), + column: Math.floor( + e.start.column + (e.end.column - e.start.column) / 2, + ), + }; + this.renderer.alignCursor(t, 0.5); + }), + (this.getCursorPosition = function () { + return this.selection.getCursor(); + }), + (this.getCursorPositionScreen = function () { + return this.session.documentToScreenPosition(this.getCursorPosition()); + }), + (this.getSelectionRange = function () { + return this.selection.getRange(); + }), + (this.selectAll = function () { + this.selection.selectAll(); + }), + (this.clearSelection = function () { + this.selection.clearSelection(); + }), + (this.moveCursorTo = function (e, t) { + this.selection.moveCursorTo(e, t); + }), + (this.moveCursorToPosition = function (e) { + this.selection.moveCursorToPosition(e); + }), + (this.jumpToMatching = function (e, t) { + var n = this.getCursorPosition(), + r = new y(this.session, n.row, n.column), + i = r.getCurrentToken(), + s = i || r.stepForward(); + if (!s) return; + var o, + u = !1, + a = {}, + f = n.column - s.start, + l, + c = { ")": "(", "(": "(", "]": "[", "[": "[", "{": "{", "}": "{" }; + do { + if (s.value.match(/[{}()\[\]]/g)) + for (; f < s.value.length && !u; f++) { + if (!c[s.value[f]]) continue; + (l = + c[s.value[f]] + + "." + + s.type.replace("rparen", "lparen")), + isNaN(a[l]) && (a[l] = 0); + switch (s.value[f]) { + case "(": + case "[": + case "{": + a[l]++; + break; + case ")": + case "]": + case "}": + a[l]--, a[l] === -1 && ((o = "bracket"), (u = !0)); + } + } + else + s.type.indexOf("tag-name") !== -1 && + (isNaN(a[s.value]) && (a[s.value] = 0), + i.value === "<" + ? a[s.value]++ + : i.value === "= 0; --s) + this.$tryReplace(n[s], e) && r++; + return this.selection.setSelectionRange(i), r; + }), + (this.$tryReplace = function (e, t) { + var n = this.session.getTextRange(e); + return ( + (t = this.$search.replace(n, t)), + t !== null ? ((e.end = this.session.replace(e, t)), e) : null + ); + }), + (this.getLastSearchOptions = function () { + return this.$search.getOptions(); + }), + (this.find = function (e, t, n) { + t || (t = {}), + typeof e == "string" || e instanceof RegExp + ? (t.needle = e) + : typeof e == "object" && r.mixin(t, e); + var i = this.selection.getRange(); + t.needle == null && + ((e = this.session.getTextRange(i) || this.$search.$options.needle), + e || + ((i = this.session.getWordRange(i.start.row, i.start.column)), + (e = this.session.getTextRange(i))), + this.$search.set({ needle: e })), + this.$search.set(t), + t.start || this.$search.set({ start: i }); + var s = this.$search.find(this.session); + if (t.preventScroll) return s; + if (s) return this.revealRange(s, n), s; + t.backwards ? (i.start = i.end) : (i.end = i.start), + this.selection.setRange(i); + }), + (this.findNext = function (e, t) { + this.find({ skipCurrent: !0, backwards: !1 }, e, t); + }), + (this.findPrevious = function (e, t) { + this.find(e, { skipCurrent: !0, backwards: !0 }, t); + }), + (this.revealRange = function (e, t) { + this.session.unfold(e), this.selection.setSelectionRange(e); + var n = this.renderer.scrollTop; + this.renderer.scrollSelectionIntoView(e.start, e.end, 0.5), + t !== !1 && this.renderer.animateScrolling(n); + }), + (this.undo = function () { + this.session.getUndoManager().undo(this.session), + this.renderer.scrollCursorIntoView(null, 0.5); + }), + (this.redo = function () { + this.session.getUndoManager().redo(this.session), + this.renderer.scrollCursorIntoView(null, 0.5); + }), + (this.destroy = function () { + this.renderer.destroy(), + this._signal("destroy", this), + this.session && this.session.destroy(); + }), + (this.setAutoScrollEditorIntoView = function (e) { + if (!e) return; + var t, + n = this, + r = !1; + this.$scrollAnchor || + (this.$scrollAnchor = document.createElement("div")); + var i = this.$scrollAnchor; + (i.style.cssText = "position:absolute"), + this.container.insertBefore(i, this.container.firstChild); + var s = this.on("changeSelection", function () { + r = !0; + }), + o = this.renderer.on("beforeRender", function () { + r && (t = n.renderer.container.getBoundingClientRect()); + }), + u = this.renderer.on("afterRender", function () { + if ( + r && + t && + (n.isFocused() || (n.searchBox && n.searchBox.isFocused())) + ) { + var e = n.renderer, + s = e.$cursorLayer.$pixelPos, + o = e.layerConfig, + u = s.top - o.offset; + s.top >= 0 && u + t.top < 0 + ? (r = !0) + : s.top < o.height && + s.top + t.top + o.lineHeight > window.innerHeight + ? (r = !1) + : (r = null), + r != null && + ((i.style.top = u + "px"), + (i.style.left = s.left + "px"), + (i.style.height = o.lineHeight + "px"), + i.scrollIntoView(r)), + (r = t = null); + } + }); + this.setAutoScrollEditorIntoView = function (e) { + if (e) return; + delete this.setAutoScrollEditorIntoView, + this.off("changeSelection", s), + this.renderer.off("afterRender", u), + this.renderer.off("beforeRender", o); + }; + }), + (this.$resetCursorStyle = function () { + var e = this.$cursorStyle || "ace", + t = this.renderer.$cursorLayer; + if (!t) return; + t.setSmoothBlinking(/smooth/.test(e)), + (t.isBlinking = !this.$readOnly && e != "wide"), + i.setCssClass(t.element, "ace_slim-cursors", /slim/.test(e)); + }); + }.call(w.prototype), + g.defineOptions(w.prototype, "editor", { + selectionStyle: { + set: function (e) { + this.onSelectionChange(), + this._signal("changeSelectionStyle", { data: e }); + }, + initialValue: "line", + }, + highlightActiveLine: { + set: function () { + this.$updateHighlightActiveLine(); + }, + initialValue: !0, + }, + highlightSelectedWord: { + set: function (e) { + this.$onSelectionChange(); + }, + initialValue: !0, + }, + readOnly: { + set: function (e) { + this.textInput.setReadOnly(e), this.$resetCursorStyle(); + }, + initialValue: !1, + }, + copyWithEmptySelection: { + set: function (e) { + this.textInput.setCopyWithEmptySelection(e); + }, + initialValue: !1, + }, + cursorStyle: { + set: function (e) { + this.$resetCursorStyle(); + }, + values: ["ace", "slim", "smooth", "wide"], + initialValue: "ace", + }, + mergeUndoDeltas: { values: [!1, !0, "always"], initialValue: !0 }, + behavioursEnabled: { initialValue: !0 }, + wrapBehavioursEnabled: { initialValue: !0 }, + autoScrollEditorIntoView: { + set: function (e) { + this.setAutoScrollEditorIntoView(e); + }, + }, + keyboardHandler: { + set: function (e) { + this.setKeyboardHandler(e); + }, + get: function () { + return this.$keybindingId; + }, + handlesSet: !0, + }, + value: { + set: function (e) { + this.session.setValue(e); + }, + get: function () { + return this.getValue(); + }, + handlesSet: !0, + hidden: !0, + }, + session: { + set: function (e) { + this.setSession(e); + }, + get: function () { + return this.session; + }, + handlesSet: !0, + hidden: !0, + }, + showLineNumbers: { + set: function (e) { + this.renderer.$gutterLayer.setShowLineNumbers(e), + this.renderer.$loop.schedule(this.renderer.CHANGE_GUTTER), + e && this.$relativeLineNumbers ? E.attach(this) : E.detach(this); + }, + initialValue: !0, + }, + relativeLineNumbers: { + set: function (e) { + this.$showLineNumbers && e ? E.attach(this) : E.detach(this); + }, + }, + hScrollBarAlwaysVisible: "renderer", + vScrollBarAlwaysVisible: "renderer", + highlightGutterLine: "renderer", + animatedScroll: "renderer", + showInvisibles: "renderer", + showPrintMargin: "renderer", + printMarginColumn: "renderer", + printMargin: "renderer", + fadeFoldWidgets: "renderer", + showFoldWidgets: "renderer", + displayIndentGuides: "renderer", + showGutter: "renderer", + fontSize: "renderer", + fontFamily: "renderer", + maxLines: "renderer", + minLines: "renderer", + scrollPastEnd: "renderer", + fixedWidthGutter: "renderer", + theme: "renderer", + hasCssTransforms: "renderer", + maxPixelHeight: "renderer", + useTextareaForIME: "renderer", + scrollSpeed: "$mouseHandler", + dragDelay: "$mouseHandler", + dragEnabled: "$mouseHandler", + focusTimeout: "$mouseHandler", + tooltipFollowsMouse: "$mouseHandler", + firstLineNumber: "session", + overwrite: "session", + newLineMode: "session", + useWorker: "session", + useSoftTabs: "session", + navigateWithinSoftTabs: "session", + tabSize: "session", + wrap: "session", + indentedSoftWrap: "session", + foldStyle: "session", + mode: "session", + }); + var E = { + getText: function (e, t) { + return ( + (Math.abs(e.selection.lead.row - t) || t + 1 + (t < 9 ? "\u00b7" : "")) + "" + ); + }, + getWidth: function (e, t, n) { + return ( + Math.max(t.toString().length, (n.lastRow + 1).toString().length, 2) * + n.characterWidth + ); + }, + update: function (e, t) { + t.renderer.$loop.schedule(t.renderer.CHANGE_GUTTER); + }, + attach: function (e) { + (e.renderer.$gutterLayer.$renderer = this), + e.on("changeSelection", this.update), + this.update(null, e); + }, + detach: function (e) { + e.renderer.$gutterLayer.$renderer == this && + (e.renderer.$gutterLayer.$renderer = null), + e.off("changeSelection", this.update), + this.update(null, e); + }, + }; + t.Editor = w; + }, + ), + define("ace/undomanager", ["require", "exports", "module", "ace/range"], function (e, t, n) { + "use strict"; + function i(e, t) { + for (var n = t; n--; ) { + var r = e[n]; + if (r && !r[0].ignore) { + while (n < t - 1) { + var i = d(e[n], e[n + 1]); + (e[n] = i[0]), (e[n + 1] = i[1]), n++; + } + return !0; + } + } + } + function a(e) { + var t = e.action == "insert", + n = e.start, + r = e.end, + i = (r.row - n.row) * (t ? 1 : -1), + s = (r.column - n.column) * (t ? 1 : -1); + t && (r = n); + for (var o in this.marks) { + var a = this.marks[o], + f = u(a, n); + if (f < 0) continue; + if (f === 0 && t) { + if (a.bias != 1) { + a.bias == -1; + continue; + } + f = 1; + } + var l = t ? f : u(a, r); + if (l > 0) { + (a.row += i), (a.column += a.row == r.row ? s : 0); + continue; + } + !t && l <= 0 && ((a.row = n.row), (a.column = n.column), l === 0 && (a.bias = 1)); + } + } + function f(e) { + return { row: e.row, column: e.column }; + } + function l(e) { + return { start: f(e.start), end: f(e.end), action: e.action, lines: e.lines.slice() }; + } + function c(e) { + e = e || this; + if (Array.isArray(e)) return e.map(c).join("\n"); + var t = ""; + e.action + ? ((t = e.action == "insert" ? "+" : "-"), (t += "[" + e.lines + "]")) + : e.value && + (Array.isArray(e.value) ? (t = e.value.map(h).join("\n")) : (t = h(e.value))), + e.start && (t += h(e)); + if (e.id || e.rev) t += " (" + (e.id || e.rev) + ")"; + return t; + } + function h(e) { + return e.start.row + ":" + e.start.column + "=>" + e.end.row + ":" + e.end.column; + } + function p(e, t) { + var n = e.action == "insert", + r = t.action == "insert"; + if (n && r) + if (o(t.start, e.end) >= 0) m(t, e, -1); + else { + if (!(o(t.start, e.start) <= 0)) return null; + m(e, t, 1); + } + else if (n && !r) + if (o(t.start, e.end) >= 0) m(t, e, -1); + else { + if (!(o(t.end, e.start) <= 0)) return null; + m(e, t, -1); + } + else if (!n && r) + if (o(t.start, e.start) >= 0) m(t, e, 1); + else { + if (!(o(t.start, e.start) <= 0)) return null; + m(e, t, 1); + } + else if (!n && !r) + if (o(t.start, e.start) >= 0) m(t, e, 1); + else { + if (!(o(t.end, e.start) <= 0)) return null; + m(e, t, -1); + } + return [t, e]; + } + function d(e, t) { + for (var n = e.length; n--; ) + for (var r = 0; r < t.length; r++) + if (!p(e[n], t[r])) { + while (n < e.length) { + while (r--) p(t[r], e[n]); + (r = t.length), n++; + } + return [e, t]; + } + return ( + (e.selectionBefore = + t.selectionBefore = + e.selectionAfter = + t.selectionAfter = + null), + [t, e] + ); + } + function v(e, t) { + var n = e.action == "insert", + r = t.action == "insert"; + if (n && r) o(e.start, t.start) < 0 ? m(t, e, 1) : m(e, t, 1); + else if (n && !r) + o(e.start, t.end) >= 0 + ? m(e, t, -1) + : o(e.start, t.start) <= 0 + ? m(t, e, 1) + : (m(e, s.fromPoints(t.start, e.start), -1), m(t, e, 1)); + else if (!n && r) + o(t.start, e.end) >= 0 + ? m(t, e, -1) + : o(t.start, e.start) <= 0 + ? m(e, t, 1) + : (m(t, s.fromPoints(e.start, t.start), -1), m(e, t, 1)); + else if (!n && !r) + if (o(t.start, e.end) >= 0) m(t, e, -1); + else { + if (!(o(t.end, e.start) <= 0)) { + var i, u; + return ( + o(e.start, t.start) < 0 && ((i = e), (e = y(e, t.start))), + o(e.end, t.end) > 0 && (u = y(e, t.end)), + g(t.end, e.start, e.end, -1), + u && + !i && + ((e.lines = u.lines), + (e.start = u.start), + (e.end = u.end), + (u = e)), + [t, i, u].filter(Boolean) + ); + } + m(e, t, -1); + } + return [t, e]; + } + function m(e, t, n) { + g(e.start, t.start, t.end, n), g(e.end, t.start, t.end, n); + } + function g(e, t, n, r) { + e.row == (r == 1 ? t : n).row && (e.column += r * (n.column - t.column)), + (e.row += r * (n.row - t.row)); + } + function y(e, t) { + var n = e.lines, + r = e.end; + e.end = f(t); + var i = e.end.row - e.start.row, + s = n.splice(i, n.length), + o = i ? t.column : t.column - e.start.column; + n.push(s[0].substring(0, o)), (s[0] = s[0].substr(o)); + var u = { start: f(t), end: r, lines: s, action: e.action }; + return u; + } + function b(e, t) { + t = l(t); + for (var n = e.length; n--; ) { + var r = e[n]; + for (var i = 0; i < r.length; i++) { + var s = r[i], + o = v(s, t); + (t = o[0]), + o.length != 2 && + (o[2] + ? (r.splice(i + 1, 1, o[1], o[2]), i++) + : o[1] || (r.splice(i, 1), i--)); + } + r.length || e.splice(n, 1); + } + return e; + } + function w(e, t) { + for (var n = 0; n < t.length; n++) { + var r = t[n]; + for (var i = 0; i < r.length; i++) b(e, r[i]); + } + } + var r = function () { + (this.$maxRev = 0), (this.$fromUndo = !1), this.reset(); + }; + (function () { + (this.addSession = function (e) { + this.$session = e; + }), + (this.add = function (e, t, n) { + if (this.$fromUndo) return; + if (e == this.$lastDelta) return; + if (t === !1 || !this.lastDeltas) + (this.lastDeltas = []), + this.$undoStack.push(this.lastDeltas), + (e.id = this.$rev = ++this.$maxRev); + if (e.action == "remove" || e.action == "insert") this.$lastDelta = e; + this.lastDeltas.push(e); + }), + (this.addSelection = function (e, t) { + this.selections.push({ value: e, rev: t || this.$rev }); + }), + (this.startNewGroup = function () { + return (this.lastDeltas = null), this.$rev; + }), + (this.markIgnored = function (e, t) { + t == null && (t = this.$rev + 1); + var n = this.$undoStack; + for (var r = n.length; r--; ) { + var i = n[r][0]; + if (i.id <= e) break; + i.id < t && (i.ignore = !0); + } + this.lastDeltas = null; + }), + (this.getSelection = function (e, t) { + var n = this.selections; + for (var r = n.length; r--; ) { + var i = n[r]; + if (i.rev < e) return t && (i = n[r + 1]), i; + } + }), + (this.getRevision = function () { + return this.$rev; + }), + (this.getDeltas = function (e, t) { + t == null && (t = this.$rev + 1); + var n = this.$undoStack, + r = null, + i = 0; + for (var s = n.length; s--; ) { + var o = n[s][0]; + o.id < t && !r && (r = s + 1); + if (o.id <= e) { + i = s + 1; + break; + } + } + return n.slice(i, r); + }), + (this.getChangedRanges = function (e, t) { + t == null && (t = this.$rev + 1); + }), + (this.getChangedLines = function (e, t) { + t == null && (t = this.$rev + 1); + }), + (this.undo = function (e, t) { + this.lastDeltas = null; + var n = this.$undoStack; + if (!i(n, n.length)) return; + e || (e = this.$session), + this.$redoStackBaseRev !== this.$rev && + this.$redoStack.length && + (this.$redoStack = []), + (this.$fromUndo = !0); + var r = n.pop(), + s = null; + return ( + r && + r.length && + ((s = e.undoChanges(r, t)), this.$redoStack.push(r), this.$syncRev()), + (this.$fromUndo = !1), + s + ); + }), + (this.redo = function (e, t) { + (this.lastDeltas = null), e || (e = this.$session), (this.$fromUndo = !0); + if (this.$redoStackBaseRev != this.$rev) { + var n = this.getDeltas(this.$redoStackBaseRev, this.$rev + 1); + w(this.$redoStack, n), + (this.$redoStackBaseRev = this.$rev), + this.$redoStack.forEach(function (e) { + e[0].id = ++this.$maxRev; + }, this); + } + var r = this.$redoStack.pop(), + i = null; + return ( + r && ((i = e.redoChanges(r, t)), this.$undoStack.push(r), this.$syncRev()), + (this.$fromUndo = !1), + i + ); + }), + (this.$syncRev = function () { + var e = this.$undoStack, + t = e[e.length - 1], + n = (t && t[0].id) || 0; + (this.$redoStackBaseRev = n), (this.$rev = n); + }), + (this.reset = function () { + (this.lastDeltas = null), + (this.$lastDelta = null), + (this.$undoStack = []), + (this.$redoStack = []), + (this.$rev = 0), + (this.mark = 0), + (this.$redoStackBaseRev = this.$rev), + (this.selections = []); + }), + (this.canUndo = function () { + return this.$undoStack.length > 0; + }), + (this.canRedo = function () { + return this.$redoStack.length > 0; + }), + (this.bookmark = function (e) { + e == undefined && (e = this.$rev), (this.mark = e); + }), + (this.isAtBookmark = function () { + return this.$rev === this.mark; + }), + (this.toJSON = function () {}), + (this.fromJSON = function () {}), + (this.hasUndo = this.canUndo), + (this.hasRedo = this.canRedo), + (this.isClean = this.isAtBookmark), + (this.markClean = this.bookmark), + (this.$prettyPrint = function (e) { + return e ? c(e) : c(this.$undoStack) + "\n---\n" + c(this.$redoStack); + }); + }).call(r.prototype); + var s = e("./range").Range, + o = s.comparePoints, + u = s.comparePoints; + t.UndoManager = r; + }), + define("ace/layer/lines", ["require", "exports", "module", "ace/lib/dom"], function (e, t, n) { + "use strict"; + var r = e("../lib/dom"), + i = function (e, t) { + (this.element = e), + (this.canvasHeight = t || 5e5), + (this.element.style.height = this.canvasHeight * 2 + "px"), + (this.cells = []), + (this.cellCache = []), + (this.$offsetCoefficient = 0); + }; + (function () { + (this.moveContainer = function (e) { + r.translate( + this.element, + 0, + -((e.firstRowScreen * e.lineHeight) % this.canvasHeight) - + e.offset * this.$offsetCoefficient, + ); + }), + (this.pageChanged = function (e, t) { + return ( + Math.floor((e.firstRowScreen * e.lineHeight) / this.canvasHeight) !== + Math.floor((t.firstRowScreen * t.lineHeight) / this.canvasHeight) + ); + }), + (this.computeLineTop = function (e, t, n) { + var r = t.firstRowScreen * t.lineHeight, + i = Math.floor(r / this.canvasHeight), + s = n.documentToScreenRow(e, 0) * t.lineHeight; + return s - i * this.canvasHeight; + }), + (this.computeLineHeight = function (e, t, n) { + return t.lineHeight * n.getRowLength(e); + }), + (this.getLength = function () { + return this.cells.length; + }), + (this.get = function (e) { + return this.cells[e]; + }), + (this.shift = function () { + this.$cacheCell(this.cells.shift()); + }), + (this.pop = function () { + this.$cacheCell(this.cells.pop()); + }), + (this.push = function (e) { + if (Array.isArray(e)) { + this.cells.push.apply(this.cells, e); + var t = r.createFragment(this.element); + for (var n = 0; n < e.length; n++) t.appendChild(e[n].element); + this.element.appendChild(t); + } else this.cells.push(e), this.element.appendChild(e.element); + }), + (this.unshift = function (e) { + if (Array.isArray(e)) { + this.cells.unshift.apply(this.cells, e); + var t = r.createFragment(this.element); + for (var n = 0; n < e.length; n++) t.appendChild(e[n].element); + this.element.firstChild + ? this.element.insertBefore(t, this.element.firstChild) + : this.element.appendChild(t); + } else + this.cells.unshift(e), + this.element.insertAdjacentElement("afterbegin", e.element); + }), + (this.last = function () { + return this.cells.length ? this.cells[this.cells.length - 1] : null; + }), + (this.$cacheCell = function (e) { + if (!e) return; + e.element.remove(), this.cellCache.push(e); + }), + (this.createCell = function (e, t, n, i) { + var s = this.cellCache.pop(); + if (!s) { + var o = r.createElement("div"); + i && i(o), + this.element.appendChild(o), + (s = { element: o, text: "", row: e }); + } + return (s.row = e), s; + }); + }).call(i.prototype), + (t.Lines = i); + }), + define( + "ace/layer/gutter", + [ + "require", + "exports", + "module", + "ace/lib/dom", + "ace/lib/oop", + "ace/lib/lang", + "ace/lib/event_emitter", + "ace/layer/lines", + ], + function (e, t, n) { + "use strict"; + function f(e) { + var t = document.createTextNode(""); + e.appendChild(t); + var n = r.createElement("span"); + return e.appendChild(n), e; + } + var r = e("../lib/dom"), + i = e("../lib/oop"), + s = e("../lib/lang"), + o = e("../lib/event_emitter").EventEmitter, + u = e("./lines").Lines, + a = function (e) { + (this.element = r.createElement("div")), + (this.element.className = "ace_layer ace_gutter-layer"), + e.appendChild(this.element), + this.setShowFoldWidgets(this.$showFoldWidgets), + (this.gutterWidth = 0), + (this.$annotations = []), + (this.$updateAnnotations = this.$updateAnnotations.bind(this)), + (this.$lines = new u(this.element)), + (this.$lines.$offsetCoefficient = 1); + }; + (function () { + i.implement(this, o), + (this.setSession = function (e) { + this.session && + this.session.removeEventListener("change", this.$updateAnnotations), + (this.session = e), + e && e.on("change", this.$updateAnnotations); + }), + (this.addGutterDecoration = function (e, t) { + window.console && + console.warn && + console.warn("deprecated use session.addGutterDecoration"), + this.session.addGutterDecoration(e, t); + }), + (this.removeGutterDecoration = function (e, t) { + window.console && + console.warn && + console.warn("deprecated use session.removeGutterDecoration"), + this.session.removeGutterDecoration(e, t); + }), + (this.setAnnotations = function (e) { + this.$annotations = []; + for (var t = 0; t < e.length; t++) { + var n = e[t], + r = n.row, + i = this.$annotations[r]; + i || (i = this.$annotations[r] = { text: [] }); + var o = n.text; + (o = o ? s.escapeHTML(o) : n.html || ""), + i.text.indexOf(o) === -1 && i.text.push(o); + var u = n.type; + u == "error" + ? (i.className = " ace_error") + : u == "warning" && i.className != " ace_error" + ? (i.className = " ace_warning") + : u == "info" && !i.className && (i.className = " ace_info"); + } + }), + (this.$updateAnnotations = function (e) { + if (!this.$annotations.length) return; + var t = e.start.row, + n = e.end.row - t; + if (n !== 0) + if (e.action == "remove") this.$annotations.splice(t, n + 1, null); + else { + var r = new Array(n + 1); + r.unshift(t, 1), + this.$annotations.splice.apply(this.$annotations, r); + } + }), + (this.update = function (e) { + this.config = e; + var t = this.session, + n = e.firstRow, + r = Math.min(e.lastRow + e.gutterOffset, t.getLength() - 1); + (this.oldLastRow = r), + (this.config = e), + this.$lines.moveContainer(e), + this.$updateCursorRow(); + var i = t.getNextFoldLine(n), + s = i ? i.start.row : Infinity, + o = null, + u = -1, + a = n; + for (;;) { + a > s && + ((a = i.end.row + 1), + (i = t.getNextFoldLine(a, i)), + (s = i ? i.start.row : Infinity)); + if (a > r) { + while (this.$lines.getLength() > u + 1) this.$lines.pop(); + break; + } + (o = this.$lines.get(++u)), + o + ? (o.row = a) + : ((o = this.$lines.createCell(a, e, this.session, f)), + this.$lines.push(o)), + this.$renderCell(o, e, i, a), + a++; + } + this._signal("afterRender"), this.$updateGutterWidth(e); + }), + (this.$updateGutterWidth = function (e) { + var t = this.session, + n = t.gutterRenderer || this.$renderer, + r = t.$firstLineNumber, + i = this.$lines.last() ? this.$lines.last().text : ""; + if (this.$fixedWidth || t.$useWrapMode) i = t.getLength() + r; + var s = n ? n.getWidth(t, i, e) : i.toString().length * e.characterWidth, + o = this.$padding || this.$computePadding(); + (s += o.left + o.right), + s !== this.gutterWidth && + !isNaN(s) && + ((this.gutterWidth = s), + (this.element.parentNode.style.width = this.element.style.width = + Math.ceil(this.gutterWidth) + "px"), + this._signal("changeGutterWidth", s)); + }), + (this.$updateCursorRow = function () { + if (!this.$highlightGutterLine) return; + var e = this.session.selection.getCursor(); + if (this.$cursorRow === e.row) return; + this.$cursorRow = e.row; + }), + (this.updateLineHighlight = function () { + if (!this.$highlightGutterLine) return; + var e = this.session.selection.cursor.row; + this.$cursorRow = e; + if (this.$cursorCell && this.$cursorCell.row == e) return; + this.$cursorCell && + (this.$cursorCell.element.className = + this.$cursorCell.element.className.replace( + "ace_gutter-active-line ", + "", + )); + var t = this.$lines.cells; + this.$cursorCell = null; + for (var n = 0; n < t.length; n++) { + var r = t[n]; + if (r.row >= this.$cursorRow) { + if (r.row > this.$cursorRow) { + var i = this.session.getFoldLine(this.$cursorRow); + if (!(n > 0 && i && i.start.row == t[n - 1].row)) break; + r = t[n - 1]; + } + (r.element.className = + "ace_gutter-active-line " + r.element.className), + (this.$cursorCell = r); + break; + } + } + }), + (this.scrollLines = function (e) { + var t = this.config; + (this.config = e), this.$updateCursorRow(); + if (this.$lines.pageChanged(t, e)) return this.update(e); + this.$lines.moveContainer(e); + var n = Math.min(e.lastRow + e.gutterOffset, this.session.getLength() - 1), + r = this.oldLastRow; + this.oldLastRow = n; + if (!t || r < e.firstRow) return this.update(e); + if (n < t.firstRow) return this.update(e); + if (t.firstRow < e.firstRow) + for ( + var i = this.session.getFoldedRowCount(t.firstRow, e.firstRow - 1); + i > 0; + i-- + ) + this.$lines.shift(); + if (r > n) + for (var i = this.session.getFoldedRowCount(n + 1, r); i > 0; i--) + this.$lines.pop(); + e.firstRow < t.firstRow && + this.$lines.unshift(this.$renderLines(e, e.firstRow, t.firstRow - 1)), + n > r && this.$lines.push(this.$renderLines(e, r + 1, n)), + this.updateLineHighlight(), + this._signal("afterRender"), + this.$updateGutterWidth(e); + }), + (this.$renderLines = function (e, t, n) { + var r = [], + i = t, + s = this.session.getNextFoldLine(i), + o = s ? s.start.row : Infinity; + for (;;) { + i > o && + ((i = s.end.row + 1), + (s = this.session.getNextFoldLine(i, s)), + (o = s ? s.start.row : Infinity)); + if (i > n) break; + var u = this.$lines.createCell(i, e, this.session, f); + this.$renderCell(u, e, s, i), r.push(u), i++; + } + return r; + }), + (this.$renderCell = function (e, t, n, i) { + var s = e.element, + o = this.session, + u = s.childNodes[0], + a = s.childNodes[1], + f = o.$firstLineNumber, + l = o.$breakpoints, + c = o.$decorations, + h = o.gutterRenderer || this.$renderer, + p = this.$showFoldWidgets && o.foldWidgets, + d = n ? n.start.row : Number.MAX_VALUE, + v = "ace_gutter-cell "; + this.$highlightGutterLine && + (i == this.$cursorRow || + (n && + i < this.$cursorRow && + i >= d && + this.$cursorRow <= n.end.row)) && + ((v += "ace_gutter-active-line "), + this.$cursorCell != e && + (this.$cursorCell && + (this.$cursorCell.element.className = + this.$cursorCell.element.className.replace( + "ace_gutter-active-line ", + "", + )), + (this.$cursorCell = e))), + l[i] && (v += l[i]), + c[i] && (v += c[i]), + this.$annotations[i] && (v += this.$annotations[i].className), + s.className != v && (s.className = v); + if (p) { + var m = p[i]; + m == null && (m = p[i] = o.getFoldWidget(i)); + } + if (m) { + var v = "ace_fold-widget ace_" + m; + m == "start" && i == d && i < n.end.row + ? (v += " ace_closed") + : (v += " ace_open"), + a.className != v && (a.className = v); + var g = t.lineHeight + "px"; + r.setStyle(a.style, "height", g), + r.setStyle(a.style, "display", "inline-block"); + } else a && r.setStyle(a.style, "display", "none"); + var y = (h ? h.getText(o, i) : i + f).toString(); + return ( + y !== u.data && (u.data = y), + r.setStyle( + e.element.style, + "height", + this.$lines.computeLineHeight(i, t, o) + "px", + ), + r.setStyle( + e.element.style, + "top", + this.$lines.computeLineTop(i, t, o) + "px", + ), + (e.text = y), + e + ); + }), + (this.$fixedWidth = !1), + (this.$highlightGutterLine = !0), + (this.$renderer = ""), + (this.setHighlightGutterLine = function (e) { + this.$highlightGutterLine = e; + }), + (this.$showLineNumbers = !0), + (this.$renderer = ""), + (this.setShowLineNumbers = function (e) { + this.$renderer = !e && { + getWidth: function () { + return ""; + }, + getText: function () { + return ""; + }, + }; + }), + (this.getShowLineNumbers = function () { + return this.$showLineNumbers; + }), + (this.$showFoldWidgets = !0), + (this.setShowFoldWidgets = function (e) { + e + ? r.addCssClass(this.element, "ace_folding-enabled") + : r.removeCssClass(this.element, "ace_folding-enabled"), + (this.$showFoldWidgets = e), + (this.$padding = null); + }), + (this.getShowFoldWidgets = function () { + return this.$showFoldWidgets; + }), + (this.$computePadding = function () { + if (!this.element.firstChild) return { left: 0, right: 0 }; + var e = r.computedStyle(this.element.firstChild); + return ( + (this.$padding = {}), + (this.$padding.left = + (parseInt(e.borderLeftWidth) || 0) + + (parseInt(e.paddingLeft) || 0) + + 1), + (this.$padding.right = + (parseInt(e.borderRightWidth) || 0) + + (parseInt(e.paddingRight) || 0)), + this.$padding + ); + }), + (this.getRegion = function (e) { + var t = this.$padding || this.$computePadding(), + n = this.element.getBoundingClientRect(); + if (e.x < t.left + n.left) return "markers"; + if (this.$showFoldWidgets && e.x > n.right - t.right) return "foldWidgets"; + }); + }).call(a.prototype), + (t.Gutter = a); + }, + ), + define( + "ace/layer/marker", + ["require", "exports", "module", "ace/range", "ace/lib/dom"], + function (e, t, n) { + "use strict"; + var r = e("../range").Range, + i = e("../lib/dom"), + s = function (e) { + (this.element = i.createElement("div")), + (this.element.className = "ace_layer ace_marker-layer"), + e.appendChild(this.element); + }; + (function () { + function e(e, t, n, r) { + return (e ? 1 : 0) | (t ? 2 : 0) | (n ? 4 : 0) | (r ? 8 : 0); + } + (this.$padding = 0), + (this.setPadding = function (e) { + this.$padding = e; + }), + (this.setSession = function (e) { + this.session = e; + }), + (this.setMarkers = function (e) { + this.markers = e; + }), + (this.elt = function (e, t) { + var n = this.i != -1 && this.element.childNodes[this.i]; + n + ? this.i++ + : ((n = document.createElement("div")), + this.element.appendChild(n), + (this.i = -1)), + (n.style.cssText = t), + (n.className = e); + }), + (this.update = function (e) { + if (!e) return; + (this.config = e), (this.i = 0); + var t; + for (var n in this.markers) { + var r = this.markers[n]; + if (!r.range) { + r.update(t, this, this.session, e); + continue; + } + var i = r.range.clipRows(e.firstRow, e.lastRow); + if (i.isEmpty()) continue; + i = i.toScreenRange(this.session); + if (r.renderer) { + var s = this.$getTop(i.start.row, e), + o = this.$padding + i.start.column * e.characterWidth; + r.renderer(t, i, o, s, e); + } else + r.type == "fullLine" + ? this.drawFullLineMarker(t, i, r.clazz, e) + : r.type == "screenLine" + ? this.drawScreenLineMarker(t, i, r.clazz, e) + : i.isMultiLine() + ? r.type == "text" + ? this.drawTextMarker(t, i, r.clazz, e) + : this.drawMultiLineMarker(t, i, r.clazz, e) + : this.drawSingleLineMarker( + t, + i, + r.clazz + " ace_start" + " ace_br15", + e, + ); + } + if (this.i != -1) + while (this.i < this.element.childElementCount) + this.element.removeChild(this.element.lastChild); + }), + (this.$getTop = function (e, t) { + return (e - t.firstRowScreen) * t.lineHeight; + }), + (this.drawTextMarker = function (t, n, i, s, o) { + var u = this.session, + a = n.start.row, + f = n.end.row, + l = a, + c = 0, + h = 0, + p = u.getScreenLastRowColumn(l), + d = new r(l, n.start.column, l, h); + for (; l <= f; l++) + (d.start.row = d.end.row = l), + (d.start.column = l == a ? n.start.column : u.getRowWrapIndent(l)), + (d.end.column = p), + (c = h), + (h = p), + (p = + l + 1 < f + ? u.getScreenLastRowColumn(l + 1) + : l == f + ? 0 + : n.end.column), + this.drawSingleLineMarker( + t, + d, + i + + (l == a ? " ace_start" : "") + + " ace_br" + + e( + l == a || (l == a + 1 && n.start.column), + c < h, + h > p, + l == f, + ), + s, + l == f ? 0 : 1, + o, + ); + }), + (this.drawMultiLineMarker = function (e, t, n, r, i) { + var s = this.$padding, + o = r.lineHeight, + u = this.$getTop(t.start.row, r), + a = s + t.start.column * r.characterWidth; + i = i || ""; + if (this.session.$bidiHandler.isBidiRow(t.start.row)) { + var f = t.clone(); + (f.end.row = f.start.row), + (f.end.column = this.session.getLine(f.start.row).length), + this.drawBidiSingleLineMarker( + e, + f, + n + " ace_br1 ace_start", + r, + null, + i, + ); + } else + this.elt( + n + " ace_br1 ace_start", + "height:" + + o + + "px;" + + "right:0;" + + "top:" + + u + + "px;left:" + + a + + "px;" + + (i || ""), + ); + if (this.session.$bidiHandler.isBidiRow(t.end.row)) { + var f = t.clone(); + (f.start.row = f.end.row), + (f.start.column = 0), + this.drawBidiSingleLineMarker(e, f, n + " ace_br12", r, null, i); + } else { + u = this.$getTop(t.end.row, r); + var l = t.end.column * r.characterWidth; + this.elt( + n + " ace_br12", + "height:" + + o + + "px;" + + "width:" + + l + + "px;" + + "top:" + + u + + "px;" + + "left:" + + s + + "px;" + + (i || ""), + ); + } + o = (t.end.row - t.start.row - 1) * r.lineHeight; + if (o <= 0) return; + u = this.$getTop(t.start.row + 1, r); + var c = (t.start.column ? 1 : 0) | (t.end.column ? 0 : 8); + this.elt( + n + (c ? " ace_br" + c : ""), + "height:" + + o + + "px;" + + "right:0;" + + "top:" + + u + + "px;" + + "left:" + + s + + "px;" + + (i || ""), + ); + }), + (this.drawSingleLineMarker = function (e, t, n, r, i, s) { + if (this.session.$bidiHandler.isBidiRow(t.start.row)) + return this.drawBidiSingleLineMarker(e, t, n, r, i, s); + var o = r.lineHeight, + u = (t.end.column + (i || 0) - t.start.column) * r.characterWidth, + a = this.$getTop(t.start.row, r), + f = this.$padding + t.start.column * r.characterWidth; + this.elt( + n, + "height:" + + o + + "px;" + + "width:" + + u + + "px;" + + "top:" + + a + + "px;" + + "left:" + + f + + "px;" + + (s || ""), + ); + }), + (this.drawBidiSingleLineMarker = function (e, t, n, r, i, s) { + var o = r.lineHeight, + u = this.$getTop(t.start.row, r), + a = this.$padding, + f = this.session.$bidiHandler.getSelections( + t.start.column, + t.end.column, + ); + f.forEach(function (e) { + this.elt( + n, + "height:" + + o + + "px;" + + "width:" + + e.width + + (i || 0) + + "px;" + + "top:" + + u + + "px;" + + "left:" + + (a + e.left) + + "px;" + + (s || ""), + ); + }, this); + }), + (this.drawFullLineMarker = function (e, t, n, r, i) { + var s = this.$getTop(t.start.row, r), + o = r.lineHeight; + t.start.row != t.end.row && (o += this.$getTop(t.end.row, r) - s), + this.elt( + n, + "height:" + + o + + "px;" + + "top:" + + s + + "px;" + + "left:0;right:0;" + + (i || ""), + ); + }), + (this.drawScreenLineMarker = function (e, t, n, r, i) { + var s = this.$getTop(t.start.row, r), + o = r.lineHeight; + this.elt( + n, + "height:" + + o + + "px;" + + "top:" + + s + + "px;" + + "left:0;right:0;" + + (i || ""), + ); + }); + }).call(s.prototype), + (t.Marker = s); + }, + ), + define( + "ace/layer/text", + [ + "require", + "exports", + "module", + "ace/lib/oop", + "ace/lib/dom", + "ace/lib/lang", + "ace/layer/lines", + "ace/lib/event_emitter", + ], + function (e, t, n) { + "use strict"; + var r = e("../lib/oop"), + i = e("../lib/dom"), + s = e("../lib/lang"), + o = e("./lines").Lines, + u = e("../lib/event_emitter").EventEmitter, + a = function (e) { + (this.dom = i), + (this.element = this.dom.createElement("div")), + (this.element.className = "ace_layer ace_text-layer"), + e.appendChild(this.element), + (this.$updateEolChar = this.$updateEolChar.bind(this)), + (this.$lines = new o(this.element)); + }; + (function () { + r.implement(this, u), + (this.EOF_CHAR = "\u00b6"), + (this.EOL_CHAR_LF = "\u00ac"), + (this.EOL_CHAR_CRLF = "\u00a4"), + (this.EOL_CHAR = this.EOL_CHAR_LF), + (this.TAB_CHAR = "\u2014"), + (this.SPACE_CHAR = "\u00b7"), + (this.$padding = 0), + (this.MAX_LINE_LENGTH = 1e4), + (this.$updateEolChar = function () { + var e = this.session.doc, + t = e.getNewLineCharacter() == "\n" && e.getNewLineMode() != "windows", + n = t ? this.EOL_CHAR_LF : this.EOL_CHAR_CRLF; + if (this.EOL_CHAR != n) return (this.EOL_CHAR = n), !0; + }), + (this.setPadding = function (e) { + (this.$padding = e), (this.element.style.margin = "0 " + e + "px"); + }), + (this.getLineHeight = function () { + return this.$fontMetrics.$characterSize.height || 0; + }), + (this.getCharacterWidth = function () { + return this.$fontMetrics.$characterSize.width || 0; + }), + (this.$setFontMetrics = function (e) { + (this.$fontMetrics = e), + this.$fontMetrics.on( + "changeCharacterSize", + function (e) { + this._signal("changeCharacterSize", e); + }.bind(this), + ), + this.$pollSizeChanges(); + }), + (this.checkForSizeChanges = function () { + this.$fontMetrics.checkForSizeChanges(); + }), + (this.$pollSizeChanges = function () { + return (this.$pollSizeChangesTimer = this.$fontMetrics.$pollSizeChanges()); + }), + (this.setSession = function (e) { + (this.session = e), e && this.$computeTabString(); + }), + (this.showInvisibles = !1), + (this.setShowInvisibles = function (e) { + return this.showInvisibles == e + ? !1 + : ((this.showInvisibles = e), this.$computeTabString(), !0); + }), + (this.displayIndentGuides = !0), + (this.setDisplayIndentGuides = function (e) { + return this.displayIndentGuides == e + ? !1 + : ((this.displayIndentGuides = e), this.$computeTabString(), !0); + }), + (this.$tabStrings = []), + (this.onChangeTabSize = this.$computeTabString = + function () { + var e = this.session.getTabSize(); + this.tabSize = e; + var t = (this.$tabStrings = [0]); + for (var n = 1; n < e + 1; n++) + if (this.showInvisibles) { + var r = this.dom.createElement("span"); + (r.className = "ace_invisible ace_invisible_tab"), + (r.textContent = s.stringRepeat(this.TAB_CHAR, n)), + t.push(r); + } else + t.push( + this.dom.createTextNode( + s.stringRepeat(" ", n), + this.element, + ), + ); + if (this.displayIndentGuides) { + this.$indentGuideRe = /\s\S| \t|\t |\s$/; + var i = "ace_indent-guide", + o = "", + u = ""; + if (this.showInvisibles) { + (i += " ace_invisible"), + (o = " ace_invisible_space"), + (u = " ace_invisible_tab"); + var a = s.stringRepeat(this.SPACE_CHAR, this.tabSize), + f = s.stringRepeat(this.TAB_CHAR, this.tabSize); + } else + var a = s.stringRepeat(" ", this.tabSize), + f = a; + var r = this.dom.createElement("span"); + (r.className = i + o), + (r.textContent = a), + (this.$tabStrings[" "] = r); + var r = this.dom.createElement("span"); + (r.className = i + u), + (r.textContent = f), + (this.$tabStrings[" "] = r); + } + }), + (this.updateLines = function (e, t, n) { + if (this.config.lastRow != e.lastRow || this.config.firstRow != e.firstRow) + return this.update(e); + this.config = e; + var r = Math.max(t, e.firstRow), + i = Math.min(n, e.lastRow), + s = this.element.childNodes, + o = 0; + for (var u = e.firstRow; u < r; u++) { + var a = this.session.getFoldLine(u); + if (a) { + if (a.containsRow(r)) { + r = a.start.row; + break; + } + u = a.end.row; + } + o++; + } + var f = !1, + u = r, + a = this.session.getNextFoldLine(u), + l = a ? a.start.row : Infinity; + for (;;) { + u > l && + ((u = a.end.row + 1), + (a = this.session.getNextFoldLine(u, a)), + (l = a ? a.start.row : Infinity)); + if (u > i) break; + var c = s[o++]; + if (c) { + this.dom.removeChildren(c), this.$renderLine(c, u, u == l ? a : !1); + var h = e.lineHeight * this.session.getRowLength(u) + "px"; + c.style.height != h && ((f = !0), (c.style.height = h)); + } + u++; + } + if (f) + while (o < this.$lines.cells.length) { + var p = this.$lines.cells[o++]; + p.element.style.top = + this.$lines.computeLineTop(p.row, e, this.session) + "px"; + } + }), + (this.scrollLines = function (e) { + var t = this.config; + this.config = e; + if (this.$lines.pageChanged(t, e)) return this.update(e); + this.$lines.moveContainer(e); + var n = e.lastRow, + r = t ? t.lastRow : -1; + if (!t || r < e.firstRow) return this.update(e); + if (n < t.firstRow) return this.update(e); + if (!t || t.lastRow < e.firstRow) return this.update(e); + if (e.lastRow < t.firstRow) return this.update(e); + if (t.firstRow < e.firstRow) + for ( + var i = this.session.getFoldedRowCount(t.firstRow, e.firstRow - 1); + i > 0; + i-- + ) + this.$lines.shift(); + if (t.lastRow > e.lastRow) + for ( + var i = this.session.getFoldedRowCount(e.lastRow + 1, t.lastRow); + i > 0; + i-- + ) + this.$lines.pop(); + e.firstRow < t.firstRow && + this.$lines.unshift( + this.$renderLinesFragment(e, e.firstRow, t.firstRow - 1), + ), + e.lastRow > t.lastRow && + this.$lines.push( + this.$renderLinesFragment(e, t.lastRow + 1, e.lastRow), + ); + }), + (this.$renderLinesFragment = function (e, t, n) { + var r = [], + s = t, + o = this.session.getNextFoldLine(s), + u = o ? o.start.row : Infinity; + for (;;) { + s > u && + ((s = o.end.row + 1), + (o = this.session.getNextFoldLine(s, o)), + (u = o ? o.start.row : Infinity)); + if (s > n) break; + var a = this.$lines.createCell(s, e, this.session), + f = a.element; + this.dom.removeChildren(f), + i.setStyle( + f.style, + "height", + this.$lines.computeLineHeight(s, e, this.session) + "px", + ), + i.setStyle( + f.style, + "top", + this.$lines.computeLineTop(s, e, this.session) + "px", + ), + this.$renderLine(f, s, s == u ? o : !1), + this.$useLineGroups() + ? (f.className = "ace_line_group") + : (f.className = "ace_line"), + r.push(a), + s++; + } + return r; + }), + (this.update = function (e) { + this.$lines.moveContainer(e), (this.config = e); + var t = e.firstRow, + n = e.lastRow, + r = this.$lines; + while (r.getLength()) r.pop(); + r.push(this.$renderLinesFragment(e, t, n)); + }), + (this.$textToken = { text: !0, rparen: !0, lparen: !0 }), + (this.$renderToken = function (e, t, n, r) { + var o = this, + u = + /(\t)|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\uFEFF\uFFF9-\uFFFC]+)|(\u3000)|([\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3001-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]|[\uD800-\uDBFF][\uDC00-\uDFFF])/g, + a = this.dom.createFragment(this.element), + f, + l = 0; + while ((f = u.exec(r))) { + var c = f[1], + h = f[2], + p = f[3], + d = f[4], + v = f[5]; + if (!o.showInvisibles && h) continue; + var m = l != f.index ? r.slice(l, f.index) : ""; + (l = f.index + f[0].length), + m && a.appendChild(this.dom.createTextNode(m, this.element)); + if (c) { + var g = o.session.getScreenTabSize(t + f.index); + a.appendChild(o.$tabStrings[g].cloneNode(!0)), (t += g - 1); + } else if (h) + if (o.showInvisibles) { + var y = this.dom.createElement("span"); + (y.className = "ace_invisible ace_invisible_space"), + (y.textContent = s.stringRepeat(o.SPACE_CHAR, h.length)), + a.appendChild(y); + } else a.appendChild(this.com.createTextNode(h, this.element)); + else if (p) { + var y = this.dom.createElement("span"); + (y.className = "ace_invisible ace_invisible_space ace_invalid"), + (y.textContent = s.stringRepeat(o.SPACE_CHAR, p.length)), + a.appendChild(y); + } else if (d) { + var b = o.showInvisibles ? o.SPACE_CHAR : ""; + t += 1; + var y = this.dom.createElement("span"); + (y.style.width = o.config.characterWidth * 2 + "px"), + (y.className = o.showInvisibles + ? "ace_cjk ace_invisible ace_invisible_space" + : "ace_cjk"), + (y.textContent = o.showInvisibles ? o.SPACE_CHAR : ""), + a.appendChild(y); + } else if (v) { + t += 1; + var y = i.createElement("span"); + (y.style.width = o.config.characterWidth * 2 + "px"), + (y.className = "ace_cjk"), + (y.textContent = v), + a.appendChild(y); + } + } + a.appendChild(this.dom.createTextNode(l ? r.slice(l) : r, this.element)); + if (!this.$textToken[n.type]) { + var w = "ace_" + n.type.replace(/\./g, " ace_"), + y = this.dom.createElement("span"); + n.type == "fold" && + (y.style.width = + n.value.length * this.config.characterWidth + "px"), + (y.className = w), + y.appendChild(a), + e.appendChild(y); + } else e.appendChild(a); + return t + r.length; + }), + (this.renderIndentGuide = function (e, t, n) { + var r = t.search(this.$indentGuideRe); + if (r <= 0 || r >= n) return t; + if (t[0] == " ") { + r -= r % this.tabSize; + var i = r / this.tabSize; + for (var s = 0; s < i; s++) + e.appendChild(this.$tabStrings[" "].cloneNode(!0)); + return t.substr(r); + } + if (t[0] == " ") { + for (var s = 0; s < r; s++) + e.appendChild(this.$tabStrings[" "].cloneNode(!0)); + return t.substr(r); + } + return t; + }), + (this.$createLineElement = function (e) { + var t = this.dom.createElement("div"); + return ( + (t.className = "ace_line"), + (t.style.height = this.config.lineHeight + "px"), + t + ); + }), + (this.$renderWrappedLine = function (e, t, n) { + var r = 0, + i = 0, + o = n[0], + u = 0, + a = this.$createLineElement(); + e.appendChild(a); + for (var f = 0; f < t.length; f++) { + var l = t[f], + c = l.value; + if (f == 0 && this.displayIndentGuides) { + (r = c.length), (c = this.renderIndentGuide(a, c, o)); + if (!c) continue; + r -= c.length; + } + if (r + c.length < o) + (u = this.$renderToken(a, u, l, c)), (r += c.length); + else { + while (r + c.length >= o) + (u = this.$renderToken(a, u, l, c.substring(0, o - r))), + (c = c.substring(o - r)), + (r = o), + (a = this.$createLineElement()), + e.appendChild(a), + a.appendChild( + this.dom.createTextNode( + s.stringRepeat("\u00a0", n.indent), + this.element, + ), + ), + i++, + (u = 0), + (o = n[i] || Number.MAX_VALUE); + c.length != 0 && + ((r += c.length), (u = this.$renderToken(a, u, l, c))); + } + } + }), + (this.$renderSimpleLine = function (e, t) { + var n = 0, + r = t[0], + i = r.value; + this.displayIndentGuides && (i = this.renderIndentGuide(e, i)), + i && (n = this.$renderToken(e, n, r, i)); + for (var s = 1; s < t.length; s++) { + (r = t[s]), (i = r.value); + if (n + i.length > this.MAX_LINE_LENGTH) + return this.$renderOverflowMessage(e, n, r, i); + n = this.$renderToken(e, n, r, i); + } + }), + (this.$renderOverflowMessage = function (e, t, n, r) { + this.$renderToken(e, t, n, r.slice(0, this.MAX_LINE_LENGTH - t)); + var i = this.dom.createElement("span"); + (i.className = "ace_inline_button ace_keyword ace_toggle_wrap"), + (i.style.position = "absolute"), + (i.style.right = "0"), + (i.textContent = ""), + e.appendChild(i); + }), + (this.$renderLine = function (e, t, n) { + !n && n != 0 && (n = this.session.getFoldLine(t)); + if (n) var r = this.$getFoldLineTokens(t, n); + else var r = this.session.getTokens(t); + var i = e; + if (r.length) { + var s = this.session.getRowSplitData(t); + if (s && s.length) { + this.$renderWrappedLine(e, r, s); + var i = e.lastChild; + } else { + var i = e; + this.$useLineGroups() && + ((i = this.$createLineElement()), e.appendChild(i)), + this.$renderSimpleLine(i, r); + } + } else + this.$useLineGroups() && + ((i = this.$createLineElement()), e.appendChild(i)); + if (this.showInvisibles && i) { + n && (t = n.end.row); + var o = this.dom.createElement("span"); + (o.className = "ace_invisible ace_invisible_eol"), + (o.textContent = + t == this.session.getLength() - 1 + ? this.EOF_CHAR + : this.EOL_CHAR), + i.appendChild(o); + } + }), + (this.$getFoldLineTokens = function (e, t) { + function i(e, t, n) { + var i = 0, + s = 0; + while (s + e[i].value.length < t) { + (s += e[i].value.length), i++; + if (i == e.length) return; + } + if (s != t) { + var o = e[i].value.substring(t - s); + o.length > n - t && (o = o.substring(0, n - t)), + r.push({ type: e[i].type, value: o }), + (s = t + o.length), + (i += 1); + } + while (s < n && i < e.length) { + var o = e[i].value; + o.length + s > n + ? r.push({ type: e[i].type, value: o.substring(0, n - s) }) + : r.push(e[i]), + (s += o.length), + (i += 1); + } + } + var n = this.session, + r = [], + s = n.getTokens(e); + return ( + t.walk( + function (e, t, o, u, a) { + e != null + ? r.push({ type: "fold", value: e }) + : (a && (s = n.getTokens(t)), s.length && i(s, u, o)); + }, + t.end.row, + this.session.getLine(t.end.row).length, + ), + r + ); + }), + (this.$useLineGroups = function () { + return this.session.getUseWrapMode(); + }), + (this.destroy = function () {}); + }).call(a.prototype), + (t.Text = a); + }, + ), + define("ace/layer/cursor", ["require", "exports", "module", "ace/lib/dom"], function (e, t, n) { + "use strict"; + var r = e("../lib/dom"), + i = function (e) { + (this.element = r.createElement("div")), + (this.element.className = "ace_layer ace_cursor-layer"), + e.appendChild(this.element), + (this.isVisible = !1), + (this.isBlinking = !0), + (this.blinkInterval = 1e3), + (this.smoothBlinking = !1), + (this.cursors = []), + (this.cursor = this.addCursor()), + r.addCssClass(this.element, "ace_hidden-cursors"), + (this.$updateCursors = this.$updateOpacity.bind(this)); + }; + (function () { + (this.$updateOpacity = function (e) { + var t = this.cursors; + for (var n = t.length; n--; ) r.setStyle(t[n].style, "opacity", e ? "" : "0"); + }), + (this.$startCssAnimation = function () { + var e = this.cursors; + for (var t = e.length; t--; ) + e[t].style.animationDuration = this.blinkInterval + "ms"; + setTimeout( + function () { + r.addCssClass(this.element, "ace_animate-blinking"); + }.bind(this), + ); + }), + (this.$stopCssAnimation = function () { + r.removeCssClass(this.element, "ace_animate-blinking"); + }), + (this.$padding = 0), + (this.setPadding = function (e) { + this.$padding = e; + }), + (this.setSession = function (e) { + this.session = e; + }), + (this.setBlinking = function (e) { + e != this.isBlinking && ((this.isBlinking = e), this.restartTimer()); + }), + (this.setBlinkInterval = function (e) { + e != this.blinkInterval && ((this.blinkInterval = e), this.restartTimer()); + }), + (this.setSmoothBlinking = function (e) { + e != this.smoothBlinking && + ((this.smoothBlinking = e), + r.setCssClass(this.element, "ace_smooth-blinking", e), + this.$updateCursors(!0), + this.restartTimer()); + }), + (this.addCursor = function () { + var e = r.createElement("div"); + return ( + (e.className = "ace_cursor"), + this.element.appendChild(e), + this.cursors.push(e), + e + ); + }), + (this.removeCursor = function () { + if (this.cursors.length > 1) { + var e = this.cursors.pop(); + return e.parentNode.removeChild(e), e; + } + }), + (this.hideCursor = function () { + (this.isVisible = !1), + r.addCssClass(this.element, "ace_hidden-cursors"), + this.restartTimer(); + }), + (this.showCursor = function () { + (this.isVisible = !0), + r.removeCssClass(this.element, "ace_hidden-cursors"), + this.restartTimer(); + }), + (this.restartTimer = function () { + var e = this.$updateCursors; + clearInterval(this.intervalId), + clearTimeout(this.timeoutId), + this.$stopCssAnimation(), + this.smoothBlinking && + r.removeCssClass(this.element, "ace_smooth-blinking"), + e(!0); + if (!this.isBlinking || !this.blinkInterval || !this.isVisible) { + this.$stopCssAnimation(); + return; + } + this.smoothBlinking && + setTimeout( + function () { + r.addCssClass(this.element, "ace_smooth-blinking"); + }.bind(this), + ); + if (r.HAS_CSS_ANIMATION) this.$startCssAnimation(); + else { + var t = function () { + this.timeoutId = setTimeout(function () { + e(!1); + }, 0.6 * this.blinkInterval); + }.bind(this); + (this.intervalId = setInterval(function () { + e(!0), t(); + }, this.blinkInterval)), + t(); + } + }), + (this.getPixelPosition = function (e, t) { + if (!this.config || !this.session) return { left: 0, top: 0 }; + e || (e = this.session.selection.getCursor()); + var n = this.session.documentToScreenPosition(e), + r = + this.$padding + + (this.session.$bidiHandler.isBidiRow(n.row, e.row) + ? this.session.$bidiHandler.getPosLeft(n.column) + : n.column * this.config.characterWidth), + i = (n.row - (t ? this.config.firstRowScreen : 0)) * this.config.lineHeight; + return { left: r, top: i }; + }), + (this.isCursorInView = function (e, t) { + return e.top >= 0 && e.top < t.maxHeight; + }), + (this.update = function (e) { + this.config = e; + var t = this.session.$selectionMarkers, + n = 0, + i = 0; + if (t === undefined || t.length === 0) t = [{ cursor: null }]; + for (var n = 0, s = t.length; n < s; n++) { + var o = this.getPixelPosition(t[n].cursor, !0); + if ((o.top > e.height + e.offset || o.top < 0) && n > 1) continue; + var u = this.cursors[i++] || this.addCursor(), + a = u.style; + this.drawCursor + ? this.drawCursor(u, o, e, t[n], this.session) + : this.isCursorInView(o, e) + ? (r.setStyle(a, "display", "block"), + r.translate(u, o.left, o.top), + r.setStyle(a, "width", Math.round(e.characterWidth) + "px"), + r.setStyle(a, "height", e.lineHeight + "px")) + : r.setStyle(a, "display", "none"); + } + while (this.cursors.length > i) this.removeCursor(); + var f = this.session.getOverwrite(); + this.$setOverwrite(f), (this.$pixelPos = o), this.restartTimer(); + }), + (this.drawCursor = null), + (this.$setOverwrite = function (e) { + e != this.overwrite && + ((this.overwrite = e), + e + ? r.addCssClass(this.element, "ace_overwrite-cursors") + : r.removeCssClass(this.element, "ace_overwrite-cursors")); + }), + (this.destroy = function () { + clearInterval(this.intervalId), clearTimeout(this.timeoutId); + }); + }).call(i.prototype), + (t.Cursor = i); + }), + define( + "ace/scrollbar", + [ + "require", + "exports", + "module", + "ace/lib/oop", + "ace/lib/dom", + "ace/lib/event", + "ace/lib/event_emitter", + ], + function (e, t, n) { + "use strict"; + var r = e("./lib/oop"), + i = e("./lib/dom"), + s = e("./lib/event"), + o = e("./lib/event_emitter").EventEmitter, + u = 32768, + a = function (e) { + (this.element = i.createElement("div")), + (this.element.className = "ace_scrollbar ace_scrollbar" + this.classSuffix), + (this.inner = i.createElement("div")), + (this.inner.className = "ace_scrollbar-inner"), + this.element.appendChild(this.inner), + e.appendChild(this.element), + this.setVisible(!1), + (this.skipEvent = !1), + s.addListener(this.element, "scroll", this.onScroll.bind(this)), + s.addListener(this.element, "mousedown", s.preventDefault); + }; + (function () { + r.implement(this, o), + (this.setVisible = function (e) { + (this.element.style.display = e ? "" : "none"), + (this.isVisible = e), + (this.coeff = 1); + }); + }).call(a.prototype); + var f = function (e, t) { + a.call(this, e), + (this.scrollTop = 0), + (this.scrollHeight = 0), + (t.$scrollbarWidth = this.width = i.scrollbarWidth(e.ownerDocument)), + (this.inner.style.width = this.element.style.width = + (this.width || 15) + 5 + "px"), + (this.$minWidth = 0); + }; + r.inherits(f, a), + function () { + (this.classSuffix = "-v"), + (this.onScroll = function () { + if (!this.skipEvent) { + this.scrollTop = this.element.scrollTop; + if (this.coeff != 1) { + var e = this.element.clientHeight / this.scrollHeight; + this.scrollTop = (this.scrollTop * (1 - e)) / (this.coeff - e); + } + this._emit("scroll", { data: this.scrollTop }); + } + this.skipEvent = !1; + }), + (this.getWidth = function () { + return Math.max(this.isVisible ? this.width : 0, this.$minWidth || 0); + }), + (this.setHeight = function (e) { + this.element.style.height = e + "px"; + }), + (this.setInnerHeight = this.setScrollHeight = + function (e) { + (this.scrollHeight = e), + e > u + ? ((this.coeff = u / e), (e = u)) + : this.coeff != 1 && (this.coeff = 1), + (this.inner.style.height = e + "px"); + }), + (this.setScrollTop = function (e) { + this.scrollTop != e && + ((this.skipEvent = !0), + (this.scrollTop = e), + (this.element.scrollTop = e * this.coeff)); + }); + }.call(f.prototype); + var l = function (e, t) { + a.call(this, e), + (this.scrollLeft = 0), + (this.height = t.$scrollbarWidth), + (this.inner.style.height = this.element.style.height = + (this.height || 15) + 5 + "px"); + }; + r.inherits(l, a), + function () { + (this.classSuffix = "-h"), + (this.onScroll = function () { + this.skipEvent || + ((this.scrollLeft = this.element.scrollLeft), + this._emit("scroll", { data: this.scrollLeft })), + (this.skipEvent = !1); + }), + (this.getHeight = function () { + return this.isVisible ? this.height : 0; + }), + (this.setWidth = function (e) { + this.element.style.width = e + "px"; + }), + (this.setInnerWidth = function (e) { + this.inner.style.width = e + "px"; + }), + (this.setScrollWidth = function (e) { + this.inner.style.width = e + "px"; + }), + (this.setScrollLeft = function (e) { + this.scrollLeft != e && + ((this.skipEvent = !0), + (this.scrollLeft = this.element.scrollLeft = e)); + }); + }.call(l.prototype), + (t.ScrollBar = f), + (t.ScrollBarV = f), + (t.ScrollBarH = l), + (t.VScrollBar = f), + (t.HScrollBar = l); + }, + ), + define("ace/renderloop", ["require", "exports", "module", "ace/lib/event"], function (e, t, n) { + "use strict"; + var r = e("./lib/event"), + i = function (e, t) { + (this.onRender = e), + (this.pending = !1), + (this.changes = 0), + (this.window = t || window); + var n = this; + this._flush = function (e) { + var t = n.changes; + t && (r.blockIdle(100), (n.changes = 0), n.onRender(t)), + n.changes && n.schedule(); + }; + }; + (function () { + this.schedule = function (e) { + (this.changes = this.changes | e), this.changes && r.nextFrame(this._flush); + }; + }).call(i.prototype), + (t.RenderLoop = i); + }), + define( + "ace/layer/font_metrics", + [ + "require", + "exports", + "module", + "ace/lib/oop", + "ace/lib/dom", + "ace/lib/lang", + "ace/lib/event", + "ace/lib/useragent", + "ace/lib/event_emitter", + ], + function (e, t, n) { + var r = e("../lib/oop"), + i = e("../lib/dom"), + s = e("../lib/lang"), + o = e("../lib/event"), + u = e("../lib/useragent"), + a = e("../lib/event_emitter").EventEmitter, + f = 256, + l = typeof ResizeObserver == "function", + c = 200, + h = (t.FontMetrics = function (e) { + (this.el = i.createElement("div")), + this.$setMeasureNodeStyles(this.el.style, !0), + (this.$main = i.createElement("div")), + this.$setMeasureNodeStyles(this.$main.style), + (this.$measureNode = i.createElement("div")), + this.$setMeasureNodeStyles(this.$measureNode.style), + this.el.appendChild(this.$main), + this.el.appendChild(this.$measureNode), + e.appendChild(this.el), + (this.$measureNode.innerHTML = s.stringRepeat("X", f)), + (this.$characterSize = { width: 0, height: 0 }), + l ? this.$addObserver() : this.checkForSizeChanges(); + }); + (function () { + r.implement(this, a), + (this.$characterSize = { width: 0, height: 0 }), + (this.$setMeasureNodeStyles = function (e, t) { + (e.width = e.height = "auto"), + (e.left = e.top = "0px"), + (e.visibility = "hidden"), + (e.position = "absolute"), + (e.whiteSpace = "pre"), + u.isIE < 8 ? (e["font-family"] = "inherit") : (e.font = "inherit"), + (e.overflow = t ? "hidden" : "visible"); + }), + (this.checkForSizeChanges = function (e) { + e === undefined && (e = this.$measureSizes()); + if ( + e && + (this.$characterSize.width !== e.width || + this.$characterSize.height !== e.height) + ) { + this.$measureNode.style.fontWeight = "bold"; + var t = this.$measureSizes(); + (this.$measureNode.style.fontWeight = ""), + (this.$characterSize = e), + (this.charSizes = Object.create(null)), + (this.allowBoldFonts = + t && t.width === e.width && t.height === e.height), + this._emit("changeCharacterSize", { data: e }); + } + }), + (this.$addObserver = function () { + var e = this; + (this.$observer = new window.ResizeObserver(function (t) { + var n = t[0].contentRect; + e.checkForSizeChanges({ height: n.height, width: n.width / f }); + })), + this.$observer.observe(this.$measureNode); + }), + (this.$pollSizeChanges = function () { + if (this.$pollSizeChangesTimer || this.$observer) + return this.$pollSizeChangesTimer; + var e = this; + return (this.$pollSizeChangesTimer = o.onIdle(function t() { + e.checkForSizeChanges(), o.onIdle(t, 500); + }, 500)); + }), + (this.setPolling = function (e) { + e + ? this.$pollSizeChanges() + : this.$pollSizeChangesTimer && + (clearInterval(this.$pollSizeChangesTimer), + (this.$pollSizeChangesTimer = 0)); + }), + (this.$measureSizes = function (e) { + var t = { + height: (e || this.$measureNode).clientHeight, + width: (e || this.$measureNode).clientWidth / f, + }; + return t.width === 0 || t.height === 0 ? null : t; + }), + (this.$measureCharWidth = function (e) { + this.$main.innerHTML = s.stringRepeat(e, f); + var t = this.$main.getBoundingClientRect(); + return t.width / f; + }), + (this.getCharacterWidth = function (e) { + var t = this.charSizes[e]; + return ( + t === undefined && + (t = this.charSizes[e] = + this.$measureCharWidth(e) / this.$characterSize.width), + t + ); + }), + (this.destroy = function () { + clearInterval(this.$pollSizeChangesTimer), + this.$observer && this.$observer.disconnect(), + this.el && + this.el.parentNode && + this.el.parentNode.removeChild(this.el); + }), + (this.$getZoom = function e(t) { + return t ? (window.getComputedStyle(t).zoom || 1) * e(t.parentElement) : 1; + }), + (this.$initTransformMeasureNodes = function () { + var e = function (e, t) { + return [ + "div", + { style: "position: absolute;top:" + e + "px;left:" + t + "px;" }, + ]; + }; + this.els = i.buildDom([e(0, 0), e(c, 0), e(0, c), e(c, c)], this.el); + }), + (this.transformCoordinates = function (e, t) { + function r(e, t, n) { + var r = e[1] * t[0] - e[0] * t[1]; + return [ + (-t[1] * n[0] + t[0] * n[1]) / r, + (+e[1] * n[0] - e[0] * n[1]) / r, + ]; + } + function i(e, t) { + return [e[0] - t[0], e[1] - t[1]]; + } + function s(e, t) { + return [e[0] + t[0], e[1] + t[1]]; + } + function o(e, t) { + return [e * t[0], e * t[1]]; + } + function u(e) { + var t = e.getBoundingClientRect(); + return [t.left, t.top]; + } + if (e) { + var n = this.$getZoom(this.el); + e = o(1 / n, e); + } + this.els || this.$initTransformMeasureNodes(); + var a = u(this.els[0]), + f = u(this.els[1]), + l = u(this.els[2]), + h = u(this.els[3]), + p = r(i(h, f), i(h, l), i(s(f, l), s(h, a))), + d = o(1 + p[0], i(f, a)), + v = o(1 + p[1], i(l, a)); + if (t) { + var m = t, + g = (p[0] * m[0]) / c + (p[1] * m[1]) / c + 1, + y = s(o(m[0], d), o(m[1], v)); + return s(o(1 / g / c, y), a); + } + var b = i(e, a), + w = r(i(d, o(p[0], b)), i(v, o(p[1], b)), b); + return o(c, w); + }); + }).call(h.prototype); + }, + ), + define( + "ace/virtual_renderer", + [ + "require", + "exports", + "module", + "ace/lib/oop", + "ace/lib/dom", + "ace/config", + "ace/layer/gutter", + "ace/layer/marker", + "ace/layer/text", + "ace/layer/cursor", + "ace/scrollbar", + "ace/scrollbar", + "ace/renderloop", + "ace/layer/font_metrics", + "ace/lib/event_emitter", + "ace/lib/useragent", + ], + function (e, t, n) { + "use strict"; + var r = e("./lib/oop"), + i = e("./lib/dom"), + s = e("./config"), + o = e("./layer/gutter").Gutter, + u = e("./layer/marker").Marker, + a = e("./layer/text").Text, + f = e("./layer/cursor").Cursor, + l = e("./scrollbar").HScrollBar, + c = e("./scrollbar").VScrollBar, + h = e("./renderloop").RenderLoop, + p = e("./layer/font_metrics").FontMetrics, + d = e("./lib/event_emitter").EventEmitter, + v = + '.ace_br1 {border-top-left-radius : 3px;}.ace_br2 {border-top-right-radius : 3px;}.ace_br3 {border-top-left-radius : 3px; border-top-right-radius: 3px;}.ace_br4 {border-bottom-right-radius: 3px;}.ace_br5 {border-top-left-radius : 3px; border-bottom-right-radius: 3px;}.ace_br6 {border-top-right-radius : 3px; border-bottom-right-radius: 3px;}.ace_br7 {border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px;}.ace_br8 {border-bottom-left-radius : 3px;}.ace_br9 {border-top-left-radius : 3px; border-bottom-left-radius: 3px;}.ace_br10{border-top-right-radius : 3px; border-bottom-left-radius: 3px;}.ace_br11{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_br13{border-top-left-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_br14{border-top-right-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_br15{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_editor {position: relative;overflow: hidden;font: 12px/normal \'Monaco\', \'Menlo\', \'Ubuntu Mono\', \'Consolas\', \'source-code-pro\', monospace;direction: ltr;text-align: left;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}.ace_scroller {position: absolute;overflow: hidden;top: 0;bottom: 0;background-color: inherit;-ms-user-select: none;-moz-user-select: none;-webkit-user-select: none;user-select: none;cursor: text;}.ace_content {position: absolute;box-sizing: border-box;min-width: 100%;contain: style size layout;}.ace_dragging .ace_scroller:before{position: absolute;top: 0;left: 0;right: 0;bottom: 0;content: \'\';background: rgba(250, 250, 250, 0.01);z-index: 1000;}.ace_dragging.ace_dark .ace_scroller:before{background: rgba(0, 0, 0, 0.01);}.ace_selecting, .ace_selecting * {cursor: text !important;}.ace_gutter {position: absolute;overflow : hidden;width: auto;top: 0;bottom: 0;left: 0;cursor: default;z-index: 4;-ms-user-select: none;-moz-user-select: none;-webkit-user-select: none;user-select: none;contain: style size layout;}.ace_gutter-active-line {position: absolute;left: 0;right: 0;}.ace_scroller.ace_scroll-left {box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;}.ace_gutter-cell {position: absolute;top: 0;left: 0;right: 0;padding-left: 19px;padding-right: 6px;background-repeat: no-repeat;}.ace_gutter-cell.ace_error {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg==");background-repeat: no-repeat;background-position: 2px center;}.ace_gutter-cell.ace_warning {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg==");background-position: 2px center;}.ace_gutter-cell.ace_info {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII=");background-position: 2px center;}.ace_dark .ace_gutter-cell.ace_info {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC");}.ace_scrollbar {contain: strict;position: absolute;right: 0;bottom: 0;z-index: 6;}.ace_scrollbar-inner {position: absolute;cursor: text;left: 0;top: 0;}.ace_scrollbar-v{overflow-x: hidden;overflow-y: scroll;top: 0;}.ace_scrollbar-h {overflow-x: scroll;overflow-y: hidden;left: 0;}.ace_print-margin {position: absolute;height: 100%;}.ace_text-input {position: absolute;z-index: 0;width: 0.5em;height: 1em;opacity: 0;background: transparent;-moz-appearance: none;appearance: none;border: none;resize: none;outline: none;overflow: hidden;font: inherit;padding: 0 1px;margin: 0 -1px;contain: strict;-ms-user-select: text;-moz-user-select: text;-webkit-user-select: text;user-select: text;white-space: pre!important;}.ace_text-input.ace_composition {background: transparent;color: inherit;z-index: 1000;opacity: 1;}.ace_composition_placeholder { color: transparent }.ace_composition_marker { border-bottom: 1px solid;position: absolute;border-radius: 0;margin-top: 1px;}[ace_nocontext=true] {transform: none!important;filter: none!important;perspective: none!important;clip-path: none!important;mask : none!important;contain: none!important;perspective: none!important;mix-blend-mode: initial!important;z-index: auto;}.ace_layer {z-index: 1;position: absolute;overflow: hidden;word-wrap: normal;white-space: pre;height: 100%;width: 100%;box-sizing: border-box;pointer-events: none;}.ace_gutter-layer {position: relative;width: auto;text-align: right;pointer-events: auto;height: 1000000px;contain: style size layout;}.ace_text-layer {font: inherit !important;position: absolute;height: 1000000px;width: 1000000px;contain: style size layout;}.ace_text-layer > .ace_line, .ace_text-layer > .ace_line_group {contain: style size layout;position: absolute;top: 0;left: 0;right: 0;}.ace_hidpi .ace_text-layer,.ace_hidpi .ace_gutter-layer,.ace_hidpi .ace_content,.ace_hidpi .ace_gutter {contain: strict;will-change: transform;}.ace_hidpi .ace_text-layer > .ace_line, .ace_hidpi .ace_text-layer > .ace_line_group {contain: strict;}.ace_cjk {display: inline-block;text-align: center;}.ace_cursor-layer {z-index: 4;}.ace_cursor {z-index: 4;position: absolute;box-sizing: border-box;border-left: 2px solid;transform: translatez(0);}.ace_multiselect .ace_cursor {border-left-width: 1px;}.ace_slim-cursors .ace_cursor {border-left-width: 1px;}.ace_overwrite-cursors .ace_cursor {border-left-width: 0;border-bottom: 1px solid;}.ace_hidden-cursors .ace_cursor {opacity: 0.2;}.ace_smooth-blinking .ace_cursor {transition: opacity 0.18s;}.ace_animate-blinking .ace_cursor {animation-duration: 1000ms;animation-timing-function: step-end;animation-name: blink-ace-animate;animation-iteration-count: infinite;}.ace_animate-blinking.ace_smooth-blinking .ace_cursor {animation-duration: 1000ms;animation-timing-function: ease-in-out;animation-name: blink-ace-animate-smooth;}@keyframes blink-ace-animate {from, to { opacity: 1; }60% { opacity: 0; }}@keyframes blink-ace-animate-smooth {from, to { opacity: 1; }45% { opacity: 1; }60% { opacity: 0; }85% { opacity: 0; }}.ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {position: absolute;z-index: 3;}.ace_marker-layer .ace_selection {position: absolute;z-index: 5;}.ace_marker-layer .ace_bracket {position: absolute;z-index: 6;}.ace_marker-layer .ace_active-line {position: absolute;z-index: 2;}.ace_marker-layer .ace_selected-word {position: absolute;z-index: 4;box-sizing: border-box;}.ace_line .ace_fold {box-sizing: border-box;display: inline-block;height: 11px;margin-top: -2px;vertical-align: middle;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="),url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII=");background-repeat: no-repeat, repeat-x;background-position: center center, top left;color: transparent;border: 1px solid black;border-radius: 2px;cursor: pointer;pointer-events: auto;}.ace_dark .ace_fold {}.ace_fold:hover{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="),url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC");}.ace_tooltip {background-color: #FFF;background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));border: 1px solid gray;border-radius: 1px;box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);color: black;max-width: 100%;padding: 3px 4px;position: fixed;z-index: 999999;box-sizing: border-box;cursor: default;white-space: pre;word-wrap: break-word;line-height: normal;font-style: normal;font-weight: normal;letter-spacing: normal;pointer-events: none;}.ace_folding-enabled > .ace_gutter-cell {padding-right: 13px;}.ace_fold-widget {box-sizing: border-box;margin: 0 -12px 0 1px;display: none;width: 11px;vertical-align: top;background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==");background-repeat: no-repeat;background-position: center;border-radius: 3px;border: 1px solid transparent;cursor: pointer;}.ace_folding-enabled .ace_fold-widget {display: inline-block; }.ace_fold-widget.ace_end {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg==");}.ace_fold-widget.ace_closed {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA==");}.ace_fold-widget:hover {border: 1px solid rgba(0, 0, 0, 0.3);background-color: rgba(255, 255, 255, 0.2);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);}.ace_fold-widget:active {border: 1px solid rgba(0, 0, 0, 0.4);background-color: rgba(0, 0, 0, 0.05);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);}.ace_dark .ace_fold-widget {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC");}.ace_dark .ace_fold-widget.ace_end {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==");}.ace_dark .ace_fold-widget.ace_closed {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==");}.ace_dark .ace_fold-widget:hover {box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);background-color: rgba(255, 255, 255, 0.1);}.ace_dark .ace_fold-widget:active {box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);}.ace_inline_button {border: 1px solid lightgray;display: inline-block;margin: -1px 8px;padding: 0 5px;pointer-events: auto;cursor: pointer;}.ace_inline_button:hover {border-color: gray;background: rgba(200,200,200,0.2);display: inline-block;pointer-events: auto;}.ace_fold-widget.ace_invalid {background-color: #FFB4B4;border-color: #DE5555;}.ace_fade-fold-widgets .ace_fold-widget {transition: opacity 0.4s ease 0.05s;opacity: 0;}.ace_fade-fold-widgets:hover .ace_fold-widget {transition: opacity 0.05s ease 0.05s;opacity:1;}.ace_underline {text-decoration: underline;}.ace_bold {font-weight: bold;}.ace_nobold .ace_bold {font-weight: normal;}.ace_italic {font-style: italic;}.ace_error-marker {background-color: rgba(255, 0, 0,0.2);position: absolute;z-index: 9;}.ace_highlight-marker {background-color: rgba(255, 255, 0,0.2);position: absolute;z-index: 8;}.ace_text-input-ios {position: absolute !important;top: -100000px !important;left: -100000px !important;}', + m = e("./lib/useragent"), + g = m.isIE; + i.importCssString(v, "ace_editor.css"); + var y = function (e, t) { + var n = this; + (this.container = e || i.createElement("div")), + i.addCssClass(this.container, "ace_editor"), + i.HI_DPI && i.addCssClass(this.container, "ace_hidpi"), + this.setTheme(t), + (this.$gutter = i.createElement("div")), + (this.$gutter.className = "ace_gutter"), + this.container.appendChild(this.$gutter), + this.$gutter.setAttribute("aria-hidden", !0), + (this.scroller = i.createElement("div")), + (this.scroller.className = "ace_scroller"), + this.container.appendChild(this.scroller), + (this.content = i.createElement("div")), + (this.content.className = "ace_content"), + this.scroller.appendChild(this.content), + (this.$gutterLayer = new o(this.$gutter)), + this.$gutterLayer.on("changeGutterWidth", this.onGutterResize.bind(this)), + (this.$markerBack = new u(this.content)); + var r = (this.$textLayer = new a(this.content)); + (this.canvas = r.element), + (this.$markerFront = new u(this.content)), + (this.$cursorLayer = new f(this.content)), + (this.$horizScroll = !1), + (this.$vScroll = !1), + (this.scrollBar = this.scrollBarV = new c(this.container, this)), + (this.scrollBarH = new l(this.container, this)), + this.scrollBarV.addEventListener("scroll", function (e) { + n.$scrollAnimation || n.session.setScrollTop(e.data - n.scrollMargin.top); + }), + this.scrollBarH.addEventListener("scroll", function (e) { + n.$scrollAnimation || n.session.setScrollLeft(e.data - n.scrollMargin.left); + }), + (this.scrollTop = 0), + (this.scrollLeft = 0), + (this.cursorPos = { row: 0, column: 0 }), + (this.$fontMetrics = new p(this.container)), + this.$textLayer.$setFontMetrics(this.$fontMetrics), + this.$textLayer.addEventListener("changeCharacterSize", function (e) { + n.updateCharacterSize(), + n.onResize(!0, n.gutterWidth, n.$size.width, n.$size.height), + n._signal("changeCharacterSize", e); + }), + (this.$size = { + width: 0, + height: 0, + scrollerHeight: 0, + scrollerWidth: 0, + $dirty: !0, + }), + (this.layerConfig = { + width: 1, + padding: 0, + firstRow: 0, + firstRowScreen: 0, + lastRow: 0, + lineHeight: 0, + characterWidth: 0, + minHeight: 1, + maxHeight: 1, + offset: 0, + height: 1, + gutterOffset: 1, + }), + (this.scrollMargin = { left: 0, right: 0, top: 0, bottom: 0, v: 0, h: 0 }), + (this.margin = { left: 0, right: 0, top: 0, bottom: 0, v: 0, h: 0 }), + (this.$keepTextAreaAtCursor = !0), + (this.$loop = new h( + this.$renderChanges.bind(this), + this.container.ownerDocument.defaultView, + )), + this.$loop.schedule(this.CHANGE_FULL), + this.updateCharacterSize(), + this.setPadding(4), + s.resetOptions(this), + s._emit("renderer", this); + }; + (function () { + (this.CHANGE_CURSOR = 1), + (this.CHANGE_MARKER = 2), + (this.CHANGE_GUTTER = 4), + (this.CHANGE_SCROLL = 8), + (this.CHANGE_LINES = 16), + (this.CHANGE_TEXT = 32), + (this.CHANGE_SIZE = 64), + (this.CHANGE_MARKER_BACK = 128), + (this.CHANGE_MARKER_FRONT = 256), + (this.CHANGE_FULL = 512), + (this.CHANGE_H_SCROLL = 1024), + r.implement(this, d), + (this.updateCharacterSize = function () { + this.$textLayer.allowBoldFonts != this.$allowBoldFonts && + ((this.$allowBoldFonts = this.$textLayer.allowBoldFonts), + this.setStyle("ace_nobold", !this.$allowBoldFonts)), + (this.layerConfig.characterWidth = this.characterWidth = + this.$textLayer.getCharacterWidth()), + (this.layerConfig.lineHeight = this.lineHeight = + this.$textLayer.getLineHeight()), + this.$updatePrintMargin(); + }), + (this.setSession = function (e) { + this.session && + this.session.doc.off("changeNewLineMode", this.onChangeNewLineMode), + (this.session = e), + e && + this.scrollMargin.top && + e.getScrollTop() <= 0 && + e.setScrollTop(-this.scrollMargin.top), + this.$cursorLayer.setSession(e), + this.$markerBack.setSession(e), + this.$markerFront.setSession(e), + this.$gutterLayer.setSession(e), + this.$textLayer.setSession(e); + if (!e) return; + this.$loop.schedule(this.CHANGE_FULL), + this.session.$setFontMetrics(this.$fontMetrics), + (this.scrollBarH.scrollLeft = this.scrollBarV.scrollTop = null), + (this.onChangeNewLineMode = this.onChangeNewLineMode.bind(this)), + this.onChangeNewLineMode(), + this.session.doc.on("changeNewLineMode", this.onChangeNewLineMode); + }), + (this.updateLines = function (e, t, n) { + t === undefined && (t = Infinity), + this.$changedLines + ? (this.$changedLines.firstRow > e && + (this.$changedLines.firstRow = e), + this.$changedLines.lastRow < t && + (this.$changedLines.lastRow = t)) + : (this.$changedLines = { firstRow: e, lastRow: t }); + if (this.$changedLines.lastRow < this.layerConfig.firstRow) { + if (!n) return; + this.$changedLines.lastRow = this.layerConfig.lastRow; + } + if (this.$changedLines.firstRow > this.layerConfig.lastRow) return; + this.$loop.schedule(this.CHANGE_LINES); + }), + (this.onChangeNewLineMode = function () { + this.$loop.schedule(this.CHANGE_TEXT), + this.$textLayer.$updateEolChar(), + this.session.$bidiHandler.setEolChar(this.$textLayer.EOL_CHAR); + }), + (this.onChangeTabSize = function () { + this.$loop.schedule(this.CHANGE_TEXT | this.CHANGE_MARKER), + this.$textLayer.onChangeTabSize(); + }), + (this.updateText = function () { + this.$loop.schedule(this.CHANGE_TEXT); + }), + (this.updateFull = function (e) { + e + ? this.$renderChanges(this.CHANGE_FULL, !0) + : this.$loop.schedule(this.CHANGE_FULL); + }), + (this.updateFontSize = function () { + this.$textLayer.checkForSizeChanges(); + }), + (this.$changes = 0), + (this.$updateSizeAsync = function () { + this.$loop.pending ? (this.$size.$dirty = !0) : this.onResize(); + }), + (this.onResize = function (e, t, n, r) { + if (this.resizing > 2) return; + this.resizing > 0 ? this.resizing++ : (this.resizing = e ? 1 : 0); + var i = this.container; + r || (r = i.clientHeight || i.scrollHeight), + n || (n = i.clientWidth || i.scrollWidth); + var s = this.$updateCachedSize(e, t, n, r); + if (!this.$size.scrollerHeight || (!n && !r)) return (this.resizing = 0); + e && (this.$gutterLayer.$padding = null), + e + ? this.$renderChanges(s | this.$changes, !0) + : this.$loop.schedule(s | this.$changes), + this.resizing && (this.resizing = 0), + (this.scrollBarV.scrollLeft = this.scrollBarV.scrollTop = null); + }), + (this.$updateCachedSize = function (e, t, n, r) { + r -= this.$extraHeight || 0; + var s = 0, + o = this.$size, + u = { + width: o.width, + height: o.height, + scrollerHeight: o.scrollerHeight, + scrollerWidth: o.scrollerWidth, + }; + r && + (e || o.height != r) && + ((o.height = r), + (s |= this.CHANGE_SIZE), + (o.scrollerHeight = o.height), + this.$horizScroll && (o.scrollerHeight -= this.scrollBarH.getHeight()), + (this.scrollBarV.element.style.bottom = + this.scrollBarH.getHeight() + "px"), + (s |= this.CHANGE_SCROLL)); + if (n && (e || o.width != n)) { + (s |= this.CHANGE_SIZE), + (o.width = n), + t == null && (t = this.$showGutter ? this.$gutter.offsetWidth : 0), + (this.gutterWidth = t), + i.setStyle(this.scrollBarH.element.style, "left", t + "px"), + i.setStyle( + this.scroller.style, + "left", + t + this.margin.left + "px", + ), + (o.scrollerWidth = Math.max( + 0, + n - t - this.scrollBarV.getWidth() - this.margin.h, + )), + i.setStyle(this.$gutter.style, "left", this.margin.left + "px"); + var a = this.scrollBarV.getWidth() + "px"; + i.setStyle(this.scrollBarH.element.style, "right", a), + i.setStyle(this.scroller.style, "right", a), + i.setStyle( + this.scroller.style, + "bottom", + this.scrollBarH.getHeight(), + ); + if ( + (this.session && + this.session.getUseWrapMode() && + this.adjustWrapLimit()) || + e + ) + s |= this.CHANGE_FULL; + } + return (o.$dirty = !n || !r), s && this._signal("resize", u), s; + }), + (this.onGutterResize = function (e) { + var t = this.$showGutter ? e : 0; + t != this.gutterWidth && + (this.$changes |= this.$updateCachedSize( + !0, + t, + this.$size.width, + this.$size.height, + )), + this.session.getUseWrapMode() && this.adjustWrapLimit() + ? this.$loop.schedule(this.CHANGE_FULL) + : this.$size.$dirty + ? this.$loop.schedule(this.CHANGE_FULL) + : this.$computeLayerConfig(); + }), + (this.adjustWrapLimit = function () { + var e = this.$size.scrollerWidth - this.$padding * 2, + t = Math.floor(e / this.characterWidth); + return this.session.adjustWrapLimit( + t, + this.$showPrintMargin && this.$printMarginColumn, + ); + }), + (this.setAnimatedScroll = function (e) { + this.setOption("animatedScroll", e); + }), + (this.getAnimatedScroll = function () { + return this.$animatedScroll; + }), + (this.setShowInvisibles = function (e) { + this.setOption("showInvisibles", e), + this.session.$bidiHandler.setShowInvisibles(e); + }), + (this.getShowInvisibles = function () { + return this.getOption("showInvisibles"); + }), + (this.getDisplayIndentGuides = function () { + return this.getOption("displayIndentGuides"); + }), + (this.setDisplayIndentGuides = function (e) { + this.setOption("displayIndentGuides", e); + }), + (this.setShowPrintMargin = function (e) { + this.setOption("showPrintMargin", e); + }), + (this.getShowPrintMargin = function () { + return this.getOption("showPrintMargin"); + }), + (this.setPrintMarginColumn = function (e) { + this.setOption("printMarginColumn", e); + }), + (this.getPrintMarginColumn = function () { + return this.getOption("printMarginColumn"); + }), + (this.getShowGutter = function () { + return this.getOption("showGutter"); + }), + (this.setShowGutter = function (e) { + return this.setOption("showGutter", e); + }), + (this.getFadeFoldWidgets = function () { + return this.getOption("fadeFoldWidgets"); + }), + (this.setFadeFoldWidgets = function (e) { + this.setOption("fadeFoldWidgets", e); + }), + (this.setHighlightGutterLine = function (e) { + this.setOption("highlightGutterLine", e); + }), + (this.getHighlightGutterLine = function () { + return this.getOption("highlightGutterLine"); + }), + (this.$updatePrintMargin = function () { + if (!this.$showPrintMargin && !this.$printMarginEl) return; + if (!this.$printMarginEl) { + var e = i.createElement("div"); + (e.className = "ace_layer ace_print-margin-layer"), + (this.$printMarginEl = i.createElement("div")), + (this.$printMarginEl.className = "ace_print-margin"), + e.appendChild(this.$printMarginEl), + this.content.insertBefore(e, this.content.firstChild); + } + var t = this.$printMarginEl.style; + (t.left = + Math.round( + this.characterWidth * this.$printMarginColumn + this.$padding, + ) + "px"), + (t.visibility = this.$showPrintMargin ? "visible" : "hidden"), + this.session && this.session.$wrap == -1 && this.adjustWrapLimit(); + }), + (this.getContainerElement = function () { + return this.container; + }), + (this.getMouseEventTarget = function () { + return this.scroller; + }), + (this.getTextAreaContainer = function () { + return this.container; + }), + (this.$moveTextAreaToCursor = function () { + var e = this.textarea.style; + if (!this.$keepTextAreaAtCursor) { + i.translate(this.textarea, -100, 0); + return; + } + var t = this.$cursorLayer.$pixelPos; + if (!t) return; + var n = this.$composition; + n && + n.markerRange && + (t = this.$cursorLayer.getPixelPosition(n.markerRange.start, !0)); + var r = this.layerConfig, + s = t.top, + o = t.left; + s -= r.offset; + var u = n && n.useTextareaForIME ? this.lineHeight : g ? 0 : 1; + if (s < 0 || s > r.height - u) { + i.translate(this.textarea, 0, 0); + return; + } + var a = 1; + if (!n) s += this.lineHeight; + else if (n.useTextareaForIME) { + var f = this.textarea.value; + (a = this.characterWidth * this.session.$getStringScreenWidth(f)[0]), + (u += 2); + } else s += this.lineHeight + 2; + (o -= this.scrollLeft), + o > this.$size.scrollerWidth - a && (o = this.$size.scrollerWidth - a), + (o += this.gutterWidth + this.margin.left), + i.setStyle(e, "height", u + "px"), + i.setStyle(e, "width", a + "px"), + i.translate( + this.textarea, + Math.min(o, this.$size.scrollerWidth - a), + Math.min(s, this.$size.height - u), + ); + }), + (this.getFirstVisibleRow = function () { + return this.layerConfig.firstRow; + }), + (this.getFirstFullyVisibleRow = function () { + return this.layerConfig.firstRow + (this.layerConfig.offset === 0 ? 0 : 1); + }), + (this.getLastFullyVisibleRow = function () { + var e = this.layerConfig, + t = e.lastRow, + n = this.session.documentToScreenRow(t, 0) * e.lineHeight; + return n - this.session.getScrollTop() > e.height - e.lineHeight + ? t - 1 + : t; + }), + (this.getLastVisibleRow = function () { + return this.layerConfig.lastRow; + }), + (this.$padding = null), + (this.setPadding = function (e) { + (this.$padding = e), + this.$textLayer.setPadding(e), + this.$cursorLayer.setPadding(e), + this.$markerFront.setPadding(e), + this.$markerBack.setPadding(e), + this.$loop.schedule(this.CHANGE_FULL), + this.$updatePrintMargin(); + }), + (this.setScrollMargin = function (e, t, n, r) { + var i = this.scrollMargin; + (i.top = e | 0), + (i.bottom = t | 0), + (i.right = r | 0), + (i.left = n | 0), + (i.v = i.top + i.bottom), + (i.h = i.left + i.right), + i.top && + this.scrollTop <= 0 && + this.session && + this.session.setScrollTop(-i.top), + this.updateFull(); + }), + (this.setMargin = function (e, t, n, r) { + var i = this.margin; + (i.top = e | 0), + (i.bottom = t | 0), + (i.right = r | 0), + (i.left = n | 0), + (i.v = i.top + i.bottom), + (i.h = i.left + i.right), + this.$updateCachedSize( + !0, + this.gutterWidth, + this.$size.width, + this.$size.height, + ), + this.updateFull(); + }), + (this.getHScrollBarAlwaysVisible = function () { + return this.$hScrollBarAlwaysVisible; + }), + (this.setHScrollBarAlwaysVisible = function (e) { + this.setOption("hScrollBarAlwaysVisible", e); + }), + (this.getVScrollBarAlwaysVisible = function () { + return this.$vScrollBarAlwaysVisible; + }), + (this.setVScrollBarAlwaysVisible = function (e) { + this.setOption("vScrollBarAlwaysVisible", e); + }), + (this.$updateScrollBarV = function () { + var e = this.layerConfig.maxHeight, + t = this.$size.scrollerHeight; + !this.$maxLines && + this.$scrollPastEnd && + ((e -= (t - this.lineHeight) * this.$scrollPastEnd), + this.scrollTop > e - t && + ((e = this.scrollTop + t), (this.scrollBarV.scrollTop = null))), + this.scrollBarV.setScrollHeight(e + this.scrollMargin.v), + this.scrollBarV.setScrollTop(this.scrollTop + this.scrollMargin.top); + }), + (this.$updateScrollBarH = function () { + this.scrollBarH.setScrollWidth( + this.layerConfig.width + 2 * this.$padding + this.scrollMargin.h, + ), + this.scrollBarH.setScrollLeft(this.scrollLeft + this.scrollMargin.left); + }), + (this.$frozen = !1), + (this.freeze = function () { + this.$frozen = !0; + }), + (this.unfreeze = function () { + this.$frozen = !1; + }), + (this.$renderChanges = function (e, t) { + this.$changes && ((e |= this.$changes), (this.$changes = 0)); + if ( + !this.session || + !this.container.offsetWidth || + this.$frozen || + (!e && !t) + ) { + this.$changes |= e; + return; + } + if (this.$size.$dirty) return (this.$changes |= e), this.onResize(!0); + this.lineHeight || this.$textLayer.checkForSizeChanges(), + this._signal("beforeRender"), + this.session && + this.session.$bidiHandler && + this.session.$bidiHandler.updateCharacterWidths(this.$fontMetrics); + var n = this.layerConfig; + if ( + e & this.CHANGE_FULL || + e & this.CHANGE_SIZE || + e & this.CHANGE_TEXT || + e & this.CHANGE_LINES || + e & this.CHANGE_SCROLL || + e & this.CHANGE_H_SCROLL + ) { + e |= this.$computeLayerConfig(); + if ( + n.firstRow != this.layerConfig.firstRow && + n.firstRowScreen == this.layerConfig.firstRowScreen + ) { + var r = + this.scrollTop + + (n.firstRow - this.layerConfig.firstRow) * this.lineHeight; + r > 0 && + ((this.scrollTop = r), + (e |= this.CHANGE_SCROLL), + (e |= this.$computeLayerConfig())); + } + (n = this.layerConfig), + this.$updateScrollBarV(), + e & this.CHANGE_H_SCROLL && this.$updateScrollBarH(), + i.translate(this.content, -this.scrollLeft, -n.offset); + var s = n.width + 2 * this.$padding + "px", + o = n.minHeight + "px"; + i.setStyle(this.content.style, "width", s), + i.setStyle(this.content.style, "height", o); + } + e & this.CHANGE_H_SCROLL && + (i.translate(this.content, -this.scrollLeft, -n.offset), + (this.scroller.className = + this.scrollLeft <= 0 + ? "ace_scroller" + : "ace_scroller ace_scroll-left")); + if (e & this.CHANGE_FULL) { + this.$textLayer.update(n), + this.$showGutter && this.$gutterLayer.update(n), + this.$markerBack.update(n), + this.$markerFront.update(n), + this.$cursorLayer.update(n), + this.$moveTextAreaToCursor(), + this._signal("afterRender"); + return; + } + if (e & this.CHANGE_SCROLL) { + e & this.CHANGE_TEXT || e & this.CHANGE_LINES + ? this.$textLayer.update(n) + : this.$textLayer.scrollLines(n), + this.$showGutter && + (e & this.CHANGE_GUTTER || e & this.CHANGE_LINES + ? this.$gutterLayer.update(n) + : this.$gutterLayer.scrollLines(n)), + this.$markerBack.update(n), + this.$markerFront.update(n), + this.$cursorLayer.update(n), + this.$moveTextAreaToCursor(), + this._signal("afterRender"); + return; + } + e & this.CHANGE_TEXT + ? (this.$textLayer.update(n), + this.$showGutter && this.$gutterLayer.update(n)) + : e & this.CHANGE_LINES + ? (this.$updateLines() || + (e & this.CHANGE_GUTTER && this.$showGutter)) && + this.$gutterLayer.update(n) + : e & this.CHANGE_TEXT || e & this.CHANGE_GUTTER + ? this.$showGutter && this.$gutterLayer.update(n) + : e & this.CHANGE_CURSOR && + this.$highlightGutterLine && + this.$gutterLayer.updateLineHighlight(n), + e & this.CHANGE_CURSOR && + (this.$cursorLayer.update(n), this.$moveTextAreaToCursor()), + e & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT) && + this.$markerFront.update(n), + e & (this.CHANGE_MARKER | this.CHANGE_MARKER_BACK) && + this.$markerBack.update(n), + this._signal("afterRender"); + }), + (this.$autosize = function () { + var e = this.session.getScreenLength() * this.lineHeight, + t = this.$maxLines * this.lineHeight, + n = + Math.min(t, Math.max((this.$minLines || 1) * this.lineHeight, e)) + + this.scrollMargin.v + + (this.$extraHeight || 0); + this.$horizScroll && (n += this.scrollBarH.getHeight()), + this.$maxPixelHeight && + n > this.$maxPixelHeight && + (n = this.$maxPixelHeight); + var r = n <= 2 * this.lineHeight, + i = !r && e > t; + if ( + n != this.desiredHeight || + this.$size.height != this.desiredHeight || + i != this.$vScroll + ) { + i != this.$vScroll && + ((this.$vScroll = i), this.scrollBarV.setVisible(i)); + var s = this.container.clientWidth; + (this.container.style.height = n + "px"), + this.$updateCachedSize(!0, this.$gutterWidth, s, n), + (this.desiredHeight = n), + this._signal("autosize"); + } + }), + (this.$computeLayerConfig = function () { + var e = this.session, + t = this.$size, + n = t.height <= 2 * this.lineHeight, + r = this.session.getScreenLength(), + i = r * this.lineHeight, + s = this.$getLongestLine(), + o = + !n && + (this.$hScrollBarAlwaysVisible || + t.scrollerWidth - s - 2 * this.$padding < 0), + u = this.$horizScroll !== o; + u && ((this.$horizScroll = o), this.scrollBarH.setVisible(o)); + var a = this.$vScroll; + this.$maxLines && this.lineHeight > 1 && this.$autosize(); + var f = this.scrollTop % this.lineHeight, + l = t.scrollerHeight + this.lineHeight, + c = + !this.$maxLines && this.$scrollPastEnd + ? (t.scrollerHeight - this.lineHeight) * this.$scrollPastEnd + : 0; + i += c; + var h = this.scrollMargin; + this.session.setScrollTop( + Math.max( + -h.top, + Math.min(this.scrollTop, i - t.scrollerHeight + h.bottom), + ), + ), + this.session.setScrollLeft( + Math.max( + -h.left, + Math.min( + this.scrollLeft, + s + 2 * this.$padding - t.scrollerWidth + h.right, + ), + ), + ); + var p = + !n && + (this.$vScrollBarAlwaysVisible || + t.scrollerHeight - i + c < 0 || + this.scrollTop > h.top), + d = a !== p; + d && ((this.$vScroll = p), this.scrollBarV.setVisible(p)); + var v = Math.ceil(l / this.lineHeight) - 1, + m = Math.max(0, Math.round((this.scrollTop - f) / this.lineHeight)), + g = m + v, + y, + b, + w = this.lineHeight; + m = e.screenToDocumentRow(m, 0); + var E = e.getFoldLine(m); + E && (m = E.start.row), + (y = e.documentToScreenRow(m, 0)), + (b = e.getRowLength(m) * w), + (g = Math.min(e.screenToDocumentRow(g, 0), e.getLength() - 1)), + (l = t.scrollerHeight + e.getRowLength(g) * w + b), + (f = this.scrollTop - y * w); + var S = 0; + if (this.layerConfig.width != s || u) S = this.CHANGE_H_SCROLL; + if (u || d) + (S = this.$updateCachedSize(!0, this.gutterWidth, t.width, t.height)), + this._signal("scrollbarVisibilityChanged"), + d && (s = this.$getLongestLine()); + return ( + (this.layerConfig = { + width: s, + padding: this.$padding, + firstRow: m, + firstRowScreen: y, + lastRow: g, + lineHeight: w, + characterWidth: this.characterWidth, + minHeight: l, + maxHeight: i, + offset: f, + gutterOffset: w + ? Math.max(0, Math.ceil((f + t.height - t.scrollerHeight) / w)) + : 0, + height: this.$size.scrollerHeight, + }), + this.session.$bidiHandler && + this.session.$bidiHandler.setContentWidth(s - this.$padding), + S + ); + }), + (this.$updateLines = function () { + if (!this.$changedLines) return; + var e = this.$changedLines.firstRow, + t = this.$changedLines.lastRow; + this.$changedLines = null; + var n = this.layerConfig; + if (e > n.lastRow + 1) return; + if (t < n.firstRow) return; + if (t === Infinity) { + this.$showGutter && this.$gutterLayer.update(n), + this.$textLayer.update(n); + return; + } + return this.$textLayer.updateLines(n, e, t), !0; + }), + (this.$getLongestLine = function () { + var e = this.session.getScreenWidth(); + return ( + this.showInvisibles && !this.session.$useWrapMode && (e += 1), + this.$textLayer && + e > this.$textLayer.MAX_LINE_LENGTH && + (e = this.$textLayer.MAX_LINE_LENGTH + 30), + Math.max( + this.$size.scrollerWidth - 2 * this.$padding, + Math.round(e * this.characterWidth), + ) + ); + }), + (this.updateFrontMarkers = function () { + this.$markerFront.setMarkers(this.session.getMarkers(!0)), + this.$loop.schedule(this.CHANGE_MARKER_FRONT); + }), + (this.updateBackMarkers = function () { + this.$markerBack.setMarkers(this.session.getMarkers()), + this.$loop.schedule(this.CHANGE_MARKER_BACK); + }), + (this.addGutterDecoration = function (e, t) { + this.$gutterLayer.addGutterDecoration(e, t); + }), + (this.removeGutterDecoration = function (e, t) { + this.$gutterLayer.removeGutterDecoration(e, t); + }), + (this.updateBreakpoints = function (e) { + this.$loop.schedule(this.CHANGE_GUTTER); + }), + (this.setAnnotations = function (e) { + this.$gutterLayer.setAnnotations(e), + this.$loop.schedule(this.CHANGE_GUTTER); + }), + (this.updateCursor = function () { + this.$loop.schedule(this.CHANGE_CURSOR); + }), + (this.hideCursor = function () { + this.$cursorLayer.hideCursor(); + }), + (this.showCursor = function () { + this.$cursorLayer.showCursor(); + }), + (this.scrollSelectionIntoView = function (e, t, n) { + this.scrollCursorIntoView(e, n), this.scrollCursorIntoView(t, n); + }), + (this.scrollCursorIntoView = function (e, t, n) { + if (this.$size.scrollerHeight === 0) return; + var r = this.$cursorLayer.getPixelPosition(e), + i = r.left, + s = r.top, + o = (n && n.top) || 0, + u = (n && n.bottom) || 0, + a = this.$scrollAnimation + ? this.session.getScrollTop() + : this.scrollTop; + a + o > s + ? (t && + a + o > s + this.lineHeight && + (s -= t * this.$size.scrollerHeight), + s === 0 && (s = -this.scrollMargin.top), + this.session.setScrollTop(s)) + : a + this.$size.scrollerHeight - u < s + this.lineHeight && + (t && + a + this.$size.scrollerHeight - u < s - this.lineHeight && + (s += t * this.$size.scrollerHeight), + this.session.setScrollTop( + s + this.lineHeight - this.$size.scrollerHeight, + )); + var f = this.scrollLeft; + f > i + ? (i < this.$padding + 2 * this.layerConfig.characterWidth && + (i = -this.scrollMargin.left), + this.session.setScrollLeft(i)) + : f + this.$size.scrollerWidth < i + this.characterWidth + ? this.session.setScrollLeft( + Math.round(i + this.characterWidth - this.$size.scrollerWidth), + ) + : f <= this.$padding && + i - f < this.characterWidth && + this.session.setScrollLeft(0); + }), + (this.getScrollTop = function () { + return this.session.getScrollTop(); + }), + (this.getScrollLeft = function () { + return this.session.getScrollLeft(); + }), + (this.getScrollTopRow = function () { + return this.scrollTop / this.lineHeight; + }), + (this.getScrollBottomRow = function () { + return Math.max( + 0, + Math.floor( + (this.scrollTop + this.$size.scrollerHeight) / this.lineHeight, + ) - 1, + ); + }), + (this.scrollToRow = function (e) { + this.session.setScrollTop(e * this.lineHeight); + }), + (this.alignCursor = function (e, t) { + typeof e == "number" && (e = { row: e, column: 0 }); + var n = this.$cursorLayer.getPixelPosition(e), + r = this.$size.scrollerHeight - this.lineHeight, + i = n.top - r * (t || 0); + return this.session.setScrollTop(i), i; + }), + (this.STEPS = 8), + (this.$calcSteps = function (e, t) { + var n = 0, + r = this.STEPS, + i = [], + s = function (e, t, n) { + return n * (Math.pow(e - 1, 3) + 1) + t; + }; + for (n = 0; n < r; ++n) i.push(s(n / this.STEPS, e, t - e)); + return i; + }), + (this.scrollToLine = function (e, t, n, r) { + var i = this.$cursorLayer.getPixelPosition({ row: e, column: 0 }), + s = i.top; + t && (s -= this.$size.scrollerHeight / 2); + var o = this.scrollTop; + this.session.setScrollTop(s), n !== !1 && this.animateScrolling(o, r); + }), + (this.animateScrolling = function (e, t) { + var n = this.scrollTop; + if (!this.$animatedScroll) return; + var r = this; + if (e == n) return; + if (this.$scrollAnimation) { + var i = this.$scrollAnimation.steps; + if (i.length) { + e = i[0]; + if (e == n) return; + } + } + var s = r.$calcSteps(e, n); + (this.$scrollAnimation = { from: e, to: n, steps: s }), + clearInterval(this.$timer), + r.session.setScrollTop(s.shift()), + (r.session.$scrollTop = n), + (this.$timer = setInterval(function () { + s.length + ? (r.session.setScrollTop(s.shift()), + (r.session.$scrollTop = n)) + : n != null + ? ((r.session.$scrollTop = -1), + r.session.setScrollTop(n), + (n = null)) + : ((r.$timer = clearInterval(r.$timer)), + (r.$scrollAnimation = null), + t && t()); + }, 10)); + }), + (this.scrollToY = function (e) { + this.scrollTop !== e && + (this.$loop.schedule(this.CHANGE_SCROLL), (this.scrollTop = e)); + }), + (this.scrollToX = function (e) { + this.scrollLeft !== e && (this.scrollLeft = e), + this.$loop.schedule(this.CHANGE_H_SCROLL); + }), + (this.scrollTo = function (e, t) { + this.session.setScrollTop(t), this.session.setScrollLeft(t); + }), + (this.scrollBy = function (e, t) { + t && this.session.setScrollTop(this.session.getScrollTop() + t), + e && this.session.setScrollLeft(this.session.getScrollLeft() + e); + }), + (this.isScrollableBy = function (e, t) { + if (t < 0 && this.session.getScrollTop() >= 1 - this.scrollMargin.top) + return !0; + if ( + t > 0 && + this.session.getScrollTop() + + this.$size.scrollerHeight - + this.layerConfig.maxHeight < + -1 + this.scrollMargin.bottom + ) + return !0; + if (e < 0 && this.session.getScrollLeft() >= 1 - this.scrollMargin.left) + return !0; + if ( + e > 0 && + this.session.getScrollLeft() + + this.$size.scrollerWidth - + this.layerConfig.width < + -1 + this.scrollMargin.right + ) + return !0; + }), + (this.pixelToScreenCoordinates = function (e, t) { + var n; + if (this.$hasCssTransforms) { + n = { top: 0, left: 0 }; + var r = this.$fontMetrics.transformCoordinates([e, t]); + (e = r[1] - this.gutterWidth - this.margin.left), (t = r[0]); + } else n = this.scroller.getBoundingClientRect(); + var i = e + this.scrollLeft - n.left - this.$padding, + s = i / this.characterWidth, + o = Math.floor((t + this.scrollTop - n.top) / this.lineHeight), + u = this.$blockCursor ? Math.floor(s) : Math.round(s); + return { row: o, column: u, side: s - u > 0 ? 1 : -1, offsetX: i }; + }), + (this.screenToTextCoordinates = function (e, t) { + var n; + if (this.$hasCssTransforms) { + n = { top: 0, left: 0 }; + var r = this.$fontMetrics.transformCoordinates([e, t]); + (e = r[1] - this.gutterWidth - this.margin.left), (t = r[0]); + } else n = this.scroller.getBoundingClientRect(); + var i = e + this.scrollLeft - n.left - this.$padding, + s = i / this.characterWidth, + o = this.$blockCursor ? Math.floor(s) : Math.round(s), + u = Math.floor((t + this.scrollTop - n.top) / this.lineHeight); + return this.session.screenToDocumentPosition(u, Math.max(o, 0), i); + }), + (this.textToScreenCoordinates = function (e, t) { + var n = this.scroller.getBoundingClientRect(), + r = this.session.documentToScreenPosition(e, t), + i = + this.$padding + + (this.session.$bidiHandler.isBidiRow(r.row, e) + ? this.session.$bidiHandler.getPosLeft(r.column) + : Math.round(r.column * this.characterWidth)), + s = r.row * this.lineHeight; + return { + pageX: n.left + i - this.scrollLeft, + pageY: n.top + s - this.scrollTop, + }; + }), + (this.visualizeFocus = function () { + i.addCssClass(this.container, "ace_focus"); + }), + (this.visualizeBlur = function () { + i.removeCssClass(this.container, "ace_focus"); + }), + (this.showComposition = function (e) { + (this.$composition = e), + e.cssText || + ((e.cssText = this.textarea.style.cssText), + (e.keepTextAreaAtCursor = this.$keepTextAreaAtCursor)), + (e.useTextareaForIME = this.$useTextareaForIME), + this.$useTextareaForIME + ? ((this.$keepTextAreaAtCursor = !0), + i.addCssClass(this.textarea, "ace_composition"), + (this.textarea.style.cssText = ""), + this.$moveTextAreaToCursor(), + (this.$cursorLayer.element.style.display = "none")) + : (e.markerId = this.session.addMarker( + e.markerRange, + "ace_composition_marker", + "text", + )); + }), + (this.setCompositionText = function (e) { + var t = this.session.selection.cursor; + this.addToken(e, "composition_placeholder", t.row, t.column), + this.$moveTextAreaToCursor(); + }), + (this.hideComposition = function () { + if (!this.$composition) return; + this.$composition.markerId && + this.session.removeMarker(this.$composition.markerId), + i.removeCssClass(this.textarea, "ace_composition"), + (this.$keepTextAreaAtCursor = this.$composition.keepTextAreaAtCursor), + (this.textarea.style.cssText = this.$composition.cssText), + (this.$composition = null), + (this.$cursorLayer.element.style.display = ""); + }), + (this.addToken = function (e, t, n, r) { + var i = this.session; + i.bgTokenizer.lines[n] = null; + var s = { type: t, value: e }, + o = i.getTokens(n); + if (r == null) o.push(s); + else { + var u = 0; + for (var a = 0; a < o.length; a++) { + var f = o[a]; + u += f.value.length; + if (r <= u) { + var l = f.value.length - (u - r), + c = f.value.slice(0, l), + h = f.value.slice(l); + o.splice(a, 1, { type: f.type, value: c }, s, { + type: f.type, + value: h, + }); + break; + } + } + } + this.updateLines(n, n); + }), + (this.setTheme = function (e, t) { + function o(r) { + if (n.$themeId != e) return t && t(); + if (!r || !r.cssClass) + throw new Error( + "couldn't load module " + e + " or it didn't call define", + ); + r.$id && (n.$themeId = r.$id), + i.importCssString(r.cssText, r.cssClass, n.container), + n.theme && i.removeCssClass(n.container, n.theme.cssClass); + var s = + "padding" in r + ? r.padding + : "padding" in (n.theme || {}) + ? 4 + : n.$padding; + n.$padding && s != n.$padding && n.setPadding(s), + (n.$theme = r.cssClass), + (n.theme = r), + i.addCssClass(n.container, r.cssClass), + i.setCssClass(n.container, "ace_dark", r.isDark), + n.$size && ((n.$size.width = 0), n.$updateSizeAsync()), + n._dispatchEvent("themeLoaded", { theme: r }), + t && t(); + } + var n = this; + (this.$themeId = e), n._dispatchEvent("themeChange", { theme: e }); + if (!e || typeof e == "string") { + var r = e || this.$options.theme.initialValue; + s.loadModule(["theme", r], o); + } else o(e); + }), + (this.getTheme = function () { + return this.$themeId; + }), + (this.setStyle = function (e, t) { + i.setCssClass(this.container, e, t !== !1); + }), + (this.unsetStyle = function (e) { + i.removeCssClass(this.container, e); + }), + (this.setCursorStyle = function (e) { + i.setStyle(this.scroller.style, "cursor", e); + }), + (this.setMouseCursor = function (e) { + i.setStyle(this.scroller.style, "cursor", e); + }), + (this.attachToShadowRoot = function () { + i.importCssString(v, "ace_editor.css", this.container); + }), + (this.destroy = function () { + this.$fontMetrics.destroy(), this.$cursorLayer.destroy(); + }); + }).call(y.prototype), + s.defineOptions(y.prototype, "renderer", { + animatedScroll: { initialValue: !1 }, + showInvisibles: { + set: function (e) { + this.$textLayer.setShowInvisibles(e) && + this.$loop.schedule(this.CHANGE_TEXT); + }, + initialValue: !1, + }, + showPrintMargin: { + set: function () { + this.$updatePrintMargin(); + }, + initialValue: !0, + }, + printMarginColumn: { + set: function () { + this.$updatePrintMargin(); + }, + initialValue: 80, + }, + printMargin: { + set: function (e) { + typeof e == "number" && (this.$printMarginColumn = e), + (this.$showPrintMargin = !!e), + this.$updatePrintMargin(); + }, + get: function () { + return this.$showPrintMargin && this.$printMarginColumn; + }, + }, + showGutter: { + set: function (e) { + (this.$gutter.style.display = e ? "block" : "none"), + this.$loop.schedule(this.CHANGE_FULL), + this.onGutterResize(); + }, + initialValue: !0, + }, + fadeFoldWidgets: { + set: function (e) { + i.setCssClass(this.$gutter, "ace_fade-fold-widgets", e); + }, + initialValue: !1, + }, + showFoldWidgets: { + set: function (e) { + this.$gutterLayer.setShowFoldWidgets(e), + this.$loop.schedule(this.CHANGE_GUTTER); + }, + initialValue: !0, + }, + displayIndentGuides: { + set: function (e) { + this.$textLayer.setDisplayIndentGuides(e) && + this.$loop.schedule(this.CHANGE_TEXT); + }, + initialValue: !0, + }, + highlightGutterLine: { + set: function (e) { + this.$gutterLayer.setHighlightGutterLine(e), + this.$loop.schedule(this.CHANGE_GUTTER); + }, + initialValue: !0, + }, + hScrollBarAlwaysVisible: { + set: function (e) { + (!this.$hScrollBarAlwaysVisible || !this.$horizScroll) && + this.$loop.schedule(this.CHANGE_SCROLL); + }, + initialValue: !1, + }, + vScrollBarAlwaysVisible: { + set: function (e) { + (!this.$vScrollBarAlwaysVisible || !this.$vScroll) && + this.$loop.schedule(this.CHANGE_SCROLL); + }, + initialValue: !1, + }, + fontSize: { + set: function (e) { + typeof e == "number" && (e += "px"), + (this.container.style.fontSize = e), + this.updateFontSize(); + }, + initialValue: 12, + }, + fontFamily: { + set: function (e) { + (this.container.style.fontFamily = e), this.updateFontSize(); + }, + }, + maxLines: { + set: function (e) { + this.updateFull(); + }, + }, + minLines: { + set: function (e) { + this.$minLines < 562949953421311 || (this.$minLines = 0), + this.updateFull(); + }, + }, + maxPixelHeight: { + set: function (e) { + this.updateFull(); + }, + initialValue: 0, + }, + scrollPastEnd: { + set: function (e) { + e = +e || 0; + if (this.$scrollPastEnd == e) return; + (this.$scrollPastEnd = e), this.$loop.schedule(this.CHANGE_SCROLL); + }, + initialValue: 0, + handlesSet: !0, + }, + fixedWidthGutter: { + set: function (e) { + (this.$gutterLayer.$fixedWidth = !!e), + this.$loop.schedule(this.CHANGE_GUTTER); + }, + }, + theme: { + set: function (e) { + this.setTheme(e); + }, + get: function () { + return this.$themeId || this.theme; + }, + initialValue: "./theme/textmate", + handlesSet: !0, + }, + hasCssTransforms: {}, + useTextareaForIME: { initialValue: !m.isMobile && !m.isIE }, + }), + (t.VirtualRenderer = y); + }, + ), + define( + "ace/worker/worker_client", + [ + "require", + "exports", + "module", + "ace/lib/oop", + "ace/lib/net", + "ace/lib/event_emitter", + "ace/config", + ], + function (e, t, n) { + "use strict"; + function u(e) { + var t = "importScripts('" + i.qualifyURL(e) + "');"; + try { + return new Blob([t], { type: "application/javascript" }); + } catch (n) { + var r = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder, + s = new r(); + return s.append(t), s.getBlob("application/javascript"); + } + } + function a(e) { + if (typeof Worker == "undefined") + return { postMessage: function () {}, terminate: function () {} }; + var t = u(e), + n = window.URL || window.webkitURL, + r = n.createObjectURL(t); + return new Worker(r); + } + var r = e("../lib/oop"), + i = e("../lib/net"), + s = e("../lib/event_emitter").EventEmitter, + o = e("../config"), + f = function (t, n, r, i, s) { + (this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this)), + (this.changeListener = this.changeListener.bind(this)), + (this.onMessage = this.onMessage.bind(this)), + e.nameToUrl && !e.toUrl && (e.toUrl = e.nameToUrl); + if (o.get("packaged") || !e.toUrl) i = i || o.moduleUrl(n, "worker"); + else { + var u = this.$normalizePath; + i = i || u(e.toUrl("ace/worker/worker.js", null, "_")); + var f = {}; + t.forEach(function (t) { + f[t] = u(e.toUrl(t, null, "_").replace(/(\.js)?(\?.*)?$/, "")); + }); + } + (this.$worker = a(i)), + s && this.send("importScripts", s), + this.$worker.postMessage({ init: !0, tlns: f, module: n, classname: r }), + (this.callbackId = 1), + (this.callbacks = {}), + (this.$worker.onmessage = this.onMessage); + }; + (function () { + r.implement(this, s), + (this.onMessage = function (e) { + var t = e.data; + switch (t.type) { + case "event": + this._signal(t.name, { data: t.data }); + break; + case "call": + var n = this.callbacks[t.id]; + n && (n(t.data), delete this.callbacks[t.id]); + break; + case "error": + this.reportError(t.data); + break; + case "log": + window.console && console.log && console.log.apply(console, t.data); + } + }), + (this.reportError = function (e) { + window.console && console.error && console.error(e); + }), + (this.$normalizePath = function (e) { + return i.qualifyURL(e); + }), + (this.terminate = function () { + this._signal("terminate", {}), + (this.deltaQueue = null), + this.$worker.terminate(), + (this.$worker = null), + this.$doc && this.$doc.off("change", this.changeListener), + (this.$doc = null); + }), + (this.send = function (e, t) { + this.$worker.postMessage({ command: e, args: t }); + }), + (this.call = function (e, t, n) { + if (n) { + var r = this.callbackId++; + (this.callbacks[r] = n), t.push(r); + } + this.send(e, t); + }), + (this.emit = function (e, t) { + try { + t.data && + t.data.err && + (t.data.err = { + message: t.data.err.message, + stack: t.data.err.stack, + code: t.data.err.code, + }), + this.$worker.postMessage({ event: e, data: { data: t.data } }); + } catch (n) { + console.error(n.stack); + } + }), + (this.attachToDocument = function (e) { + this.$doc && this.terminate(), + (this.$doc = e), + this.call("setValue", [e.getValue()]), + e.on("change", this.changeListener); + }), + (this.changeListener = function (e) { + this.deltaQueue || + ((this.deltaQueue = []), setTimeout(this.$sendDeltaQueue, 0)), + e.action == "insert" + ? this.deltaQueue.push(e.start, e.lines) + : this.deltaQueue.push(e.start, e.end); + }), + (this.$sendDeltaQueue = function () { + var e = this.deltaQueue; + if (!e) return; + (this.deltaQueue = null), + e.length > 50 && e.length > this.$doc.getLength() >> 1 + ? this.call("setValue", [this.$doc.getValue()]) + : this.emit("change", { data: e }); + }); + }).call(f.prototype); + var l = function (e, t, n) { + (this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this)), + (this.changeListener = this.changeListener.bind(this)), + (this.callbackId = 1), + (this.callbacks = {}), + (this.messageBuffer = []); + var r = null, + i = !1, + u = Object.create(s), + a = this; + (this.$worker = {}), + (this.$worker.terminate = function () {}), + (this.$worker.postMessage = function (e) { + a.messageBuffer.push(e), r && (i ? setTimeout(f) : f()); + }), + (this.setEmitSync = function (e) { + i = e; + }); + var f = function () { + var e = a.messageBuffer.shift(); + e.command + ? r[e.command].apply(r, e.args) + : e.event && u._signal(e.event, e.data); + }; + (u.postMessage = function (e) { + a.onMessage({ data: e }); + }), + (u.callback = function (e, t) { + this.postMessage({ type: "call", id: t, data: e }); + }), + (u.emit = function (e, t) { + this.postMessage({ type: "event", name: e, data: t }); + }), + o.loadModule(["worker", t], function (e) { + r = new e[n](u); + while (a.messageBuffer.length) f(); + }); + }; + (l.prototype = f.prototype), + (t.UIWorkerClient = l), + (t.WorkerClient = f), + (t.createWorker = a); + }, + ), + define( + "ace/placeholder", + ["require", "exports", "module", "ace/range", "ace/lib/event_emitter", "ace/lib/oop"], + function (e, t, n) { + "use strict"; + var r = e("./range").Range, + i = e("./lib/event_emitter").EventEmitter, + s = e("./lib/oop"), + o = function (e, t, n, r, i, s) { + var o = this; + (this.length = t), + (this.session = e), + (this.doc = e.getDocument()), + (this.mainClass = i), + (this.othersClass = s), + (this.$onUpdate = this.onUpdate.bind(this)), + this.doc.on("change", this.$onUpdate), + (this.$others = r), + (this.$onCursorChange = function () { + setTimeout(function () { + o.onCursorChange(); + }); + }), + (this.$pos = n); + var u = e.getUndoManager().$undoStack || + e.getUndoManager().$undostack || { length: -1 }; + (this.$undoStackDepth = u.length), + this.setup(), + e.selection.on("changeCursor", this.$onCursorChange); + }; + (function () { + s.implement(this, i), + (this.setup = function () { + var e = this, + t = this.doc, + n = this.session; + (this.selectionBefore = n.selection.toJSON()), + n.selection.inMultiSelectMode && n.selection.toSingleRange(), + (this.pos = t.createAnchor(this.$pos.row, this.$pos.column)); + var i = this.pos; + (i.$insertRight = !0), + i.detach(), + (i.markerId = n.addMarker( + new r(i.row, i.column, i.row, i.column + this.length), + this.mainClass, + null, + !1, + )), + (this.others = []), + this.$others.forEach(function (n) { + var r = t.createAnchor(n.row, n.column); + (r.$insertRight = !0), r.detach(), e.others.push(r); + }), + n.setUndoSelect(!1); + }), + (this.showOtherMarkers = function () { + if (this.othersActive) return; + var e = this.session, + t = this; + (this.othersActive = !0), + this.others.forEach(function (n) { + n.markerId = e.addMarker( + new r(n.row, n.column, n.row, n.column + t.length), + t.othersClass, + null, + !1, + ); + }); + }), + (this.hideOtherMarkers = function () { + if (!this.othersActive) return; + this.othersActive = !1; + for (var e = 0; e < this.others.length; e++) + this.session.removeMarker(this.others[e].markerId); + }), + (this.onUpdate = function (e) { + if (this.$updating) return this.updateAnchors(e); + var t = e; + if (t.start.row !== t.end.row) return; + if (t.start.row !== this.pos.row) return; + this.$updating = !0; + var n = + e.action === "insert" + ? t.end.column - t.start.column + : t.start.column - t.end.column, + i = + t.start.column >= this.pos.column && + t.start.column <= this.pos.column + this.length + 1, + s = t.start.column - this.pos.column; + this.updateAnchors(e), i && (this.length += n); + if (i && !this.session.$fromUndo) + if (e.action === "insert") + for (var o = this.others.length - 1; o >= 0; o--) { + var u = this.others[o], + a = { row: u.row, column: u.column + s }; + this.doc.insertMergedLines(a, e.lines); + } + else if (e.action === "remove") + for (var o = this.others.length - 1; o >= 0; o--) { + var u = this.others[o], + a = { row: u.row, column: u.column + s }; + this.doc.remove(new r(a.row, a.column, a.row, a.column - n)); + } + (this.$updating = !1), this.updateMarkers(); + }), + (this.updateAnchors = function (e) { + this.pos.onChange(e); + for (var t = this.others.length; t--; ) this.others[t].onChange(e); + this.updateMarkers(); + }), + (this.updateMarkers = function () { + if (this.$updating) return; + var e = this, + t = this.session, + n = function (n, i) { + t.removeMarker(n.markerId), + (n.markerId = t.addMarker( + new r(n.row, n.column, n.row, n.column + e.length), + i, + null, + !1, + )); + }; + n(this.pos, this.mainClass); + for (var i = this.others.length; i--; ) n(this.others[i], this.othersClass); + }), + (this.onCursorChange = function (e) { + if (this.$updating || !this.session) return; + var t = this.session.selection.getCursor(); + t.row === this.pos.row && + t.column >= this.pos.column && + t.column <= this.pos.column + this.length + ? (this.showOtherMarkers(), this._emit("cursorEnter", e)) + : (this.hideOtherMarkers(), this._emit("cursorLeave", e)); + }), + (this.detach = function () { + this.session.removeMarker(this.pos && this.pos.markerId), + this.hideOtherMarkers(), + this.doc.removeEventListener("change", this.$onUpdate), + this.session.selection.removeEventListener( + "changeCursor", + this.$onCursorChange, + ), + this.session.setUndoSelect(!0), + (this.session = null); + }), + (this.cancel = function () { + if (this.$undoStackDepth === -1) return; + var e = this.session.getUndoManager(), + t = (e.$undoStack || e.$undostack).length - this.$undoStackDepth; + for (var n = 0; n < t; n++) e.undo(this.session, !0); + this.selectionBefore && + this.session.selection.fromJSON(this.selectionBefore); + }); + }).call(o.prototype), + (t.PlaceHolder = o); + }, + ), + define( + "ace/mouse/multi_select_handler", + ["require", "exports", "module", "ace/lib/event", "ace/lib/useragent"], + function (e, t, n) { + function s(e, t) { + return e.row == t.row && e.column == t.column; + } + function o(e) { + var t = e.domEvent, + n = t.altKey, + o = t.shiftKey, + u = t.ctrlKey, + a = e.getAccelKey(), + f = e.getButton(); + u && i.isMac && (f = t.button); + if (e.editor.inMultiSelectMode && f == 2) { + e.editor.textInput.onContextMenu(e.domEvent); + return; + } + if (!u && !n && !a) { + f === 0 && e.editor.inMultiSelectMode && e.editor.exitMultiSelectMode(); + return; + } + if (f !== 0) return; + var l = e.editor, + c = l.selection, + h = l.inMultiSelectMode, + p = e.getDocumentPosition(), + d = c.getCursor(), + v = e.inSelection() || (c.isEmpty() && s(p, d)), + m = e.x, + g = e.y, + y = function (e) { + (m = e.clientX), (g = e.clientY); + }, + b = l.session, + w = l.renderer.pixelToScreenCoordinates(m, g), + E = w, + S; + if (l.$mouseHandler.$enableJumpToDef) + (u && n) || (a && n) + ? (S = o ? "block" : "add") + : n && l.$blockSelectEnabled && (S = "block"); + else if (a && !n) { + S = "add"; + if (!h && o) return; + } else n && l.$blockSelectEnabled && (S = "block"); + S && i.isMac && t.ctrlKey && l.$mouseHandler.cancelContextMenu(); + if (S == "add") { + if (!h && v) return; + if (!h) { + var x = c.toOrientedRange(); + l.addSelectionMarker(x); + } + var T = c.rangeList.rangeAtPoint(p); + (l.inVirtualSelectionMode = !0), + o && ((T = null), (x = c.ranges[0] || x), l.removeSelectionMarker(x)), + l.once("mouseup", function () { + var e = c.toOrientedRange(); + T && e.isEmpty() && s(T.cursor, e.cursor) + ? c.substractPoint(e.cursor) + : (o + ? c.substractPoint(x.cursor) + : x && (l.removeSelectionMarker(x), c.addRange(x)), + c.addRange(e)), + (l.inVirtualSelectionMode = !1); + }); + } else if (S == "block") { + e.stop(), (l.inVirtualSelectionMode = !0); + var N, + C = [], + k = function () { + var e = l.renderer.pixelToScreenCoordinates(m, g), + t = b.screenToDocumentPosition(e.row, e.column, e.offsetX); + if (s(E, e) && s(t, c.lead)) return; + (E = e), + l.selection.moveToPosition(t), + l.renderer.scrollCursorIntoView(), + l.removeSelectionMarkers(C), + (C = c.rectangularRangeBlock(E, w)), + l.$mouseHandler.$clickSelection && + C.length == 1 && + C[0].isEmpty() && + (C[0] = l.$mouseHandler.$clickSelection.clone()), + C.forEach(l.addSelectionMarker, l), + l.updateSelectionMarkers(); + }; + h && !a + ? c.toSingleRange() + : !h && a && ((N = c.toOrientedRange()), l.addSelectionMarker(N)), + o ? (w = b.documentToScreenPosition(c.lead)) : c.moveToPosition(p), + (E = { row: -1, column: -1 }); + var L = function (e) { + k(), + clearInterval(O), + l.removeSelectionMarkers(C), + C.length || (C = [c.toOrientedRange()]), + N && (l.removeSelectionMarker(N), c.toSingleRange(N)); + for (var t = 0; t < C.length; t++) c.addRange(C[t]); + (l.inVirtualSelectionMode = !1), + (l.$mouseHandler.$clickSelection = null); + }, + A = k; + r.capture(l.container, y, L); + var O = setInterval(function () { + A(); + }, 20); + return e.preventDefault(); + } + } + var r = e("../lib/event"), + i = e("../lib/useragent"); + t.onMouseDown = o; + }, + ), + define( + "ace/commands/multi_select_commands", + ["require", "exports", "module", "ace/keyboard/hash_handler"], + function (e, t, n) { + (t.defaultCommands = [ + { + name: "addCursorAbove", + exec: function (e) { + e.selectMoreLines(-1); + }, + bindKey: { win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up" }, + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "addCursorBelow", + exec: function (e) { + e.selectMoreLines(1); + }, + bindKey: { win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down" }, + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "addCursorAboveSkipCurrent", + exec: function (e) { + e.selectMoreLines(-1, !0); + }, + bindKey: { win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up" }, + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "addCursorBelowSkipCurrent", + exec: function (e) { + e.selectMoreLines(1, !0); + }, + bindKey: { win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down" }, + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "selectMoreBefore", + exec: function (e) { + e.selectMore(-1); + }, + bindKey: { win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left" }, + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "selectMoreAfter", + exec: function (e) { + e.selectMore(1); + }, + bindKey: { win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right" }, + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "selectNextBefore", + exec: function (e) { + e.selectMore(-1, !0); + }, + bindKey: { win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left" }, + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "selectNextAfter", + exec: function (e) { + e.selectMore(1, !0); + }, + bindKey: { win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right" }, + scrollIntoView: "cursor", + readOnly: !0, + }, + { + name: "splitIntoLines", + exec: function (e) { + e.multiSelect.splitIntoLines(); + }, + bindKey: { win: "Ctrl-Alt-L", mac: "Ctrl-Alt-L" }, + readOnly: !0, + }, + { + name: "alignCursors", + exec: function (e) { + e.alignCursors(); + }, + bindKey: { win: "Ctrl-Alt-A", mac: "Ctrl-Alt-A" }, + scrollIntoView: "cursor", + }, + { + name: "findAll", + exec: function (e) { + e.findAll(); + }, + bindKey: { win: "Ctrl-Alt-K", mac: "Ctrl-Alt-G" }, + scrollIntoView: "cursor", + readOnly: !0, + }, + ]), + (t.multiSelectCommands = [ + { + name: "singleSelection", + bindKey: "esc", + exec: function (e) { + e.exitMultiSelectMode(); + }, + scrollIntoView: "cursor", + readOnly: !0, + isAvailable: function (e) { + return e && e.inMultiSelectMode; + }, + }, + ]); + var r = e("../keyboard/hash_handler").HashHandler; + t.keyboardHandler = new r(t.multiSelectCommands); + }, + ), + define( + "ace/multi_select", + [ + "require", + "exports", + "module", + "ace/range_list", + "ace/range", + "ace/selection", + "ace/mouse/multi_select_handler", + "ace/lib/event", + "ace/lib/lang", + "ace/commands/multi_select_commands", + "ace/search", + "ace/edit_session", + "ace/editor", + "ace/config", + ], + function (e, t, n) { + function h(e, t, n) { + return ( + (c.$options.wrap = !0), + (c.$options.needle = t), + (c.$options.backwards = n == -1), + c.find(e) + ); + } + function v(e, t) { + return e.row == t.row && e.column == t.column; + } + function m(e) { + if (e.$multiselectOnSessionChange) return; + (e.$onAddRange = e.$onAddRange.bind(e)), + (e.$onRemoveRange = e.$onRemoveRange.bind(e)), + (e.$onMultiSelect = e.$onMultiSelect.bind(e)), + (e.$onSingleSelect = e.$onSingleSelect.bind(e)), + (e.$multiselectOnSessionChange = t.onSessionChange.bind(e)), + (e.$checkMultiselectChange = e.$checkMultiselectChange.bind(e)), + e.$multiselectOnSessionChange(e), + e.on("changeSession", e.$multiselectOnSessionChange), + e.on("mousedown", o), + e.commands.addCommands(f.defaultCommands), + g(e); + } + function g(e) { + function r(t) { + n && (e.renderer.setMouseCursor(""), (n = !1)); + } + var t = e.textInput.getElement(), + n = !1; + u.addListener(t, "keydown", function (t) { + var i = t.keyCode == 18 && !(t.ctrlKey || t.shiftKey || t.metaKey); + e.$blockSelectEnabled && i + ? n || (e.renderer.setMouseCursor("crosshair"), (n = !0)) + : n && r(); + }), + u.addListener(t, "keyup", r), + u.addListener(t, "blur", r); + } + var r = e("./range_list").RangeList, + i = e("./range").Range, + s = e("./selection").Selection, + o = e("./mouse/multi_select_handler").onMouseDown, + u = e("./lib/event"), + a = e("./lib/lang"), + f = e("./commands/multi_select_commands"); + t.commands = f.defaultCommands.concat(f.multiSelectCommands); + var l = e("./search").Search, + c = new l(), + p = e("./edit_session").EditSession; + (function () { + this.getSelectionMarkers = function () { + return this.$selectionMarkers; + }; + }).call(p.prototype), + function () { + (this.ranges = null), + (this.rangeList = null), + (this.addRange = function (e, t) { + if (!e) return; + if (!this.inMultiSelectMode && this.rangeCount === 0) { + var n = this.toOrientedRange(); + this.rangeList.add(n), this.rangeList.add(e); + if (this.rangeList.ranges.length != 2) + return ( + this.rangeList.removeAll(), t || this.fromOrientedRange(e) + ); + this.rangeList.removeAll(), + this.rangeList.add(n), + this.$onAddRange(n); + } + e.cursor || (e.cursor = e.end); + var r = this.rangeList.add(e); + return ( + this.$onAddRange(e), + r.length && this.$onRemoveRange(r), + this.rangeCount > 1 && + !this.inMultiSelectMode && + (this._signal("multiSelect"), + (this.inMultiSelectMode = !0), + (this.session.$undoSelect = !1), + this.rangeList.attach(this.session)), + t || this.fromOrientedRange(e) + ); + }), + (this.toSingleRange = function (e) { + e = e || this.ranges[0]; + var t = this.rangeList.removeAll(); + t.length && this.$onRemoveRange(t), e && this.fromOrientedRange(e); + }), + (this.substractPoint = function (e) { + var t = this.rangeList.substractPoint(e); + if (t) return this.$onRemoveRange(t), t[0]; + }), + (this.mergeOverlappingRanges = function () { + var e = this.rangeList.merge(); + e.length && this.$onRemoveRange(e); + }), + (this.$onAddRange = function (e) { + (this.rangeCount = this.rangeList.ranges.length), + this.ranges.unshift(e), + this._signal("addRange", { range: e }); + }), + (this.$onRemoveRange = function (e) { + this.rangeCount = this.rangeList.ranges.length; + if (this.rangeCount == 1 && this.inMultiSelectMode) { + var t = this.rangeList.ranges.pop(); + e.push(t), (this.rangeCount = 0); + } + for (var n = e.length; n--; ) { + var r = this.ranges.indexOf(e[n]); + this.ranges.splice(r, 1); + } + this._signal("removeRange", { ranges: e }), + this.rangeCount === 0 && + this.inMultiSelectMode && + ((this.inMultiSelectMode = !1), + this._signal("singleSelect"), + (this.session.$undoSelect = !0), + this.rangeList.detach(this.session)), + (t = t || this.ranges[0]), + t && !t.isEqual(this.getRange()) && this.fromOrientedRange(t); + }), + (this.$initRangeList = function () { + if (this.rangeList) return; + (this.rangeList = new r()), (this.ranges = []), (this.rangeCount = 0); + }), + (this.getAllRanges = function () { + return this.rangeCount + ? this.rangeList.ranges.concat() + : [this.getRange()]; + }), + (this.splitIntoLines = function () { + if (this.rangeCount > 1) { + var e = this.rangeList.ranges, + t = e[e.length - 1], + n = i.fromPoints(e[0].start, t.end); + this.toSingleRange(), + this.setSelectionRange(n, t.cursor == t.start); + } else { + var n = this.getRange(), + r = this.isBackwards(), + s = n.start.row, + o = n.end.row; + if (s == o) { + if (r) + var u = n.end, + a = n.start; + else + var u = n.start, + a = n.end; + this.addRange(i.fromPoints(a, a)), + this.addRange(i.fromPoints(u, u)); + return; + } + var f = [], + l = this.getLineRange(s, !0); + (l.start.column = n.start.column), f.push(l); + for (var c = s + 1; c < o; c++) f.push(this.getLineRange(c, !0)); + (l = this.getLineRange(o, !0)), + (l.end.column = n.end.column), + f.push(l), + f.forEach(this.addRange, this); + } + }), + (this.toggleBlockSelection = function () { + if (this.rangeCount > 1) { + var e = this.rangeList.ranges, + t = e[e.length - 1], + n = i.fromPoints(e[0].start, t.end); + this.toSingleRange(), + this.setSelectionRange(n, t.cursor == t.start); + } else { + var r = this.session.documentToScreenPosition(this.cursor), + s = this.session.documentToScreenPosition(this.anchor), + o = this.rectangularRangeBlock(r, s); + o.forEach(this.addRange, this); + } + }), + (this.rectangularRangeBlock = function (e, t, n) { + var r = [], + s = e.column < t.column; + if (s) + var o = e.column, + u = t.column, + a = e.offsetX, + f = t.offsetX; + else + var o = t.column, + u = e.column, + a = t.offsetX, + f = e.offsetX; + var l = e.row < t.row; + if (l) + var c = e.row, + h = t.row; + else + var c = t.row, + h = e.row; + o < 0 && (o = 0), c < 0 && (c = 0), c == h && (n = !0); + var p; + for (var d = c; d <= h; d++) { + var m = i.fromPoints( + this.session.screenToDocumentPosition(d, o, a), + this.session.screenToDocumentPosition(d, u, f), + ); + if (m.isEmpty()) { + if (p && v(m.end, p)) break; + p = m.end; + } + (m.cursor = s ? m.start : m.end), r.push(m); + } + l && r.reverse(); + if (!n) { + var g = r.length - 1; + while (r[g].isEmpty() && g > 0) g--; + if (g > 0) { + var y = 0; + while (r[y].isEmpty()) y++; + } + for (var b = g; b >= y; b--) r[b].isEmpty() && r.splice(b, 1); + } + return r; + }); + }.call(s.prototype); + var d = e("./editor").Editor; + (function () { + (this.updateSelectionMarkers = function () { + this.renderer.updateCursor(), this.renderer.updateBackMarkers(); + }), + (this.addSelectionMarker = function (e) { + e.cursor || (e.cursor = e.end); + var t = this.getSelectionStyle(); + return ( + (e.marker = this.session.addMarker(e, "ace_selection", t)), + this.session.$selectionMarkers.push(e), + (this.session.selectionMarkerCount = + this.session.$selectionMarkers.length), + e + ); + }), + (this.removeSelectionMarker = function (e) { + if (!e.marker) return; + this.session.removeMarker(e.marker); + var t = this.session.$selectionMarkers.indexOf(e); + t != -1 && this.session.$selectionMarkers.splice(t, 1), + (this.session.selectionMarkerCount = + this.session.$selectionMarkers.length); + }), + (this.removeSelectionMarkers = function (e) { + var t = this.session.$selectionMarkers; + for (var n = e.length; n--; ) { + var r = e[n]; + if (!r.marker) continue; + this.session.removeMarker(r.marker); + var i = t.indexOf(r); + i != -1 && t.splice(i, 1); + } + this.session.selectionMarkerCount = t.length; + }), + (this.$onAddRange = function (e) { + this.addSelectionMarker(e.range), + this.renderer.updateCursor(), + this.renderer.updateBackMarkers(); + }), + (this.$onRemoveRange = function (e) { + this.removeSelectionMarkers(e.ranges), + this.renderer.updateCursor(), + this.renderer.updateBackMarkers(); + }), + (this.$onMultiSelect = function (e) { + if (this.inMultiSelectMode) return; + (this.inMultiSelectMode = !0), + this.setStyle("ace_multiselect"), + this.keyBinding.addKeyboardHandler(f.keyboardHandler), + this.commands.setDefaultHandler("exec", this.$onMultiSelectExec), + this.renderer.updateCursor(), + this.renderer.updateBackMarkers(); + }), + (this.$onSingleSelect = function (e) { + if (this.session.multiSelect.inVirtualMode) return; + (this.inMultiSelectMode = !1), + this.unsetStyle("ace_multiselect"), + this.keyBinding.removeKeyboardHandler(f.keyboardHandler), + this.commands.removeDefaultHandler("exec", this.$onMultiSelectExec), + this.renderer.updateCursor(), + this.renderer.updateBackMarkers(), + this._emit("changeSelection"); + }), + (this.$onMultiSelectExec = function (e) { + var t = e.command, + n = e.editor; + if (!n.multiSelect) return; + if (!t.multiSelectAction) { + var r = t.exec(n, e.args || {}); + n.multiSelect.addRange(n.multiSelect.toOrientedRange()), + n.multiSelect.mergeOverlappingRanges(); + } else + t.multiSelectAction == "forEach" + ? (r = n.forEachSelection(t, e.args)) + : t.multiSelectAction == "forEachLine" + ? (r = n.forEachSelection(t, e.args, !0)) + : t.multiSelectAction == "single" + ? (n.exitMultiSelectMode(), (r = t.exec(n, e.args || {}))) + : (r = t.multiSelectAction(n, e.args || {})); + return r; + }), + (this.forEachSelection = function (e, t, n) { + if (this.inVirtualSelectionMode) return; + var r = n && n.keepOrder, + i = n == 1 || (n && n.$byLines), + o = this.session, + u = this.selection, + a = u.rangeList, + f = (r ? u : a).ranges, + l; + if (!f.length) return e.exec ? e.exec(this, t || {}) : e(this, t || {}); + var c = u._eventRegistry; + u._eventRegistry = {}; + var h = new s(o); + this.inVirtualSelectionMode = !0; + for (var p = f.length; p--; ) { + if (i) while (p > 0 && f[p].start.row == f[p - 1].end.row) p--; + h.fromOrientedRange(f[p]), + (h.index = p), + (this.selection = o.selection = h); + var d = e.exec ? e.exec(this, t || {}) : e(this, t || {}); + !l && d !== undefined && (l = d), h.toOrientedRange(f[p]); + } + h.detach(), + (this.selection = o.selection = u), + (this.inVirtualSelectionMode = !1), + (u._eventRegistry = c), + u.mergeOverlappingRanges(), + u.ranges[0] && u.fromOrientedRange(u.ranges[0]); + var v = this.renderer.$scrollAnimation; + return ( + this.onCursorChange(), + this.onSelectionChange(), + v && v.from == v.to && this.renderer.animateScrolling(v.from), + l + ); + }), + (this.exitMultiSelectMode = function () { + if (!this.inMultiSelectMode || this.inVirtualSelectionMode) return; + this.multiSelect.toSingleRange(); + }), + (this.getSelectedText = function () { + var e = ""; + if (this.inMultiSelectMode && !this.inVirtualSelectionMode) { + var t = this.multiSelect.rangeList.ranges, + n = []; + for (var r = 0; r < t.length; r++) + n.push(this.session.getTextRange(t[r])); + var i = this.session.getDocument().getNewLineCharacter(); + (e = n.join(i)), e.length == (n.length - 1) * i.length && (e = ""); + } else + this.selection.isEmpty() || + (e = this.session.getTextRange(this.getSelectionRange())); + return e; + }), + (this.$checkMultiselectChange = function (e, t) { + if (this.inMultiSelectMode && !this.inVirtualSelectionMode) { + var n = this.multiSelect.ranges[0]; + if (this.multiSelect.isEmpty() && t == this.multiSelect.anchor) return; + var r = + t == this.multiSelect.anchor + ? n.cursor == n.start + ? n.end + : n.start + : n.cursor; + r.row != t.row || + this.session.$clipPositionToDocument(r.row, r.column).column != t.column + ? this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange()) + : this.multiSelect.mergeOverlappingRanges(); + } + }), + (this.findAll = function (e, t, n) { + (t = t || {}), (t.needle = e || t.needle); + if (t.needle == undefined) { + var r = this.selection.isEmpty() + ? this.selection.getWordRange() + : this.selection.getRange(); + t.needle = this.session.getTextRange(r); + } + this.$search.set(t); + var i = this.$search.findAll(this.session); + if (!i.length) return 0; + var s = this.multiSelect; + n || s.toSingleRange(i[0]); + for (var o = i.length; o--; ) s.addRange(i[o], !0); + return ( + r && s.rangeList.rangeAtPoint(r.start) && s.addRange(r, !0), i.length + ); + }), + (this.selectMoreLines = function (e, t) { + var n = this.selection.toOrientedRange(), + r = n.cursor == n.end, + s = this.session.documentToScreenPosition(n.cursor); + this.selection.$desiredColumn && (s.column = this.selection.$desiredColumn); + var o = this.session.screenToDocumentPosition(s.row + e, s.column); + if (!n.isEmpty()) + var u = this.session.documentToScreenPosition(r ? n.end : n.start), + a = this.session.screenToDocumentPosition(u.row + e, u.column); + else var a = o; + if (r) { + var f = i.fromPoints(o, a); + f.cursor = f.start; + } else { + var f = i.fromPoints(a, o); + f.cursor = f.end; + } + f.desiredColumn = s.column; + if (!this.selection.inMultiSelectMode) this.selection.addRange(n); + else if (t) var l = n.cursor; + this.selection.addRange(f), l && this.selection.substractPoint(l); + }), + (this.transposeSelections = function (e) { + var t = this.session, + n = t.multiSelect, + r = n.ranges; + for (var i = r.length; i--; ) { + var s = r[i]; + if (s.isEmpty()) { + var o = t.getWordRange(s.start.row, s.start.column); + (s.start.row = o.start.row), + (s.start.column = o.start.column), + (s.end.row = o.end.row), + (s.end.column = o.end.column); + } + } + n.mergeOverlappingRanges(); + var u = []; + for (var i = r.length; i--; ) { + var s = r[i]; + u.unshift(t.getTextRange(s)); + } + e < 0 ? u.unshift(u.pop()) : u.push(u.shift()); + for (var i = r.length; i--; ) { + var s = r[i], + o = s.clone(); + t.replace(s, u[i]), + (s.start.row = o.start.row), + (s.start.column = o.start.column); + } + n.fromOrientedRange(n.ranges[0]); + }), + (this.selectMore = function (e, t, n) { + var r = this.session, + i = r.multiSelect, + s = i.toOrientedRange(); + if (s.isEmpty()) { + (s = r.getWordRange(s.start.row, s.start.column)), + (s.cursor = e == -1 ? s.start : s.end), + this.multiSelect.addRange(s); + if (n) return; + } + var o = r.getTextRange(s), + u = h(r, o, e); + u && + ((u.cursor = e == -1 ? u.start : u.end), + this.session.unfold(u), + this.multiSelect.addRange(u), + this.renderer.scrollCursorIntoView(null, 0.5)), + t && this.multiSelect.substractPoint(s.cursor); + }), + (this.alignCursors = function () { + var e = this.session, + t = e.multiSelect, + n = t.ranges, + r = -1, + s = n.filter(function (e) { + if (e.cursor.row == r) return !0; + r = e.cursor.row; + }); + if (!n.length || s.length == n.length - 1) { + var o = this.selection.getRange(), + u = o.start.row, + f = o.end.row, + l = u == f; + if (l) { + var c = this.session.getLength(), + h; + do h = this.session.getLine(f); + while (/[=:]/.test(h) && ++f < c); + do h = this.session.getLine(u); + while (/[=:]/.test(h) && --u > 0); + u < 0 && (u = 0), f >= c && (f = c - 1); + } + var p = this.session.removeFullLines(u, f); + (p = this.$reAlignText(p, l)), + this.session.insert({ row: u, column: 0 }, p.join("\n") + "\n"), + l || + ((o.start.column = 0), (o.end.column = p[p.length - 1].length)), + this.selection.setRange(o); + } else { + s.forEach(function (e) { + t.substractPoint(e.cursor); + }); + var d = 0, + v = Infinity, + m = n.map(function (t) { + var n = t.cursor, + r = e.getLine(n.row), + i = r.substr(n.column).search(/\S/g); + return ( + i == -1 && (i = 0), + n.column > d && (d = n.column), + i < v && (v = i), + i + ); + }); + n.forEach(function (t, n) { + var r = t.cursor, + s = d - r.column, + o = m[n] - v; + s > o + ? e.insert(r, a.stringRepeat(" ", s - o)) + : e.remove(new i(r.row, r.column, r.row, r.column - s + o)), + (t.start.column = t.end.column = d), + (t.start.row = t.end.row = r.row), + (t.cursor = t.end); + }), + t.fromOrientedRange(n[0]), + this.renderer.updateCursor(), + this.renderer.updateBackMarkers(); + } + }), + (this.$reAlignText = function (e, t) { + function u(e) { + return a.stringRepeat(" ", e); + } + function f(e) { + return e[2] + ? u(i) + + e[2] + + u(s - e[2].length + o) + + e[4].replace(/^([=:])\s+/, "$1 ") + : e[0]; + } + function l(e) { + return e[2] + ? u(i + s - e[2].length) + + e[2] + + u(o) + + e[4].replace(/^([=:])\s+/, "$1 ") + : e[0]; + } + function c(e) { + return e[2] + ? u(i) + e[2] + u(o) + e[4].replace(/^([=:])\s+/, "$1 ") + : e[0]; + } + var n = !0, + r = !0, + i, + s, + o; + return e + .map(function (e) { + var t = e.match(/(\s*)(.*?)(\s*)([=:].*)/); + return t + ? i == null + ? ((i = t[1].length), + (s = t[2].length), + (o = t[3].length), + t) + : (i + s + o != t[1].length + t[2].length + t[3].length && + (r = !1), + i != t[1].length && (n = !1), + i > t[1].length && (i = t[1].length), + s < t[2].length && (s = t[2].length), + o > t[3].length && (o = t[3].length), + t) + : [e]; + }) + .map(t ? f : n ? (r ? l : f) : c); + }); + }).call(d.prototype), + (t.onSessionChange = function (e) { + var t = e.session; + t && + !t.multiSelect && + ((t.$selectionMarkers = []), + t.selection.$initRangeList(), + (t.multiSelect = t.selection)), + (this.multiSelect = t && t.multiSelect); + var n = e.oldSession; + n && + (n.multiSelect.off("addRange", this.$onAddRange), + n.multiSelect.off("removeRange", this.$onRemoveRange), + n.multiSelect.off("multiSelect", this.$onMultiSelect), + n.multiSelect.off("singleSelect", this.$onSingleSelect), + n.multiSelect.lead.off("change", this.$checkMultiselectChange), + n.multiSelect.anchor.off("change", this.$checkMultiselectChange)), + t && + (t.multiSelect.on("addRange", this.$onAddRange), + t.multiSelect.on("removeRange", this.$onRemoveRange), + t.multiSelect.on("multiSelect", this.$onMultiSelect), + t.multiSelect.on("singleSelect", this.$onSingleSelect), + t.multiSelect.lead.on("change", this.$checkMultiselectChange), + t.multiSelect.anchor.on("change", this.$checkMultiselectChange)), + t && + this.inMultiSelectMode != t.selection.inMultiSelectMode && + (t.selection.inMultiSelectMode + ? this.$onMultiSelect() + : this.$onSingleSelect()); + }), + (t.MultiSelect = m), + e("./config").defineOptions(d.prototype, "editor", { + enableMultiselect: { + set: function (e) { + m(this), + e + ? (this.on("changeSession", this.$multiselectOnSessionChange), + this.on("mousedown", o)) + : (this.off("changeSession", this.$multiselectOnSessionChange), + this.off("mousedown", o)); + }, + value: !0, + }, + enableBlockSelect: { + set: function (e) { + this.$blockSelectEnabled = e; + }, + value: !0, + }, + }); + }, + ), + define( + "ace/mode/folding/fold_mode", + ["require", "exports", "module", "ace/range"], + function (e, t, n) { + "use strict"; + var r = e("../../range").Range, + i = (t.FoldMode = function () {}); + (function () { + (this.foldingStartMarker = null), + (this.foldingStopMarker = null), + (this.getFoldWidget = function (e, t, n) { + var r = e.getLine(n); + return this.foldingStartMarker.test(r) + ? "start" + : t == "markbeginend" && + this.foldingStopMarker && + this.foldingStopMarker.test(r) + ? "end" + : ""; + }), + (this.getFoldWidgetRange = function (e, t, n) { + return null; + }), + (this.indentationBlock = function (e, t, n) { + var i = /\S/, + s = e.getLine(t), + o = s.search(i); + if (o == -1) return; + var u = n || s.length, + a = e.getLength(), + f = t, + l = t; + while (++t < a) { + var c = e.getLine(t).search(i); + if (c == -1) continue; + if (c <= o) break; + l = t; + } + if (l > f) { + var h = e.getLine(l).length; + return new r(f, u, l, h); + } + }), + (this.openingBracketBlock = function (e, t, n, i, s) { + var o = { row: n, column: i + 1 }, + u = e.$findClosingBracket(t, o, s); + if (!u) return; + var a = e.foldWidgets[u.row]; + return ( + a == null && (a = e.getFoldWidget(u.row)), + a == "start" && + u.row > o.row && + (u.row--, (u.column = e.getLine(u.row).length)), + r.fromPoints(o, u) + ); + }), + (this.closingBracketBlock = function (e, t, n, i, s) { + var o = { row: n, column: i }, + u = e.$findOpeningBracket(t, o); + if (!u) return; + return u.column++, o.column--, r.fromPoints(u, o); + }); + }).call(i.prototype); + }, + ), + define( + "ace/theme/textmate", + ["require", "exports", "module", "ace/lib/dom"], + function (e, t, n) { + "use strict"; + (t.isDark = !1), + (t.cssClass = "ace-tm"), + (t.cssText = + '.ace-tm .ace_gutter {background: #f0f0f0;color: #333;}.ace-tm .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-tm .ace_fold {background-color: #6B72E6;}.ace-tm {background-color: #FFFFFF;color: black;}.ace-tm .ace_cursor {color: black;}.ace-tm .ace_invisible {color: rgb(191, 191, 191);}.ace-tm .ace_storage,.ace-tm .ace_keyword {color: blue;}.ace-tm .ace_constant {color: rgb(197, 6, 11);}.ace-tm .ace_constant.ace_buildin {color: rgb(88, 72, 246);}.ace-tm .ace_constant.ace_language {color: rgb(88, 92, 246);}.ace-tm .ace_constant.ace_library {color: rgb(6, 150, 14);}.ace-tm .ace_invalid {background-color: rgba(255, 0, 0, 0.1);color: red;}.ace-tm .ace_support.ace_function {color: rgb(60, 76, 114);}.ace-tm .ace_support.ace_constant {color: rgb(6, 150, 14);}.ace-tm .ace_support.ace_type,.ace-tm .ace_support.ace_class {color: rgb(109, 121, 222);}.ace-tm .ace_keyword.ace_operator {color: rgb(104, 118, 135);}.ace-tm .ace_string {color: rgb(3, 106, 7);}.ace-tm .ace_comment {color: rgb(76, 136, 107);}.ace-tm .ace_comment.ace_doc {color: rgb(0, 102, 255);}.ace-tm .ace_comment.ace_doc.ace_tag {color: rgb(128, 159, 191);}.ace-tm .ace_constant.ace_numeric {color: rgb(0, 0, 205);}.ace-tm .ace_variable {color: rgb(49, 132, 149);}.ace-tm .ace_xml-pe {color: rgb(104, 104, 91);}.ace-tm .ace_entity.ace_name.ace_function {color: #0000A2;}.ace-tm .ace_heading {color: rgb(12, 7, 255);}.ace-tm .ace_list {color:rgb(185, 6, 144);}.ace-tm .ace_meta.ace_tag {color:rgb(0, 22, 142);}.ace-tm .ace_string.ace_regex {color: rgb(255, 0, 0)}.ace-tm .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-tm.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px white;}.ace-tm .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-tm .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-tm .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-tm .ace_marker-layer .ace_active-line {background: rgba(0, 0, 0, 0.07);}.ace-tm .ace_gutter-active-line {background-color : #dcdcdc;}.ace-tm .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-tm .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;}'), + (t.$id = "ace/theme/textmate"); + var r = e("../lib/dom"); + r.importCssString(t.cssText, t.cssClass); + }, + ), + define( + "ace/line_widgets", + ["require", "exports", "module", "ace/lib/oop", "ace/lib/dom", "ace/range"], + function (e, t, n) { + "use strict"; + function o(e) { + (this.session = e), + (this.session.widgetManager = this), + (this.session.getRowLength = this.getRowLength), + (this.session.$getWidgetScreenLength = this.$getWidgetScreenLength), + (this.updateOnChange = this.updateOnChange.bind(this)), + (this.renderWidgets = this.renderWidgets.bind(this)), + (this.measureWidgets = this.measureWidgets.bind(this)), + (this.session._changedWidgets = []), + (this.$onChangeEditor = this.$onChangeEditor.bind(this)), + this.session.on("change", this.updateOnChange), + this.session.on("changeFold", this.updateOnFold), + this.session.on("changeEditor", this.$onChangeEditor); + } + var r = e("./lib/oop"), + i = e("./lib/dom"), + s = e("./range").Range; + (function () { + (this.getRowLength = function (e) { + var t; + return ( + this.lineWidgets + ? (t = (this.lineWidgets[e] && this.lineWidgets[e].rowCount) || 0) + : (t = 0), + !this.$useWrapMode || !this.$wrapData[e] + ? 1 + t + : this.$wrapData[e].length + 1 + t + ); + }), + (this.$getWidgetScreenLength = function () { + var e = 0; + return ( + this.lineWidgets.forEach(function (t) { + t && t.rowCount && !t.hidden && (e += t.rowCount); + }), + e + ); + }), + (this.$onChangeEditor = function (e) { + this.attach(e.editor); + }), + (this.attach = function (e) { + e && e.widgetManager && e.widgetManager != this && e.widgetManager.detach(); + if (this.editor == e) return; + this.detach(), + (this.editor = e), + e && + ((e.widgetManager = this), + e.renderer.on("beforeRender", this.measureWidgets), + e.renderer.on("afterRender", this.renderWidgets)); + }), + (this.detach = function (e) { + var t = this.editor; + if (!t) return; + (this.editor = null), + (t.widgetManager = null), + t.renderer.off("beforeRender", this.measureWidgets), + t.renderer.off("afterRender", this.renderWidgets); + var n = this.session.lineWidgets; + n && + n.forEach(function (e) { + e && + e.el && + e.el.parentNode && + ((e._inDocument = !1), e.el.parentNode.removeChild(e.el)); + }); + }), + (this.updateOnFold = function (e, t) { + var n = t.lineWidgets; + if (!n || !e.action) return; + var r = e.data, + i = r.start.row, + s = r.end.row, + o = e.action == "add"; + for (var u = i + 1; u < s; u++) n[u] && (n[u].hidden = o); + n[s] && + (o + ? n[i] + ? (n[s].hidden = o) + : (n[i] = n[s]) + : (n[i] == n[s] && (n[i] = undefined), (n[s].hidden = o))); + }), + (this.updateOnChange = function (e) { + var t = this.session.lineWidgets; + if (!t) return; + var n = e.start.row, + r = e.end.row - n; + if (r !== 0) + if (e.action == "remove") { + var i = t.splice(n + 1, r); + i.forEach(function (e) { + e && this.removeLineWidget(e); + }, this), + this.$updateRows(); + } else { + var s = new Array(r); + s.unshift(n, 0), t.splice.apply(t, s), this.$updateRows(); + } + }), + (this.$updateRows = function () { + var e = this.session.lineWidgets; + if (!e) return; + var t = !0; + e.forEach(function (e, n) { + if (e) { + (t = !1), (e.row = n); + while (e.$oldWidget) (e.$oldWidget.row = n), (e = e.$oldWidget); + } + }), + t && (this.session.lineWidgets = null); + }), + (this.addLineWidget = function (e) { + this.session.lineWidgets || + (this.session.lineWidgets = new Array(this.session.getLength())); + var t = this.session.lineWidgets[e.row]; + t && + ((e.$oldWidget = t), + t.el && + t.el.parentNode && + (t.el.parentNode.removeChild(t.el), (t._inDocument = !1))), + (this.session.lineWidgets[e.row] = e), + (e.session = this.session); + var n = this.editor.renderer; + e.html && + !e.el && + ((e.el = i.createElement("div")), (e.el.innerHTML = e.html)), + e.el && + (i.addCssClass(e.el, "ace_lineWidgetContainer"), + (e.el.style.position = "absolute"), + (e.el.style.zIndex = 5), + n.container.appendChild(e.el), + (e._inDocument = !0)), + e.coverGutter || (e.el.style.zIndex = 3), + e.pixelHeight == null && (e.pixelHeight = e.el.offsetHeight), + e.rowCount == null && + (e.rowCount = e.pixelHeight / n.layerConfig.lineHeight); + var r = this.session.getFoldAt(e.row, 0); + e.$fold = r; + if (r) { + var s = this.session.lineWidgets; + e.row == r.end.row && !s[r.start.row] + ? (s[r.start.row] = e) + : (e.hidden = !0); + } + return ( + this.session._emit("changeFold", { data: { start: { row: e.row } } }), + this.$updateRows(), + this.renderWidgets(null, n), + this.onWidgetChanged(e), + e + ); + }), + (this.removeLineWidget = function (e) { + (e._inDocument = !1), + (e.session = null), + e.el && e.el.parentNode && e.el.parentNode.removeChild(e.el); + if (e.editor && e.editor.destroy) + try { + e.editor.destroy(); + } catch (t) {} + if (this.session.lineWidgets) { + var n = this.session.lineWidgets[e.row]; + if (n == e) + (this.session.lineWidgets[e.row] = e.$oldWidget), + e.$oldWidget && this.onWidgetChanged(e.$oldWidget); + else + while (n) { + if (n.$oldWidget == e) { + n.$oldWidget = e.$oldWidget; + break; + } + n = n.$oldWidget; + } + } + this.session._emit("changeFold", { data: { start: { row: e.row } } }), + this.$updateRows(); + }), + (this.getWidgetsAtRow = function (e) { + var t = this.session.lineWidgets, + n = t && t[e], + r = []; + while (n) r.push(n), (n = n.$oldWidget); + return r; + }), + (this.onWidgetChanged = function (e) { + this.session._changedWidgets.push(e), + this.editor && this.editor.renderer.updateFull(); + }), + (this.measureWidgets = function (e, t) { + var n = this.session._changedWidgets, + r = t.layerConfig; + if (!n || !n.length) return; + var i = Infinity; + for (var s = 0; s < n.length; s++) { + var o = n[s]; + if (!o || !o.el) continue; + if (o.session != this.session) continue; + if (!o._inDocument) { + if (this.session.lineWidgets[o.row] != o) continue; + (o._inDocument = !0), t.container.appendChild(o.el); + } + (o.h = o.el.offsetHeight), + o.fixedWidth || + ((o.w = o.el.offsetWidth), + (o.screenWidth = Math.ceil(o.w / r.characterWidth))); + var u = o.h / r.lineHeight; + o.coverLine && + ((u -= this.session.getRowLineCount(o.row)), u < 0 && (u = 0)), + o.rowCount != u && ((o.rowCount = u), o.row < i && (i = o.row)); + } + i != Infinity && + (this.session._emit("changeFold", { data: { start: { row: i } } }), + (this.session.lineWidgetWidth = null)), + (this.session._changedWidgets = []); + }), + (this.renderWidgets = function (e, t) { + var n = t.layerConfig, + r = this.session.lineWidgets; + if (!r) return; + var i = Math.min(this.firstRow, n.firstRow), + s = Math.max(this.lastRow, n.lastRow, r.length); + while (i > 0 && !r[i]) i--; + (this.firstRow = n.firstRow), + (this.lastRow = n.lastRow), + (t.$cursorLayer.config = n); + for (var o = i; o <= s; o++) { + var u = r[o]; + if (!u || !u.el) continue; + if (u.hidden) { + u.el.style.top = -100 - (u.pixelHeight || 0) + "px"; + continue; + } + u._inDocument || ((u._inDocument = !0), t.container.appendChild(u.el)); + var a = t.$cursorLayer.getPixelPosition({ row: o, column: 0 }, !0).top; + u.coverLine || + (a += n.lineHeight * this.session.getRowLineCount(u.row)), + (u.el.style.top = a - n.offset + "px"); + var f = u.coverGutter ? 0 : t.gutterWidth; + u.fixedWidth || (f -= t.scrollLeft), + (u.el.style.left = f + "px"), + u.fullWidth && + u.screenWidth && + (u.el.style.minWidth = n.width + 2 * n.padding + "px"), + u.fixedWidth + ? (u.el.style.right = t.scrollBar.getWidth() + "px") + : (u.el.style.right = ""); + } + }); + }).call(o.prototype), + (t.LineWidgets = o); + }, + ), + define( + "ace/ext/error_marker", + ["require", "exports", "module", "ace/line_widgets", "ace/lib/dom", "ace/range"], + function (e, t, n) { + "use strict"; + function o(e, t, n) { + var r = 0, + i = e.length - 1; + while (r <= i) { + var s = (r + i) >> 1, + o = n(t, e[s]); + if (o > 0) r = s + 1; + else { + if (!(o < 0)) return s; + i = s - 1; + } + } + return -(r + 1); + } + function u(e, t, n) { + var r = e.getAnnotations().sort(s.comparePoints); + if (!r.length) return; + var i = o(r, { row: t, column: -1 }, s.comparePoints); + i < 0 && (i = -i - 1), + i >= r.length + ? (i = n > 0 ? 0 : r.length - 1) + : i === 0 && n < 0 && (i = r.length - 1); + var u = r[i]; + if (!u || !n) return; + if (u.row === t) { + do u = r[(i += n)]; + while (u && u.row === t); + if (!u) return r.slice(); + } + var a = []; + t = u.row; + do a[n < 0 ? "unshift" : "push"](u), (u = r[(i += n)]); + while (u && u.row == t); + return a.length && a; + } + var r = e("../line_widgets").LineWidgets, + i = e("../lib/dom"), + s = e("../range").Range; + (t.showErrorMarker = function (e, t) { + var n = e.session; + n.widgetManager || ((n.widgetManager = new r(n)), n.widgetManager.attach(e)); + var s = e.getCursorPosition(), + o = s.row, + a = n.widgetManager.getWidgetsAtRow(o).filter(function (e) { + return e.type == "errorMarker"; + })[0]; + a ? a.destroy() : (o -= t); + var f = u(n, o, t), + l; + if (f) { + var c = f[0]; + (s.column = (c.pos && typeof c.column != "number" ? c.pos.sc : c.column) || 0), + (s.row = c.row), + (l = e.renderer.$gutterLayer.$annotations[s.row]); + } else { + if (a) return; + l = { text: ["Looks good!"], className: "ace_ok" }; + } + e.session.unfold(s.row), e.selection.moveToPosition(s); + var h = { + row: s.row, + fixedWidth: !0, + coverGutter: !0, + el: i.createElement("div"), + type: "errorMarker", + }, + p = h.el.appendChild(i.createElement("div")), + d = h.el.appendChild(i.createElement("div")); + d.className = "error_widget_arrow " + l.className; + var v = e.renderer.$cursorLayer.getPixelPosition(s).left; + (d.style.left = v + e.renderer.gutterWidth - 5 + "px"), + (h.el.className = "error_widget_wrapper"), + (p.className = "error_widget " + l.className), + (p.innerHTML = l.text.join("
")), + p.appendChild(i.createElement("div")); + var m = function (e, t, n) { + if (t === 0 && (n === "esc" || n === "return")) + return h.destroy(), { command: "null" }; + }; + (h.destroy = function () { + if (e.$mouseHandler.isMousePressed) return; + e.keyBinding.removeKeyboardHandler(m), + n.widgetManager.removeLineWidget(h), + e.off("changeSelection", h.destroy), + e.off("changeSession", h.destroy), + e.off("mouseup", h.destroy), + e.off("change", h.destroy); + }), + e.keyBinding.addKeyboardHandler(m), + e.on("changeSelection", h.destroy), + e.on("changeSession", h.destroy), + e.on("mouseup", h.destroy), + e.on("change", h.destroy), + e.session.widgetManager.addLineWidget(h), + (h.el.onmousedown = e.focus.bind(e)), + e.renderer.scrollCursorIntoView(null, 0.5, { bottom: h.el.offsetHeight }); + }), + i.importCssString( + " .error_widget_wrapper { background: inherit; color: inherit; border:none } .error_widget { border-top: solid 2px; border-bottom: solid 2px; margin: 5px 0; padding: 10px 40px; white-space: pre-wrap; } .error_widget.ace_error, .error_widget_arrow.ace_error{ border-color: #ff5a5a } .error_widget.ace_warning, .error_widget_arrow.ace_warning{ border-color: #F1D817 } .error_widget.ace_info, .error_widget_arrow.ace_info{ border-color: #5a5a5a } .error_widget.ace_ok, .error_widget_arrow.ace_ok{ border-color: #5aaa5a } .error_widget_arrow { position: absolute; border: solid 5px; border-top-color: transparent!important; border-right-color: transparent!important; border-left-color: transparent!important; top: -5px; }", + "", + ); + }, + ), + define( + "ace/ace", + [ + "require", + "exports", + "module", + "ace/lib/fixoldbrowsers", + "ace/lib/dom", + "ace/lib/event", + "ace/range", + "ace/editor", + "ace/edit_session", + "ace/undomanager", + "ace/virtual_renderer", + "ace/worker/worker_client", + "ace/keyboard/hash_handler", + "ace/placeholder", + "ace/multi_select", + "ace/mode/folding/fold_mode", + "ace/theme/textmate", + "ace/ext/error_marker", + "ace/config", + ], + function (e, t, n) { + "use strict"; + e("./lib/fixoldbrowsers"); + var r = e("./lib/dom"), + i = e("./lib/event"), + s = e("./range").Range, + o = e("./editor").Editor, + u = e("./edit_session").EditSession, + a = e("./undomanager").UndoManager, + f = e("./virtual_renderer").VirtualRenderer; + e("./worker/worker_client"), + e("./keyboard/hash_handler"), + e("./placeholder"), + e("./multi_select"), + e("./mode/folding/fold_mode"), + e("./theme/textmate"), + e("./ext/error_marker"), + (t.config = e("./config")), + (t.require = e), + typeof define == "function" && (t.define = define), + (t.edit = function (e, n) { + if (typeof e == "string") { + var s = e; + e = document.getElementById(s); + if (!e) throw new Error("ace.edit can't find div #" + s); + } + if (e && e.env && e.env.editor instanceof o) return e.env.editor; + var u = ""; + if (e && /input|textarea/i.test(e.tagName)) { + var a = e; + (u = a.value), + (e = r.createElement("pre")), + a.parentNode.replaceChild(e, a); + } else e && ((u = e.textContent), (e.innerHTML = "")); + var l = t.createEditSession(u), + c = new o(new f(e), l, n), + h = { document: l, editor: c, onResize: c.resize.bind(c, null) }; + return ( + a && (h.textarea = a), + i.addListener(window, "resize", h.onResize), + c.on("destroy", function () { + i.removeListener(window, "resize", h.onResize), + (h.editor.container.env = null); + }), + (c.container.env = c.env = h), + c + ); + }), + (t.createEditSession = function (e, t) { + var n = new u(e, t); + return n.setUndoManager(new a()), n; + }), + (t.Range = s), + (t.EditSession = u), + (t.UndoManager = a), + (t.VirtualRenderer = f), + (t.version = "1.4.1"); + }, + ); +(function () { + window.require(["ace/ace"], function (a) { + if (a) { + a.config.init(true); + a.define = window.define; + } + if (!window.ace) window.ace = a; + for (var key in a) if (a.hasOwnProperty(key)) window.ace[key] = a[key]; + window.ace["default"] = window.ace; + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = window.ace; + } + }); +})(); diff --git a/web/static/ace/ext-beautify.js b/web/static/ace/ext-beautify.js index fa8bb5ae5..c95276659 100644 --- a/web/static/ace/ext-beautify.js +++ b/web/static/ace/ext-beautify.js @@ -1,9 +1,245 @@ -define("ace/ext/beautify",["require","exports","module","ace/token_iterator"],function(e,t,n){"use strict";function i(e,t){return e.type.lastIndexOf(t+".xml")>-1}var r=e("../token_iterator").TokenIterator;t.singletonTags=["area","base","br","col","command","embed","hr","html","img","input","keygen","link","meta","param","source","track","wbr"],t.blockTags=["article","aside","blockquote","body","div","dl","fieldset","footer","form","head","header","html","nav","ol","p","script","section","style","table","tbody","tfoot","thead","ul"],t.beautify=function(e){var n=new r(e,0,0),s=n.getCurrentToken(),o=e.getTabString(),u=t.singletonTags,a=t.blockTags,f,l=!1,c=!1,h=!1,p="",d="",v="",m=0,g=0,y=0,b=0,w=0,E=0,S=!1,x,T=0,N=0,C=[],k=!1,L,A=!1,O=!1,M=!1,_=!1,D={0:0},P={},H=function(){f&&f.value&&f.type!=="string.regexp"&&(f.value=f.value.trim())},B=function(){p=p.replace(/ +$/,"")},j=function(){p=p.trimRight(),l=!1};while(s!==null){T=n.getCurrentTokenRow(),C=n.$rowTokens,f=n.stepForward();if(typeof s!="undefined"){d=s.value,w=0,M=v==="style"||e.$modeId==="ace/mode/css",i(s,"tag-open")?(O=!0,f&&(_=a.indexOf(f.value)!==-1),d==="0;N--)p+="\n";l=!0,!i(s,"comment")&&!s.type.match(/^(comment|string)$/)&&(d=d.trimLeft())}if(d){s.type==="keyword"&&d.match(/^(if|else|elseif|for|foreach|while|switch)$/)?(P[m]=d,H(),h=!0,d.match(/^(else|elseif)$/)&&p.match(/\}[\s]*$/)&&(j(),c=!0)):s.type==="paren.lparen"?(H(),d.substr(-1)==="{"&&(h=!0,A=!1,O||(N=1)),d.substr(0,1)==="{"&&(c=!0,p.substr(-1)!=="["&&p.trimRight().substr(-1)==="["?(j(),c=!1):p.trimRight().substr(-1)===")"?j():B())):s.type==="paren.rparen"?(w=1,d.substr(0,1)==="}"&&(P[m-1]==="case"&&w++,p.trimRight().substr(-1)==="{"?j():(c=!0,M&&(N+=2))),d.substr(0,1)==="]"&&p.substr(-1)!=="}"&&p.trimRight().substr(-1)==="}"&&(c=!1,b++,j()),d.substr(0,1)===")"&&p.substr(-1)!=="("&&p.trimRight().substr(-1)==="("&&(c=!1,b++,j()),B()):s.type!=="keyword.operator"&&s.type!=="keyword"||!d.match(/^(=|==|===|!=|!==|&&|\|\||and|or|xor|\+=|.=|>|>=|<|<=|=>)$/)?s.type==="punctuation.operator"&&d===";"?(j(),H(),h=!0,M&&N++):s.type==="punctuation.operator"&&d.match(/^(:|,)$/)?(j(),H(),h=!0,l=!1):s.type==="support.php_tag"&&d==="?>"&&!l?(j(),c=!0):i(s,"attribute-name")&&p.substr(-1).match(/^\s$/)?c=!0:i(s,"attribute-equals")?(B(),H()):i(s,"tag-close")&&(B(),d==="/>"&&(c=!0)):(j(),H(),c=!0,h=!0);if(l&&(!s.type.match(/^(comment)$/)||!!d.substr(0,1).match(/^[/#]$/))&&(!s.type.match(/^(string)$/)||!!d.substr(0,1).match(/^['"]$/))){b=y;if(m>g){b++;for(L=m;L>g;L--)D[L]=b}else m")_&&f&&f.value===""&&u.indexOf(v)===-1&&m--,x=T}}s=f}p=p.trim(),e.doc.setValue(p)},t.commands=[{name:"beautify",exec:function(e){t.beautify(e.session)},bindKey:"Ctrl-Shift-B"}]}); - (function() { - window.require(["ace/ext/beautify"], function(m) { - if (typeof module == "object" && typeof exports == "object" && module) { - module.exports = m; +define("ace/ext/beautify", ["require", "exports", "module", "ace/token_iterator"], function ( + e, + t, + n, +) { + "use strict"; + function i(e, t) { + return e.type.lastIndexOf(t + ".xml") > -1; + } + var r = e("../token_iterator").TokenIterator; + (t.singletonTags = [ + "area", + "base", + "br", + "col", + "command", + "embed", + "hr", + "html", + "img", + "input", + "keygen", + "link", + "meta", + "param", + "source", + "track", + "wbr", + ]), + (t.blockTags = [ + "article", + "aside", + "blockquote", + "body", + "div", + "dl", + "fieldset", + "footer", + "form", + "head", + "header", + "html", + "nav", + "ol", + "p", + "script", + "section", + "style", + "table", + "tbody", + "tfoot", + "thead", + "ul", + ]), + (t.beautify = function (e) { + var n = new r(e, 0, 0), + s = n.getCurrentToken(), + o = e.getTabString(), + u = t.singletonTags, + a = t.blockTags, + f, + l = !1, + c = !1, + h = !1, + p = "", + d = "", + v = "", + m = 0, + g = 0, + y = 0, + b = 0, + w = 0, + E = 0, + S = !1, + x, + T = 0, + N = 0, + C = [], + k = !1, + L, + A = !1, + O = !1, + M = !1, + _ = !1, + D = { 0: 0 }, + P = {}, + H = function () { + f && f.value && f.type !== "string.regexp" && (f.value = f.value.trim()); + }, + B = function () { + p = p.replace(/ +$/, ""); + }, + j = function () { + (p = p.trimRight()), (l = !1); + }; + while (s !== null) { + (T = n.getCurrentTokenRow()), (C = n.$rowTokens), (f = n.stepForward()); + if (typeof s != "undefined") { + (d = s.value), + (w = 0), + (M = v === "style" || e.$modeId === "ace/mode/css"), + i(s, "tag-open") + ? ((O = !0), + f && (_ = a.indexOf(f.value) !== -1), + d === " 0; N--) p += "\n"; + (l = !0), + !i(s, "comment") && + !s.type.match(/^(comment|string)$/) && + (d = d.trimLeft()); + } + if (d) { + s.type === "keyword" && + d.match(/^(if|else|elseif|for|foreach|while|switch)$/) + ? ((P[m] = d), + H(), + (h = !0), + d.match(/^(else|elseif)$/) && p.match(/\}[\s]*$/) && (j(), (c = !0))) + : s.type === "paren.lparen" + ? (H(), + d.substr(-1) === "{" && ((h = !0), (A = !1), O || (N = 1)), + d.substr(0, 1) === "{" && + ((c = !0), + p.substr(-1) !== "[" && p.trimRight().substr(-1) === "[" + ? (j(), (c = !1)) + : p.trimRight().substr(-1) === ")" + ? j() + : B())) + : s.type === "paren.rparen" + ? ((w = 1), + d.substr(0, 1) === "}" && + (P[m - 1] === "case" && w++, + p.trimRight().substr(-1) === "{" + ? j() + : ((c = !0), M && (N += 2))), + d.substr(0, 1) === "]" && + p.substr(-1) !== "}" && + p.trimRight().substr(-1) === "}" && + ((c = !1), b++, j()), + d.substr(0, 1) === ")" && + p.substr(-1) !== "(" && + p.trimRight().substr(-1) === "(" && + ((c = !1), b++, j()), + B()) + : (s.type !== "keyword.operator" && s.type !== "keyword") || + !d.match( + /^(=|==|===|!=|!==|&&|\|\||and|or|xor|\+=|.=|>|>=|<|<=|=>)$/, + ) + ? s.type === "punctuation.operator" && d === ";" + ? (j(), H(), (h = !0), M && N++) + : s.type === "punctuation.operator" && d.match(/^(:|,)$/) + ? (j(), H(), (h = !0), (l = !1)) + : s.type === "support.php_tag" && d === "?>" && !l + ? (j(), (c = !0)) + : i(s, "attribute-name") && p.substr(-1).match(/^\s$/) + ? (c = !0) + : i(s, "attribute-equals") + ? (B(), H()) + : i(s, "tag-close") && (B(), d === "/>" && (c = !0)) + : (j(), H(), (c = !0), (h = !0)); + if ( + l && + (!s.type.match(/^(comment)$/) || !!d.substr(0, 1).match(/^[/#]$/)) && + (!s.type.match(/^(string)$/) || !!d.substr(0, 1).match(/^['"]$/)) + ) { + b = y; + if (m > g) { + b++; + for (L = m; L > g; L--) D[L] = b; + } else m < g && (b = D[m]); + (g = m), (y = b), w && (b -= w), A && !E && (b++, (A = !1)); + for (L = 0; L < b; L++) p += o; } - }); - })(); - \ No newline at end of file + s.type === "keyword" && d.match(/^(case|default)$/) && ((P[m] = d), m++), + s.type === "keyword" && + d.match(/^(break)$/) && + P[m - 1] && + P[m - 1].match(/^(case|default)$/) && + m--, + s.type === "paren.lparen" && + ((E += (d.match(/\(/g) || []).length), (m += d.length)), + s.type === "keyword" && d.match(/^(if|else|elseif|for|while)$/) + ? ((A = !0), (E = 0)) + : !E && d.trim() && s.type !== "comment" && (A = !1); + if (s.type === "paren.rparen") { + E -= (d.match(/\)/g) || []).length; + for (L = 0; L < d.length; L++) + m--, d.substr(L, 1) === "}" && P[m] === "case" && m--; + } + c && !l && (B(), p.substr(-1) !== "\n" && (p += " ")), + (p += d), + h && (p += " "), + (l = !1), + (c = !1), + (h = !1); + if ( + (i(s, "tag-close") && (_ || a.indexOf(v) !== -1)) || + (i(s, "doctype") && d === ">") + ) + _ && f && f.value === "" && u.indexOf(v) === -1 && m--, + (x = T); + } + } + s = f; + } + (p = p.trim()), e.doc.setValue(p); + }), + (t.commands = [ + { + name: "beautify", + exec: function (e) { + t.beautify(e.session); + }, + bindKey: "Ctrl-Shift-B", + }, + ]); +}); +(function () { + window.require(["ace/ext/beautify"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/ext-elastic_tabstops_lite.js b/web/static/ace/ext-elastic_tabstops_lite.js index 0b0085740..d0859a823 100644 --- a/web/static/ace/ext-elastic_tabstops_lite.js +++ b/web/static/ace/ext-elastic_tabstops_lite.js @@ -1,9 +1,208 @@ -define("ace/ext/elastic_tabstops_lite",["require","exports","module","ace/editor","ace/config"],function(e,t,n){"use strict";var r=function(e){this.$editor=e;var t=this,n=[],r=!1;this.onAfterExec=function(){r=!1,t.processRows(n),n=[]},this.onExec=function(){r=!0},this.onChange=function(e){r&&(n.indexOf(e.start.row)==-1&&n.push(e.start.row),e.end.row!=e.start.row&&n.push(e.end.row))}};(function(){this.processRows=function(e){this.$inChange=!0;var t=[];for(var n=0,r=e.length;n-1)continue;var s=this.$findCellWidthsForBlock(i),o=this.$setBlockCellWidthsToMax(s.cellWidths),u=s.firstRow;for(var a=0,f=o.length;a=0){n=this.$cellWidthsForRow(r);if(n.length==0)break;t.unshift(n),r--}var i=r+1;r=e;var s=this.$editor.session.getLength();while(r0&&(this.$editor.session.getDocument().insertInLine({row:e,column:f+1},Array(l+1).join(" ")+" "),this.$editor.session.getDocument().removeInLine(e,f,f+1),r+=l),l<0&&p>=-l&&(this.$editor.session.getDocument().removeInLine(e,f+l,f),r+=l)}},this.$izip_longest=function(e){if(!e[0])return[];var t=e[0].length,n=e.length;for(var r=1;rt&&(t=i)}var s=[];for(var o=0;o=t.length?t.length:e.length,r=[];for(var i=0;i -1) continue; + var s = this.$findCellWidthsForBlock(i), + o = this.$setBlockCellWidthsToMax(s.cellWidths), + u = s.firstRow; + for (var a = 0, f = o.length; a < f; a++) { + var l = o[a]; + t.push(u), this.$adjustRow(u, l), u++; + } + } + this.$inChange = !1; + }), + (this.$findCellWidthsForBlock = function (e) { + var t = [], + n, + r = e; + while (r >= 0) { + n = this.$cellWidthsForRow(r); + if (n.length == 0) break; + t.unshift(n), r--; + } + var i = r + 1; + r = e; + var s = this.$editor.session.getLength(); + while (r < s - 1) { + r++, (n = this.$cellWidthsForRow(r)); + if (n.length == 0) break; + t.push(n); + } + return { cellWidths: t, firstRow: i }; + }), + (this.$cellWidthsForRow = function (e) { + var t = this.$selectionColumnsForRow(e), + n = [-1].concat(this.$tabsForRow(e)), + r = n + .map(function (e) { + return 0; + }) + .slice(1), + i = this.$editor.session.getLine(e); + for (var s = 0, o = n.length - 1; s < o; s++) { + var u = n[s] + 1, + a = n[s + 1], + f = this.$rightmostSelectionInCell(t, a), + l = i.substring(u, a); + r[s] = Math.max(l.replace(/\s+$/g, "").length, f - u); + } + return r; + }), + (this.$selectionColumnsForRow = function (e) { + var t = [], + n = this.$editor.getCursorPosition(); + return ( + this.$editor.session.getSelection().isEmpty() && e == n.row && t.push(n.column), + t + ); + }), + (this.$setBlockCellWidthsToMax = function (e) { + var t = !0, + n, + r, + i, + s = this.$izip_longest(e); + for (var o = 0, u = s.length; o < u; o++) { + var a = s[o]; + if (!a.push) { + console.error(a); + continue; + } + a.push(NaN); + for (var f = 0, l = a.length; f < l; f++) { + var c = a[f]; + t && ((n = f), (i = 0), (t = !1)); + if (isNaN(c)) { + r = f; + for (var h = n; h < r; h++) e[h][o] = i; + t = !0; } - }); - })(); - \ No newline at end of file + i = Math.max(i, c); + } + } + return e; + }), + (this.$rightmostSelectionInCell = function (e, t) { + var n = 0; + if (e.length) { + var r = []; + for (var i = 0, s = e.length; i < s; i++) e[i] <= t ? r.push(i) : r.push(0); + n = Math.max.apply(Math, r); + } + return n; + }), + (this.$tabsForRow = function (e) { + var t = [], + n = this.$editor.session.getLine(e), + r = /\t/g, + i; + while ((i = r.exec(n)) != null) t.push(i.index); + return t; + }), + (this.$adjustRow = function (e, t) { + var n = this.$tabsForRow(e); + if (n.length == 0) return; + var r = 0, + i = -1, + s = this.$izip(t, n); + for (var o = 0, u = s.length; o < u; o++) { + var a = s[o][0], + f = s[o][1]; + (i += 1 + a), (f += r); + var l = i - f; + if (l == 0) continue; + var c = this.$editor.session.getLine(e).substr(0, f), + h = c.replace(/\s*$/g, ""), + p = c.length - h.length; + l > 0 && + (this.$editor.session + .getDocument() + .insertInLine({ row: e, column: f + 1 }, Array(l + 1).join(" ") + " "), + this.$editor.session.getDocument().removeInLine(e, f, f + 1), + (r += l)), + l < 0 && + p >= -l && + (this.$editor.session.getDocument().removeInLine(e, f + l, f), + (r += l)); + } + }), + (this.$izip_longest = function (e) { + if (!e[0]) return []; + var t = e[0].length, + n = e.length; + for (var r = 1; r < n; r++) { + var i = e[r].length; + i > t && (t = i); + } + var s = []; + for (var o = 0; o < t; o++) { + var u = []; + for (var r = 0; r < n; r++) e[r][o] === "" ? u.push(NaN) : u.push(e[r][o]); + s.push(u); + } + return s; + }), + (this.$izip = function (e, t) { + var n = e.length >= t.length ? t.length : e.length, + r = []; + for (var i = 0; i < n; i++) { + var s = [e[i], t[i]]; + r.push(s); + } + return r; + }); + }).call(r.prototype), + (t.ElasticTabstopsLite = r); + var i = e("../editor").Editor; + e("../config").defineOptions(i.prototype, "editor", { + useElasticTabstops: { + set: function (e) { + e + ? (this.elasticTabstops || (this.elasticTabstops = new r(this)), + this.commands.on("afterExec", this.elasticTabstops.onAfterExec), + this.commands.on("exec", this.elasticTabstops.onExec), + this.on("change", this.elasticTabstops.onChange)) + : this.elasticTabstops && + (this.commands.removeListener("afterExec", this.elasticTabstops.onAfterExec), + this.commands.removeListener("exec", this.elasticTabstops.onExec), + this.removeListener("change", this.elasticTabstops.onChange)); + }, + }, + }); +}); +(function () { + window.require(["ace/ext/elastic_tabstops_lite"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/ext-emmet.js b/web/static/ace/ext-emmet.js index a8b70e406..76bf10aaa 100644 --- a/web/static/ace/ext-emmet.js +++ b/web/static/ace/ext-emmet.js @@ -1,9 +1,1053 @@ -define("ace/snippets",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/lib/lang","ace/range","ace/anchor","ace/keyboard/hash_handler","ace/tokenizer","ace/lib/dom","ace/editor"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./lib/event_emitter").EventEmitter,s=e("./lib/lang"),o=e("./range").Range,u=e("./anchor").Anchor,a=e("./keyboard/hash_handler").HashHandler,f=e("./tokenizer").Tokenizer,l=o.comparePoints,c=function(){this.snippetMap={},this.snippetNameMap={}};(function(){r.implement(this,i),this.getTokenizer=function(){function e(e,t,n){return e=e.substr(1),/^\d+$/.test(e)&&!n.inFormatString?[{tabstopId:parseInt(e,10)}]:[{text:e}]}function t(e){return"(?:[^\\\\"+e+"]|\\\\.)"}return c.$tokenizer=new f({start:[{regex:/:/,onMatch:function(e,t,n){return n.length&&n[0].expectIf?(n[0].expectIf=!1,n[0].elseBranch=n[0],[n[0]]):":"}},{regex:/\\./,onMatch:function(e,t,n){var r=e[1];return r=="}"&&n.length?e=r:"`$\\".indexOf(r)!=-1?e=r:n.inFormatString&&(r=="n"?e="\n":r=="t"?e="\n":"ulULE".indexOf(r)!=-1&&(e={changeCase:r,local:r>"a"})),[e]}},{regex:/}/,onMatch:function(e,t,n){return[n.length?n.shift():e]}},{regex:/\$(?:\d+|\w+)/,onMatch:e},{regex:/\$\{[\dA-Z_a-z]+/,onMatch:function(t,n,r){var i=e(t.substr(1),n,r);return r.unshift(i[0]),i},next:"snippetVar"},{regex:/\n/,token:"newline",merge:!1}],snippetVar:[{regex:"\\|"+t("\\|")+"*\\|",onMatch:function(e,t,n){n[0].choices=e.slice(1,-1).split(",")},next:"start"},{regex:"/("+t("/")+"+)/(?:("+t("/")+"*)/)(\\w*):?",onMatch:function(e,t,n){var r=n[0];return r.fmtString=e,e=this.splitRegex.exec(e),r.guard=e[1],r.fmt=e[2],r.flag=e[3],""},next:"start"},{regex:"`"+t("`")+"*`",onMatch:function(e,t,n){return n[0].code=e.splice(1,-1),""},next:"start"},{regex:"\\?",onMatch:function(e,t,n){n[0]&&(n[0].expectIf=!0)},next:"start"},{regex:"([^:}\\\\]|\\\\.)*:?",token:"",next:"start"}],formatString:[{regex:"/("+t("/")+"+)/",token:"regex"},{regex:"",onMatch:function(e,t,n){n.inFormatString=!0},next:"start"}]}),c.prototype.getTokenizer=function(){return c.$tokenizer},c.$tokenizer},this.tokenizeTmSnippet=function(e,t){return this.getTokenizer().getLineTokens(e,t).tokens.map(function(e){return e.value||e})},this.$getDefaultValue=function(e,t){if(/^[A-Z]\d+$/.test(t)){var n=t.substr(1);return(this.variables[t[0]+"__"]||{})[n]}if(/^\d+$/.test(t))return(this.variables.__||{})[t];t=t.replace(/^TM_/,"");if(!e)return;var r=e.session;switch(t){case"CURRENT_WORD":var i=r.getWordRange();case"SELECTION":case"SELECTED_TEXT":return r.getTextRange(i);case"CURRENT_LINE":return r.getLine(e.getCursorPosition().row);case"PREV_LINE":return r.getLine(e.getCursorPosition().row-1);case"LINE_INDEX":return e.getCursorPosition().column;case"LINE_NUMBER":return e.getCursorPosition().row+1;case"SOFT_TABS":return r.getUseSoftTabs()?"YES":"NO";case"TAB_SIZE":return r.getTabSize();case"FILENAME":case"FILEPATH":return"";case"FULLNAME":return"Ace"}},this.variables={},this.getVariableValue=function(e,t){return this.variables.hasOwnProperty(t)?this.variables[t](e,t)||"":this.$getDefaultValue(e,t)||""},this.tmStrFormat=function(e,t,n){var r=t.flag||"",i=t.guard;i=new RegExp(i,r.replace(/[^gi]/,""));var s=this.tokenizeTmSnippet(t.fmt,"formatString"),o=this,u=e.replace(i,function(){o.variables.__=arguments;var e=o.resolveVariables(s,n),t="E";for(var r=0;r1?(y=t[t.length-1].length,g+=t.length-1):y+=e.length,b+=e}else e.start?e.end={row:g,column:y}:e.start={row:g,column:y}});var w=e.getSelectionRange(),E=e.session.replace(w,b),S=new h(e),x=e.inVirtualSelectionMode&&e.selection.index;S.addTabstops(u,w.start,E,x)},this.insertSnippet=function(e,t){var n=this;if(e.inVirtualSelectionMode)return n.insertSnippetForSelection(e,t);e.forEachSelection(function(){n.insertSnippetForSelection(e,t)},null,{keepOrder:!0}),e.tabstopManager&&e.tabstopManager.tabNext()},this.$getScope=function(e){var t=e.session.$mode.$id||"";t=t.split("/").pop();if(t==="html"||t==="php"){t==="php"&&!e.session.$mode.inlinePhp&&(t="html");var n=e.getCursorPosition(),r=e.session.getState(n.row);typeof r=="object"&&(r=r[0]),r.substring&&(r.substring(0,3)=="js-"?t="javascript":r.substring(0,4)=="css-"?t="css":r.substring(0,4)=="php-"&&(t="php"))}return t},this.getActiveScopes=function(e){var t=this.$getScope(e),n=[t],r=this.snippetMap;return r[t]&&r[t].includeScopes&&n.push.apply(n,r[t].includeScopes),n.push("_"),n},this.expandWithTab=function(e,t){var n=this,r=e.forEachSelection(function(){return n.expandSnippetForSelection(e,t)},null,{keepOrder:!0});return r&&e.tabstopManager&&e.tabstopManager.tabNext(),r},this.expandSnippetForSelection=function(e,t){var n=e.getCursorPosition(),r=e.session.getLine(n.row),i=r.substring(0,n.column),s=r.substr(n.column),o=this.snippetMap,u;return this.getActiveScopes(e).some(function(e){var t=o[e];return t&&(u=this.findMatchingSnippet(t,i,s)),!!u},this),u?t&&t.dryRun?!0:(e.session.doc.removeInLine(n.row,n.column-u.replaceBefore.length,n.column+u.replaceAfter.length),this.variables.M__=u.matchBefore,this.variables.T__=u.matchAfter,this.insertSnippetForSelection(e,u.content),this.variables.M__=this.variables.T__=null,!0):!1},this.findMatchingSnippet=function(e,t,n){for(var r=e.length;r--;){var i=e[r];if(i.startRe&&!i.startRe.test(t))continue;if(i.endRe&&!i.endRe.test(n))continue;if(!i.startRe&&!i.endRe)continue;return i.matchBefore=i.startRe?i.startRe.exec(t):[""],i.matchAfter=i.endRe?i.endRe.exec(n):[""],i.replaceBefore=i.triggerRe?i.triggerRe.exec(t)[0]:"",i.replaceAfter=i.endTriggerRe?i.endTriggerRe.exec(n)[0]:"",i}},this.snippetMap={},this.snippetNameMap={},this.register=function(e,t){function o(e){return e&&!/^\^?\(.*\)\$?$|^\\b$/.test(e)&&(e="(?:"+e+")"),e||""}function u(e,t,n){return e=o(e),t=o(t),n?(e=t+e,e&&e[e.length-1]!="$"&&(e+="$")):(e+=t,e&&e[0]!="^"&&(e="^"+e)),new RegExp(e)}function a(e){e.scope||(e.scope=t||"_"),t=e.scope,n[t]||(n[t]=[],r[t]={});var o=r[t];if(e.name){var a=o[e.name];a&&i.unregister(a),o[e.name]=e}n[t].push(e),e.tabTrigger&&!e.trigger&&(!e.guard&&/^\w/.test(e.tabTrigger)&&(e.guard="\\b"),e.trigger=s.escapeRegExp(e.tabTrigger));if(!e.trigger&&!e.guard&&!e.endTrigger&&!e.endGuard)return;e.startRe=u(e.trigger,e.guard,!0),e.triggerRe=new RegExp(e.trigger),e.endRe=u(e.endTrigger,e.endGuard,!0),e.endTriggerRe=new RegExp(e.endTrigger)}var n=this.snippetMap,r=this.snippetNameMap,i=this;e||(e=[]),e&&e.content?a(e):Array.isArray(e)&&e.forEach(a),this._signal("registerSnippets",{scope:t})},this.unregister=function(e,t){function i(e){var i=r[e.scope||t];if(i&&i[e.name]){delete i[e.name];var s=n[e.scope||t],o=s&&s.indexOf(e);o>=0&&s.splice(o,1)}}var n=this.snippetMap,r=this.snippetNameMap;e.content?i(e):Array.isArray(e)&&e.forEach(i)},this.parseSnippetFile=function(e){e=e.replace(/\r/g,"");var t=[],n={},r=/^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm,i;while(i=r.exec(e)){if(i[1])try{n=JSON.parse(i[1]),t.push(n)}catch(s){}if(i[4])n.content=i[4].replace(/^\t/gm,""),t.push(n),n={};else{var o=i[2],u=i[3];if(o=="regex"){var a=/\/((?:[^\/\\]|\\.)*)|$/g;n.guard=a.exec(u)[1],n.trigger=a.exec(u)[1],n.endTrigger=a.exec(u)[1],n.endGuard=a.exec(u)[1]}else o=="snippet"?(n.tabTrigger=u.match(/^\S*/)[0],n.name||(n.name=u)):n[o]=u}}return t},this.getSnippetByName=function(e,t){var n=this.snippetNameMap,r;return this.getActiveScopes(t).some(function(t){var i=n[t];return i&&(r=i[e]),!!r},this),r}}).call(c.prototype);var h=function(e){if(e.tabstopManager)return e.tabstopManager;e.tabstopManager=this,this.$onChange=this.onChange.bind(this),this.$onChangeSelection=s.delayedCall(this.onChangeSelection.bind(this)).schedule,this.$onChangeSession=this.onChangeSession.bind(this),this.$onAfterExec=this.onAfterExec.bind(this),this.attach(e)};(function(){this.attach=function(e){this.index=0,this.ranges=[],this.tabstops=[],this.$openTabstops=null,this.selectedTabstop=null,this.editor=e,this.editor.on("change",this.$onChange),this.editor.on("changeSelection",this.$onChangeSelection),this.editor.on("changeSession",this.$onChangeSession),this.editor.commands.on("afterExec",this.$onAfterExec),this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler)},this.detach=function(){this.tabstops.forEach(this.removeTabstopMarkers,this),this.ranges=null,this.tabstops=null,this.selectedTabstop=null,this.editor.removeListener("change",this.$onChange),this.editor.removeListener("changeSelection",this.$onChangeSelection),this.editor.removeListener("changeSession",this.$onChangeSession),this.editor.commands.removeListener("afterExec",this.$onAfterExec),this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler),this.editor.tabstopManager=null,this.editor=null},this.onChange=function(e){var t=e,n=e.action[0]=="r",r=e.start,i=e.end,s=r.row,o=i.row,u=o-s,a=i.column-r.column;n&&(u=-u,a=-a);if(!this.$inChange&&n){var f=this.selectedTabstop,c=f&&!f.some(function(e){return l(e.start,r)<=0&&l(e.end,i)>=0});if(c)return this.detach()}var h=this.ranges;for(var p=0;p0){this.removeRange(d),p--;continue}d.start.row==s&&d.start.column>r.column&&(d.start.column+=a),d.end.row==s&&d.end.column>=r.column&&(d.end.column+=a),d.start.row>=s&&(d.start.row+=u),d.end.row>=s&&(d.end.row+=u),l(d.start,d.end)>0&&this.removeRange(d)}h.length||this.detach()},this.updateLinkedFields=function(){var e=this.selectedTabstop;if(!e||!e.hasLinkedRanges)return;this.$inChange=!0;var n=this.editor.session,r=n.getTextRange(e.firstNonLinked);for(var i=e.length;i--;){var s=e[i];if(!s.linked)continue;var o=t.snippetManager.tmStrFormat(r,s.original);n.replace(s,o)}this.$inChange=!1},this.onAfterExec=function(e){e.command&&!e.command.readOnly&&this.updateLinkedFields()},this.onChangeSelection=function(){if(!this.editor)return;var e=this.editor.selection.lead,t=this.editor.selection.anchor,n=this.editor.selection.isEmpty();for(var r=this.ranges.length;r--;){if(this.ranges[r].linked)continue;var i=this.ranges[r].contains(e.row,e.column),s=n||this.ranges[r].contains(t.row,t.column);if(i&&s)return}this.detach()},this.onChangeSession=function(){this.detach()},this.tabNext=function(e){var t=this.tabstops.length,n=this.index+(e||1);n=Math.min(Math.max(n,1),t),n==t&&(n=0),this.selectTabstop(n),n===0&&this.detach()},this.selectTabstop=function(e){this.$openTabstops=null;var t=this.tabstops[this.index];t&&this.addTabstopMarkers(t),this.index=e,t=this.tabstops[this.index];if(!t||!t.length)return;this.selectedTabstop=t;if(!this.editor.inVirtualSelectionMode){var n=this.editor.multiSelect;n.toSingleRange(t.firstNonLinked.clone());for(var r=t.length;r--;){if(t.hasLinkedRanges&&t[r].linked)continue;n.addRange(t[r].clone(),!0)}n.ranges[0]&&n.addRange(n.ranges[0].clone())}else this.editor.selection.setRange(t.firstNonLinked);this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler)},this.addTabstops=function(e,t,n){this.$openTabstops||(this.$openTabstops=[]);if(!e[0]){var r=o.fromPoints(n,n);v(r.start,t),v(r.end,t),e[0]=[r],e[0].index=0}var i=this.index,s=[i+1,0],u=this.ranges;e.forEach(function(e,n){var r=this.$openTabstops[n]||e;for(var i=e.length;i--;){var a=e[i],f=o.fromPoints(a.start,a.end||a.start);d(f.start,t),d(f.end,t),f.original=a,f.tabstop=r,u.push(f),r!=e?r.unshift(f):r[i]=f,a.fmtString?(f.linked=!0,r.hasLinkedRanges=!0):r.firstNonLinked||(r.firstNonLinked=f)}r.firstNonLinked||(r.hasLinkedRanges=!1),r===e&&(s.push(r),this.$openTabstops[n]=r),this.addTabstopMarkers(r)},this),s.length>2&&(this.tabstops.length&&s.push(s.splice(2,1)[0]),this.tabstops.splice.apply(this.tabstops,s))},this.addTabstopMarkers=function(e){var t=this.editor.session;e.forEach(function(e){e.markerId||(e.markerId=t.addMarker(e,"ace_snippet-marker","text"))})},this.removeTabstopMarkers=function(e){var t=this.editor.session;e.forEach(function(e){t.removeMarker(e.markerId),e.markerId=null})},this.removeRange=function(e){var t=e.tabstop.indexOf(e);e.tabstop.splice(t,1),t=this.ranges.indexOf(e),this.ranges.splice(t,1),this.editor.session.removeMarker(e.markerId),e.tabstop.length||(t=this.tabstops.indexOf(e.tabstop),t!=-1&&this.tabstops.splice(t,1),this.tabstops.length||this.detach())},this.keyboardHandler=new a,this.keyboardHandler.bindKeys({Tab:function(e){if(t.snippetManager&&t.snippetManager.expandWithTab(e))return;e.tabstopManager.tabNext(1)},"Shift-Tab":function(e){e.tabstopManager.tabNext(-1)},Esc:function(e){e.tabstopManager.detach()},Return:function(e){return!1}})}).call(h.prototype);var p={};p.onChange=u.prototype.onChange,p.setPosition=function(e,t){this.pos.row=e,this.pos.column=t},p.update=function(e,t,n){this.$insertRight=n,this.pos=e,this.onChange(t)};var d=function(e,t){e.row==0&&(e.column+=t.column),e.row+=t.row},v=function(e,t){e.row==t.row&&(e.column-=t.column),e.row-=t.row};e("./lib/dom").importCssString(".ace_snippet-marker { -moz-box-sizing: border-box; box-sizing: border-box; background: rgba(194, 193, 208, 0.09); border: 1px dotted rgba(211, 208, 235, 0.62); position: absolute;}"),t.snippetManager=new c;var m=e("./editor").Editor;(function(){this.insertSnippet=function(e,n){return t.snippetManager.insertSnippet(this,e,n)},this.expandSnippet=function(e){return t.snippetManager.expandWithTab(this,e)}}).call(m.prototype)}),define("ace/ext/emmet",["require","exports","module","ace/keyboard/hash_handler","ace/editor","ace/snippets","ace/range","resources","resources","tabStops","resources","utils","actions","ace/config","ace/config"],function(e,t,n){"use strict";function f(){}var r=e("ace/keyboard/hash_handler").HashHandler,i=e("ace/editor").Editor,s=e("ace/snippets").snippetManager,o=e("ace/range").Range,u,a;f.prototype={setupContext:function(e){this.ace=e,this.indentation=e.session.getTabString(),u||(u=window.emmet);var t=u.resources||u.require("resources");t.setVariable("indentation",this.indentation),this.$syntax=null,this.$syntax=this.getSyntax()},getSelectionRange:function(){var e=this.ace.getSelectionRange(),t=this.ace.session.doc;return{start:t.positionToIndex(e.start),end:t.positionToIndex(e.end)}},createSelection:function(e,t){var n=this.ace.session.doc;this.ace.selection.setRange({start:n.indexToPosition(e),end:n.indexToPosition(t)})},getCurrentLineRange:function(){var e=this.ace,t=e.getCursorPosition().row,n=e.session.getLine(t).length,r=e.session.doc.positionToIndex({row:t,column:0});return{start:r,end:r+n}},getCaretPos:function(){var e=this.ace.getCursorPosition();return this.ace.session.doc.positionToIndex(e)},setCaretPos:function(e){var t=this.ace.session.doc.indexToPosition(e);this.ace.selection.moveToPosition(t)},getCurrentLine:function(){var e=this.ace.getCursorPosition().row;return this.ace.session.getLine(e)},replaceContent:function(e,t,n,r){n==null&&(n=t==null?this.getContent().length:t),t==null&&(t=0);var i=this.ace,u=i.session.doc,a=o.fromPoints(u.indexToPosition(t),u.indexToPosition(n));i.session.remove(a),a.end=a.start,e=this.$updateTabstops(e),s.insertSnippet(i,e)},getContent:function(){return this.ace.getValue()},getSyntax:function(){if(this.$syntax)return this.$syntax;var e=this.ace.session.$modeId.split("/").pop();if(e=="html"||e=="php"){var t=this.ace.getCursorPosition(),n=this.ace.session.getState(t.row);typeof n!="string"&&(n=n[0]),n&&(n=n.split("-"),n.length>1?e=n[0]:e=="php"&&(e="html"))}return e},getProfileName:function(){var e=u.resources||u.require("resources");switch(this.getSyntax()){case"css":return"css";case"xml":case"xsl":return"xml";case"html":var t=e.getVariable("profile");return t||(t=this.ace.session.getLines(0,2).join("").search(/]+XHTML/i)!=-1?"xhtml":"html"),t;default:var n=this.ace.session.$mode;return n.emmetConfig&&n.emmetConfig.profile||"xhtml"}},prompt:function(e){return prompt(e)},getSelection:function(){return this.ace.session.getTextRange()},getFilePath:function(){return""},$updateTabstops:function(e){var t=1e3,n=0,r=null,i=u.tabStops||u.require("tabStops"),s=u.resources||u.require("resources"),o=s.getVocabulary("user"),a={tabstop:function(e){var s=parseInt(e.group,10),o=s===0;o?s=++n:s+=t;var u=e.placeholder;u&&(u=i.processText(u,a));var f="${"+s+(u?":"+u:"")+"}";return o&&(r=[e.start,f]),f},escape:function(e){return e=="$"?"\\$":e=="\\"?"\\\\":e}};e=i.processText(e,a);if(o.variables.insert_final_tabstop&&!/\$\{0\}$/.test(e))e+="${0}";else if(r){var f=u.utils?u.utils.common:u.require("utils");e=f.replaceSubstring(e,"${0}",r[0],r[1])}return e}};var l={expand_abbreviation:{mac:"ctrl+alt+e",win:"alt+e"},match_pair_outward:{mac:"ctrl+d",win:"ctrl+,"},match_pair_inward:{mac:"ctrl+j",win:"ctrl+shift+0"},matching_pair:{mac:"ctrl+alt+j",win:"alt+j"},next_edit_point:"alt+right",prev_edit_point:"alt+left",toggle_comment:{mac:"command+/",win:"ctrl+/"},split_join_tag:{mac:"shift+command+'",win:"shift+ctrl+`"},remove_tag:{mac:"command+'",win:"shift+ctrl+;"},evaluate_math_expression:{mac:"shift+command+y",win:"shift+ctrl+y"},increment_number_by_1:"ctrl+up",decrement_number_by_1:"ctrl+down",increment_number_by_01:"alt+up",decrement_number_by_01:"alt+down",increment_number_by_10:{mac:"alt+command+up",win:"shift+alt+up"},decrement_number_by_10:{mac:"alt+command+down",win:"shift+alt+down"},select_next_item:{mac:"shift+command+.",win:"shift+ctrl+."},select_previous_item:{mac:"shift+command+,",win:"shift+ctrl+,"},reflect_css_value:{mac:"shift+command+r",win:"shift+ctrl+r"},encode_decode_data_url:{mac:"shift+ctrl+d",win:"ctrl+'"},expand_abbreviation_with_tab:"Tab",wrap_with_abbreviation:{mac:"shift+ctrl+a",win:"shift+ctrl+a"}},c=new f;t.commands=new r,t.runEmmetCommand=function d(e){try{c.setupContext(e);var n=u.actions||u.require("actions");if(this.action=="expand_abbreviation_with_tab"){if(!e.selection.isEmpty())return!1;var r=e.selection.lead,i=e.session.getTokenAt(r.row,r.column);if(i&&/\btag\b/.test(i.type))return!1}if(this.action=="wrap_with_abbreviation")return setTimeout(function(){n.run("wrap_with_abbreviation",c)},0);var s=n.run(this.action,c)}catch(o){if(!u)return t.load(d.bind(this,e)),!0;e._signal("changeStatus",typeof o=="string"?o:o.message),console.log(o),s=!1}return s};for(var h in l)t.commands.addCommand({name:"emmet:"+h,action:h,bindKey:l[h],exec:t.runEmmetCommand,multiSelectAction:"forEach"});t.updateCommands=function(e,n){n?e.keyBinding.addKeyboardHandler(t.commands):e.keyBinding.removeKeyboardHandler(t.commands)},t.isSupportedMode=function(e){if(!e)return!1;if(e.emmetConfig)return!0;var t=e.$id||e;return/css|less|scss|sass|stylus|html|php|twig|ejs|handlebars/.test(t)},t.isAvailable=function(e,n){if(/(evaluate_math_expression|expand_abbreviation)$/.test(n))return!0;var r=e.session.$mode,i=t.isSupportedMode(r);if(i&&r.$modes)try{c.setupContext(e),/js|php/.test(c.getSyntax())&&(i=!1)}catch(s){}return i};var p=function(e,n){var r=n;if(!r)return;var i=t.isSupportedMode(r.session.$mode);e.enableEmmet===!1&&(i=!1),i&&t.load(),t.updateCommands(r,i)};t.load=function(t){typeof a=="string"&&e("ace/config").loadModule(a,function(){a=null,t&&t()})},t.AceEmmetEditor=f,e("ace/config").defineOptions(i.prototype,"editor",{enableEmmet:{set:function(e){this[e?"on":"removeListener"]("changeMode",p),p({enableEmmet:!!e},this)},value:!0}}),t.setCore=function(e){typeof e=="string"?a=e:u=e}}); - (function() { - window.require(["ace/ext/emmet"], function(m) { - if (typeof module == "object" && typeof exports == "object" && module) { - module.exports = m; +define( + "ace/snippets", + [ + "require", + "exports", + "module", + "ace/lib/oop", + "ace/lib/event_emitter", + "ace/lib/lang", + "ace/range", + "ace/anchor", + "ace/keyboard/hash_handler", + "ace/tokenizer", + "ace/lib/dom", + "ace/editor", + ], + function (e, t, n) { + "use strict"; + var r = e("./lib/oop"), + i = e("./lib/event_emitter").EventEmitter, + s = e("./lib/lang"), + o = e("./range").Range, + u = e("./anchor").Anchor, + a = e("./keyboard/hash_handler").HashHandler, + f = e("./tokenizer").Tokenizer, + l = o.comparePoints, + c = function () { + (this.snippetMap = {}), (this.snippetNameMap = {}); + }; + (function () { + r.implement(this, i), + (this.getTokenizer = function () { + function e(e, t, n) { + return ( + (e = e.substr(1)), + /^\d+$/.test(e) && !n.inFormatString + ? [{ tabstopId: parseInt(e, 10) }] + : [{ text: e }] + ); + } + function t(e) { + return "(?:[^\\\\" + e + "]|\\\\.)"; + } + return ( + (c.$tokenizer = new f({ + start: [ + { + regex: /:/, + onMatch: function (e, t, n) { + return n.length && n[0].expectIf + ? ((n[0].expectIf = !1), + (n[0].elseBranch = n[0]), + [n[0]]) + : ":"; + }, + }, + { + regex: /\\./, + onMatch: function (e, t, n) { + var r = e[1]; + return ( + r == "}" && n.length + ? (e = r) + : "`$\\".indexOf(r) != -1 + ? (e = r) + : n.inFormatString && + (r == "n" + ? (e = "\n") + : r == "t" + ? (e = "\n") + : "ulULE".indexOf(r) != -1 && + (e = { + changeCase: r, + local: r > "a", + })), + [e] + ); + }, + }, + { + regex: /}/, + onMatch: function (e, t, n) { + return [n.length ? n.shift() : e]; + }, + }, + { regex: /\$(?:\d+|\w+)/, onMatch: e }, + { + regex: /\$\{[\dA-Z_a-z]+/, + onMatch: function (t, n, r) { + var i = e(t.substr(1), n, r); + return r.unshift(i[0]), i; + }, + next: "snippetVar", + }, + { regex: /\n/, token: "newline", merge: !1 }, + ], + snippetVar: [ + { + regex: "\\|" + t("\\|") + "*\\|", + onMatch: function (e, t, n) { + n[0].choices = e.slice(1, -1).split(","); + }, + next: "start", + }, + { + regex: "/(" + t("/") + "+)/(?:(" + t("/") + "*)/)(\\w*):?", + onMatch: function (e, t, n) { + var r = n[0]; + return ( + (r.fmtString = e), + (e = this.splitRegex.exec(e)), + (r.guard = e[1]), + (r.fmt = e[2]), + (r.flag = e[3]), + "" + ); + }, + next: "start", + }, + { + regex: "`" + t("`") + "*`", + onMatch: function (e, t, n) { + return (n[0].code = e.splice(1, -1)), ""; + }, + next: "start", + }, + { + regex: "\\?", + onMatch: function (e, t, n) { + n[0] && (n[0].expectIf = !0); + }, + next: "start", + }, + { regex: "([^:}\\\\]|\\\\.)*:?", token: "", next: "start" }, + ], + formatString: [ + { regex: "/(" + t("/") + "+)/", token: "regex" }, + { + regex: "", + onMatch: function (e, t, n) { + n.inFormatString = !0; + }, + next: "start", + }, + ], + })), + (c.prototype.getTokenizer = function () { + return c.$tokenizer; + }), + c.$tokenizer + ); + }), + (this.tokenizeTmSnippet = function (e, t) { + return this.getTokenizer() + .getLineTokens(e, t) + .tokens.map(function (e) { + return e.value || e; + }); + }), + (this.$getDefaultValue = function (e, t) { + if (/^[A-Z]\d+$/.test(t)) { + var n = t.substr(1); + return (this.variables[t[0] + "__"] || {})[n]; + } + if (/^\d+$/.test(t)) return (this.variables.__ || {})[t]; + t = t.replace(/^TM_/, ""); + if (!e) return; + var r = e.session; + switch (t) { + case "CURRENT_WORD": + var i = r.getWordRange(); + case "SELECTION": + case "SELECTED_TEXT": + return r.getTextRange(i); + case "CURRENT_LINE": + return r.getLine(e.getCursorPosition().row); + case "PREV_LINE": + return r.getLine(e.getCursorPosition().row - 1); + case "LINE_INDEX": + return e.getCursorPosition().column; + case "LINE_NUMBER": + return e.getCursorPosition().row + 1; + case "SOFT_TABS": + return r.getUseSoftTabs() ? "YES" : "NO"; + case "TAB_SIZE": + return r.getTabSize(); + case "FILENAME": + case "FILEPATH": + return ""; + case "FULLNAME": + return "Ace"; + } + }), + (this.variables = {}), + (this.getVariableValue = function (e, t) { + return this.variables.hasOwnProperty(t) + ? this.variables[t](e, t) || "" + : this.$getDefaultValue(e, t) || ""; + }), + (this.tmStrFormat = function (e, t, n) { + var r = t.flag || "", + i = t.guard; + i = new RegExp(i, r.replace(/[^gi]/, "")); + var s = this.tokenizeTmSnippet(t.fmt, "formatString"), + o = this, + u = e.replace(i, function () { + o.variables.__ = arguments; + var e = o.resolveVariables(s, n), + t = "E"; + for (var r = 0; r < e.length; r++) { + var i = e[r]; + if (typeof i == "object") { + e[r] = ""; + if (i.changeCase && i.local) { + var u = e[r + 1]; + u && + typeof u == "string" && + (i.changeCase == "u" + ? (e[r] = u[0].toUpperCase()) + : (e[r] = u[0].toLowerCase()), + (e[r + 1] = u.substr(1))); + } else i.changeCase && (t = i.changeCase); + } else + t == "U" + ? (e[r] = i.toUpperCase()) + : t == "L" && (e[r] = i.toLowerCase()); + } + return e.join(""); + }); + return (this.variables.__ = null), u; + }), + (this.resolveVariables = function (e, t) { + function o(t) { + var n = e.indexOf(t, r + 1); + n != -1 && (r = n); + } + var n = []; + for (var r = 0; r < e.length; r++) { + var i = e[r]; + if (typeof i == "string") n.push(i); + else { + if (typeof i != "object") continue; + if (i.skip) o(i); + else { + if (i.processed < r) continue; + if (i.text) { + var s = this.getVariableValue(t, i.text); + s && i.fmtString && (s = this.tmStrFormat(s, i)), + (i.processed = r), + i.expectIf == null + ? s && (n.push(s), o(i)) + : s + ? (i.skip = i.elseBranch) + : o(i); + } else + i.tabstopId != null + ? n.push(i) + : i.changeCase != null && n.push(i); + } } + } + return n; + }), + (this.insertSnippetForSelection = function (e, t) { + function f(e) { + var t = []; + for (var n = 0; n < e.length; n++) { + var r = e[n]; + if (typeof r == "object") { + if (a[r.tabstopId]) continue; + var i = e.lastIndexOf(r, n - 1); + r = t[i] || { tabstopId: r.tabstopId }; + } + t[n] = r; + } + return t; + } + var n = e.getCursorPosition(), + r = e.session.getLine(n.row), + i = e.session.getTabString(), + s = r.match(/^\s*/)[0]; + n.column < s.length && (s = s.slice(0, n.column)), (t = t.replace(/\r/g, "")); + var o = this.tokenizeTmSnippet(t); + (o = this.resolveVariables(o, e)), + (o = o.map(function (e) { + return e == "\n" + ? e + s + : typeof e == "string" + ? e.replace(/\t/g, i) + : e; + })); + var u = []; + o.forEach(function (e, t) { + if (typeof e != "object") return; + var n = e.tabstopId, + r = u[n]; + r || ((r = u[n] = []), (r.index = n), (r.value = "")); + if (r.indexOf(e) !== -1) return; + r.push(e); + var i = o.indexOf(e, t + 1); + if (i === -1) return; + var s = o.slice(t + 1, i), + a = s.some(function (e) { + return typeof e == "object"; + }); + a && !r.value + ? (r.value = s) + : s.length && + (!r.value || typeof r.value != "string") && + (r.value = s.join("")); + }), + u.forEach(function (e) { + e.length = 0; + }); + var a = {}; + for (var l = 0; l < o.length; l++) { + var c = o[l]; + if (typeof c != "object") continue; + var p = c.tabstopId, + d = o.indexOf(c, l + 1); + if (a[p]) { + a[p] === c && (a[p] = null); + continue; + } + var v = u[p], + m = typeof v.value == "string" ? [v.value] : f(v.value); + m.unshift(l + 1, Math.max(0, d - l)), + m.push(c), + (a[p] = c), + o.splice.apply(o, m), + v.indexOf(c) === -1 && v.push(c); + } + var g = 0, + y = 0, + b = ""; + o.forEach(function (e) { + if (typeof e == "string") { + var t = e.split("\n"); + t.length > 1 + ? ((y = t[t.length - 1].length), (g += t.length - 1)) + : (y += e.length), + (b += e); + } else + e.start + ? (e.end = { row: g, column: y }) + : (e.start = { row: g, column: y }); + }); + var w = e.getSelectionRange(), + E = e.session.replace(w, b), + S = new h(e), + x = e.inVirtualSelectionMode && e.selection.index; + S.addTabstops(u, w.start, E, x); + }), + (this.insertSnippet = function (e, t) { + var n = this; + if (e.inVirtualSelectionMode) return n.insertSnippetForSelection(e, t); + e.forEachSelection( + function () { + n.insertSnippetForSelection(e, t); + }, + null, + { keepOrder: !0 }, + ), + e.tabstopManager && e.tabstopManager.tabNext(); + }), + (this.$getScope = function (e) { + var t = e.session.$mode.$id || ""; + t = t.split("/").pop(); + if (t === "html" || t === "php") { + t === "php" && !e.session.$mode.inlinePhp && (t = "html"); + var n = e.getCursorPosition(), + r = e.session.getState(n.row); + typeof r == "object" && (r = r[0]), + r.substring && + (r.substring(0, 3) == "js-" + ? (t = "javascript") + : r.substring(0, 4) == "css-" + ? (t = "css") + : r.substring(0, 4) == "php-" && (t = "php")); + } + return t; + }), + (this.getActiveScopes = function (e) { + var t = this.$getScope(e), + n = [t], + r = this.snippetMap; + return ( + r[t] && r[t].includeScopes && n.push.apply(n, r[t].includeScopes), + n.push("_"), + n + ); + }), + (this.expandWithTab = function (e, t) { + var n = this, + r = e.forEachSelection( + function () { + return n.expandSnippetForSelection(e, t); + }, + null, + { keepOrder: !0 }, + ); + return r && e.tabstopManager && e.tabstopManager.tabNext(), r; + }), + (this.expandSnippetForSelection = function (e, t) { + var n = e.getCursorPosition(), + r = e.session.getLine(n.row), + i = r.substring(0, n.column), + s = r.substr(n.column), + o = this.snippetMap, + u; + return ( + this.getActiveScopes(e).some(function (e) { + var t = o[e]; + return t && (u = this.findMatchingSnippet(t, i, s)), !!u; + }, this), + u + ? t && t.dryRun + ? !0 + : (e.session.doc.removeInLine( + n.row, + n.column - u.replaceBefore.length, + n.column + u.replaceAfter.length, + ), + (this.variables.M__ = u.matchBefore), + (this.variables.T__ = u.matchAfter), + this.insertSnippetForSelection(e, u.content), + (this.variables.M__ = this.variables.T__ = null), + !0) + : !1 + ); + }), + (this.findMatchingSnippet = function (e, t, n) { + for (var r = e.length; r--; ) { + var i = e[r]; + if (i.startRe && !i.startRe.test(t)) continue; + if (i.endRe && !i.endRe.test(n)) continue; + if (!i.startRe && !i.endRe) continue; + return ( + (i.matchBefore = i.startRe ? i.startRe.exec(t) : [""]), + (i.matchAfter = i.endRe ? i.endRe.exec(n) : [""]), + (i.replaceBefore = i.triggerRe ? i.triggerRe.exec(t)[0] : ""), + (i.replaceAfter = i.endTriggerRe ? i.endTriggerRe.exec(n)[0] : ""), + i + ); + } + }), + (this.snippetMap = {}), + (this.snippetNameMap = {}), + (this.register = function (e, t) { + function o(e) { + return ( + e && !/^\^?\(.*\)\$?$|^\\b$/.test(e) && (e = "(?:" + e + ")"), e || "" + ); + } + function u(e, t, n) { + return ( + (e = o(e)), + (t = o(t)), + n + ? ((e = t + e), e && e[e.length - 1] != "$" && (e += "$")) + : ((e += t), e && e[0] != "^" && (e = "^" + e)), + new RegExp(e) + ); + } + function a(e) { + e.scope || (e.scope = t || "_"), + (t = e.scope), + n[t] || ((n[t] = []), (r[t] = {})); + var o = r[t]; + if (e.name) { + var a = o[e.name]; + a && i.unregister(a), (o[e.name] = e); + } + n[t].push(e), + e.tabTrigger && + !e.trigger && + (!e.guard && /^\w/.test(e.tabTrigger) && (e.guard = "\\b"), + (e.trigger = s.escapeRegExp(e.tabTrigger))); + if (!e.trigger && !e.guard && !e.endTrigger && !e.endGuard) return; + (e.startRe = u(e.trigger, e.guard, !0)), + (e.triggerRe = new RegExp(e.trigger)), + (e.endRe = u(e.endTrigger, e.endGuard, !0)), + (e.endTriggerRe = new RegExp(e.endTrigger)); + } + var n = this.snippetMap, + r = this.snippetNameMap, + i = this; + e || (e = []), + e && e.content ? a(e) : Array.isArray(e) && e.forEach(a), + this._signal("registerSnippets", { scope: t }); + }), + (this.unregister = function (e, t) { + function i(e) { + var i = r[e.scope || t]; + if (i && i[e.name]) { + delete i[e.name]; + var s = n[e.scope || t], + o = s && s.indexOf(e); + o >= 0 && s.splice(o, 1); + } + } + var n = this.snippetMap, + r = this.snippetNameMap; + e.content ? i(e) : Array.isArray(e) && e.forEach(i); + }), + (this.parseSnippetFile = function (e) { + e = e.replace(/\r/g, ""); + var t = [], + n = {}, + r = /^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm, + i; + while ((i = r.exec(e))) { + if (i[1]) + try { + (n = JSON.parse(i[1])), t.push(n); + } catch (s) {} + if (i[4]) (n.content = i[4].replace(/^\t/gm, "")), t.push(n), (n = {}); + else { + var o = i[2], + u = i[3]; + if (o == "regex") { + var a = /\/((?:[^\/\\]|\\.)*)|$/g; + (n.guard = a.exec(u)[1]), + (n.trigger = a.exec(u)[1]), + (n.endTrigger = a.exec(u)[1]), + (n.endGuard = a.exec(u)[1]); + } else + o == "snippet" + ? ((n.tabTrigger = u.match(/^\S*/)[0]), n.name || (n.name = u)) + : (n[o] = u); + } + } + return t; + }), + (this.getSnippetByName = function (e, t) { + var n = this.snippetNameMap, + r; + return ( + this.getActiveScopes(t).some(function (t) { + var i = n[t]; + return i && (r = i[e]), !!r; + }, this), + r + ); + }); + }).call(c.prototype); + var h = function (e) { + if (e.tabstopManager) return e.tabstopManager; + (e.tabstopManager = this), + (this.$onChange = this.onChange.bind(this)), + (this.$onChangeSelection = s.delayedCall( + this.onChangeSelection.bind(this), + ).schedule), + (this.$onChangeSession = this.onChangeSession.bind(this)), + (this.$onAfterExec = this.onAfterExec.bind(this)), + this.attach(e); + }; + (function () { + (this.attach = function (e) { + (this.index = 0), + (this.ranges = []), + (this.tabstops = []), + (this.$openTabstops = null), + (this.selectedTabstop = null), + (this.editor = e), + this.editor.on("change", this.$onChange), + this.editor.on("changeSelection", this.$onChangeSelection), + this.editor.on("changeSession", this.$onChangeSession), + this.editor.commands.on("afterExec", this.$onAfterExec), + this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler); + }), + (this.detach = function () { + this.tabstops.forEach(this.removeTabstopMarkers, this), + (this.ranges = null), + (this.tabstops = null), + (this.selectedTabstop = null), + this.editor.removeListener("change", this.$onChange), + this.editor.removeListener("changeSelection", this.$onChangeSelection), + this.editor.removeListener("changeSession", this.$onChangeSession), + this.editor.commands.removeListener("afterExec", this.$onAfterExec), + this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler), + (this.editor.tabstopManager = null), + (this.editor = null); + }), + (this.onChange = function (e) { + var t = e, + n = e.action[0] == "r", + r = e.start, + i = e.end, + s = r.row, + o = i.row, + u = o - s, + a = i.column - r.column; + n && ((u = -u), (a = -a)); + if (!this.$inChange && n) { + var f = this.selectedTabstop, + c = + f && + !f.some(function (e) { + return l(e.start, r) <= 0 && l(e.end, i) >= 0; + }); + if (c) return this.detach(); + } + var h = this.ranges; + for (var p = 0; p < h.length; p++) { + var d = h[p]; + if (d.end.row < r.row) continue; + if (n && l(r, d.start) < 0 && l(i, d.end) > 0) { + this.removeRange(d), p--; + continue; + } + d.start.row == s && d.start.column > r.column && (d.start.column += a), + d.end.row == s && d.end.column >= r.column && (d.end.column += a), + d.start.row >= s && (d.start.row += u), + d.end.row >= s && (d.end.row += u), + l(d.start, d.end) > 0 && this.removeRange(d); + } + h.length || this.detach(); + }), + (this.updateLinkedFields = function () { + var e = this.selectedTabstop; + if (!e || !e.hasLinkedRanges) return; + this.$inChange = !0; + var n = this.editor.session, + r = n.getTextRange(e.firstNonLinked); + for (var i = e.length; i--; ) { + var s = e[i]; + if (!s.linked) continue; + var o = t.snippetManager.tmStrFormat(r, s.original); + n.replace(s, o); + } + this.$inChange = !1; + }), + (this.onAfterExec = function (e) { + e.command && !e.command.readOnly && this.updateLinkedFields(); + }), + (this.onChangeSelection = function () { + if (!this.editor) return; + var e = this.editor.selection.lead, + t = this.editor.selection.anchor, + n = this.editor.selection.isEmpty(); + for (var r = this.ranges.length; r--; ) { + if (this.ranges[r].linked) continue; + var i = this.ranges[r].contains(e.row, e.column), + s = n || this.ranges[r].contains(t.row, t.column); + if (i && s) return; + } + this.detach(); + }), + (this.onChangeSession = function () { + this.detach(); + }), + (this.tabNext = function (e) { + var t = this.tabstops.length, + n = this.index + (e || 1); + (n = Math.min(Math.max(n, 1), t)), + n == t && (n = 0), + this.selectTabstop(n), + n === 0 && this.detach(); + }), + (this.selectTabstop = function (e) { + this.$openTabstops = null; + var t = this.tabstops[this.index]; + t && this.addTabstopMarkers(t), + (this.index = e), + (t = this.tabstops[this.index]); + if (!t || !t.length) return; + this.selectedTabstop = t; + if (!this.editor.inVirtualSelectionMode) { + var n = this.editor.multiSelect; + n.toSingleRange(t.firstNonLinked.clone()); + for (var r = t.length; r--; ) { + if (t.hasLinkedRanges && t[r].linked) continue; + n.addRange(t[r].clone(), !0); + } + n.ranges[0] && n.addRange(n.ranges[0].clone()); + } else this.editor.selection.setRange(t.firstNonLinked); + this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler); + }), + (this.addTabstops = function (e, t, n) { + this.$openTabstops || (this.$openTabstops = []); + if (!e[0]) { + var r = o.fromPoints(n, n); + v(r.start, t), v(r.end, t), (e[0] = [r]), (e[0].index = 0); + } + var i = this.index, + s = [i + 1, 0], + u = this.ranges; + e.forEach(function (e, n) { + var r = this.$openTabstops[n] || e; + for (var i = e.length; i--; ) { + var a = e[i], + f = o.fromPoints(a.start, a.end || a.start); + d(f.start, t), + d(f.end, t), + (f.original = a), + (f.tabstop = r), + u.push(f), + r != e ? r.unshift(f) : (r[i] = f), + a.fmtString + ? ((f.linked = !0), (r.hasLinkedRanges = !0)) + : r.firstNonLinked || (r.firstNonLinked = f); + } + r.firstNonLinked || (r.hasLinkedRanges = !1), + r === e && (s.push(r), (this.$openTabstops[n] = r)), + this.addTabstopMarkers(r); + }, this), + s.length > 2 && + (this.tabstops.length && s.push(s.splice(2, 1)[0]), + this.tabstops.splice.apply(this.tabstops, s)); + }), + (this.addTabstopMarkers = function (e) { + var t = this.editor.session; + e.forEach(function (e) { + e.markerId || (e.markerId = t.addMarker(e, "ace_snippet-marker", "text")); + }); + }), + (this.removeTabstopMarkers = function (e) { + var t = this.editor.session; + e.forEach(function (e) { + t.removeMarker(e.markerId), (e.markerId = null); + }); + }), + (this.removeRange = function (e) { + var t = e.tabstop.indexOf(e); + e.tabstop.splice(t, 1), + (t = this.ranges.indexOf(e)), + this.ranges.splice(t, 1), + this.editor.session.removeMarker(e.markerId), + e.tabstop.length || + ((t = this.tabstops.indexOf(e.tabstop)), + t != -1 && this.tabstops.splice(t, 1), + this.tabstops.length || this.detach()); + }), + (this.keyboardHandler = new a()), + this.keyboardHandler.bindKeys({ + Tab: function (e) { + if (t.snippetManager && t.snippetManager.expandWithTab(e)) return; + e.tabstopManager.tabNext(1); + }, + "Shift-Tab": function (e) { + e.tabstopManager.tabNext(-1); + }, + Esc: function (e) { + e.tabstopManager.detach(); + }, + Return: function (e) { + return !1; + }, + }); + }).call(h.prototype); + var p = {}; + (p.onChange = u.prototype.onChange), + (p.setPosition = function (e, t) { + (this.pos.row = e), (this.pos.column = t); + }), + (p.update = function (e, t, n) { + (this.$insertRight = n), (this.pos = e), this.onChange(t); + }); + var d = function (e, t) { + e.row == 0 && (e.column += t.column), (e.row += t.row); + }, + v = function (e, t) { + e.row == t.row && (e.column -= t.column), (e.row -= t.row); + }; + e("./lib/dom").importCssString( + ".ace_snippet-marker { -moz-box-sizing: border-box; box-sizing: border-box; background: rgba(194, 193, 208, 0.09); border: 1px dotted rgba(211, 208, 235, 0.62); position: absolute;}", + ), + (t.snippetManager = new c()); + var m = e("./editor").Editor; + (function () { + (this.insertSnippet = function (e, n) { + return t.snippetManager.insertSnippet(this, e, n); + }), + (this.expandSnippet = function (e) { + return t.snippetManager.expandWithTab(this, e); + }); + }).call(m.prototype); + }, +), + define( + "ace/ext/emmet", + [ + "require", + "exports", + "module", + "ace/keyboard/hash_handler", + "ace/editor", + "ace/snippets", + "ace/range", + "resources", + "resources", + "tabStops", + "resources", + "utils", + "actions", + "ace/config", + "ace/config", + ], + function (e, t, n) { + "use strict"; + function f() {} + var r = e("ace/keyboard/hash_handler").HashHandler, + i = e("ace/editor").Editor, + s = e("ace/snippets").snippetManager, + o = e("ace/range").Range, + u, + a; + f.prototype = { + setupContext: function (e) { + (this.ace = e), + (this.indentation = e.session.getTabString()), + u || (u = window.emmet); + var t = u.resources || u.require("resources"); + t.setVariable("indentation", this.indentation), + (this.$syntax = null), + (this.$syntax = this.getSyntax()); + }, + getSelectionRange: function () { + var e = this.ace.getSelectionRange(), + t = this.ace.session.doc; + return { start: t.positionToIndex(e.start), end: t.positionToIndex(e.end) }; + }, + createSelection: function (e, t) { + var n = this.ace.session.doc; + this.ace.selection.setRange({ + start: n.indexToPosition(e), + end: n.indexToPosition(t), + }); + }, + getCurrentLineRange: function () { + var e = this.ace, + t = e.getCursorPosition().row, + n = e.session.getLine(t).length, + r = e.session.doc.positionToIndex({ row: t, column: 0 }); + return { start: r, end: r + n }; + }, + getCaretPos: function () { + var e = this.ace.getCursorPosition(); + return this.ace.session.doc.positionToIndex(e); + }, + setCaretPos: function (e) { + var t = this.ace.session.doc.indexToPosition(e); + this.ace.selection.moveToPosition(t); + }, + getCurrentLine: function () { + var e = this.ace.getCursorPosition().row; + return this.ace.session.getLine(e); + }, + replaceContent: function (e, t, n, r) { + n == null && (n = t == null ? this.getContent().length : t), + t == null && (t = 0); + var i = this.ace, + u = i.session.doc, + a = o.fromPoints(u.indexToPosition(t), u.indexToPosition(n)); + i.session.remove(a), + (a.end = a.start), + (e = this.$updateTabstops(e)), + s.insertSnippet(i, e); + }, + getContent: function () { + return this.ace.getValue(); + }, + getSyntax: function () { + if (this.$syntax) return this.$syntax; + var e = this.ace.session.$modeId.split("/").pop(); + if (e == "html" || e == "php") { + var t = this.ace.getCursorPosition(), + n = this.ace.session.getState(t.row); + typeof n != "string" && (n = n[0]), + n && + ((n = n.split("-")), + n.length > 1 ? (e = n[0]) : e == "php" && (e = "html")); + } + return e; + }, + getProfileName: function () { + var e = u.resources || u.require("resources"); + switch (this.getSyntax()) { + case "css": + return "css"; + case "xml": + case "xsl": + return "xml"; + case "html": + var t = e.getVariable("profile"); + return ( + t || + (t = + this.ace.session + .getLines(0, 2) + .join("") + .search(/]+XHTML/i) != -1 + ? "xhtml" + : "html"), + t + ); + default: + var n = this.ace.session.$mode; + return (n.emmetConfig && n.emmetConfig.profile) || "xhtml"; + } + }, + prompt: function (e) { + return prompt(e); + }, + getSelection: function () { + return this.ace.session.getTextRange(); + }, + getFilePath: function () { + return ""; + }, + $updateTabstops: function (e) { + var t = 1e3, + n = 0, + r = null, + i = u.tabStops || u.require("tabStops"), + s = u.resources || u.require("resources"), + o = s.getVocabulary("user"), + a = { + tabstop: function (e) { + var s = parseInt(e.group, 10), + o = s === 0; + o ? (s = ++n) : (s += t); + var u = e.placeholder; + u && (u = i.processText(u, a)); + var f = "${" + s + (u ? ":" + u : "") + "}"; + return o && (r = [e.start, f]), f; + }, + escape: function (e) { + return e == "$" ? "\\$" : e == "\\" ? "\\\\" : e; + }, + }; + e = i.processText(e, a); + if (o.variables.insert_final_tabstop && !/\$\{0\}$/.test(e)) e += "${0}"; + else if (r) { + var f = u.utils ? u.utils.common : u.require("utils"); + e = f.replaceSubstring(e, "${0}", r[0], r[1]); + } + return e; + }, + }; + var l = { + expand_abbreviation: { mac: "ctrl+alt+e", win: "alt+e" }, + match_pair_outward: { mac: "ctrl+d", win: "ctrl+," }, + match_pair_inward: { mac: "ctrl+j", win: "ctrl+shift+0" }, + matching_pair: { mac: "ctrl+alt+j", win: "alt+j" }, + next_edit_point: "alt+right", + prev_edit_point: "alt+left", + toggle_comment: { mac: "command+/", win: "ctrl+/" }, + split_join_tag: { mac: "shift+command+'", win: "shift+ctrl+`" }, + remove_tag: { mac: "command+'", win: "shift+ctrl+;" }, + evaluate_math_expression: { mac: "shift+command+y", win: "shift+ctrl+y" }, + increment_number_by_1: "ctrl+up", + decrement_number_by_1: "ctrl+down", + increment_number_by_01: "alt+up", + decrement_number_by_01: "alt+down", + increment_number_by_10: { mac: "alt+command+up", win: "shift+alt+up" }, + decrement_number_by_10: { mac: "alt+command+down", win: "shift+alt+down" }, + select_next_item: { mac: "shift+command+.", win: "shift+ctrl+." }, + select_previous_item: { mac: "shift+command+,", win: "shift+ctrl+," }, + reflect_css_value: { mac: "shift+command+r", win: "shift+ctrl+r" }, + encode_decode_data_url: { mac: "shift+ctrl+d", win: "ctrl+'" }, + expand_abbreviation_with_tab: "Tab", + wrap_with_abbreviation: { mac: "shift+ctrl+a", win: "shift+ctrl+a" }, + }, + c = new f(); + (t.commands = new r()), + (t.runEmmetCommand = function d(e) { + try { + c.setupContext(e); + var n = u.actions || u.require("actions"); + if (this.action == "expand_abbreviation_with_tab") { + if (!e.selection.isEmpty()) return !1; + var r = e.selection.lead, + i = e.session.getTokenAt(r.row, r.column); + if (i && /\btag\b/.test(i.type)) return !1; + } + if (this.action == "wrap_with_abbreviation") + return setTimeout(function () { + n.run("wrap_with_abbreviation", c); + }, 0); + var s = n.run(this.action, c); + } catch (o) { + if (!u) return t.load(d.bind(this, e)), !0; + e._signal("changeStatus", typeof o == "string" ? o : o.message), + console.log(o), + (s = !1); + } + return s; + }); + for (var h in l) + t.commands.addCommand({ + name: "emmet:" + h, + action: h, + bindKey: l[h], + exec: t.runEmmetCommand, + multiSelectAction: "forEach", + }); + (t.updateCommands = function (e, n) { + n + ? e.keyBinding.addKeyboardHandler(t.commands) + : e.keyBinding.removeKeyboardHandler(t.commands); + }), + (t.isSupportedMode = function (e) { + if (!e) return !1; + if (e.emmetConfig) return !0; + var t = e.$id || e; + return /css|less|scss|sass|stylus|html|php|twig|ejs|handlebars/.test(t); + }), + (t.isAvailable = function (e, n) { + if (/(evaluate_math_expression|expand_abbreviation)$/.test(n)) return !0; + var r = e.session.$mode, + i = t.isSupportedMode(r); + if (i && r.$modes) + try { + c.setupContext(e), /js|php/.test(c.getSyntax()) && (i = !1); + } catch (s) {} + return i; + }); + var p = function (e, n) { + var r = n; + if (!r) return; + var i = t.isSupportedMode(r.session.$mode); + e.enableEmmet === !1 && (i = !1), i && t.load(), t.updateCommands(r, i); + }; + (t.load = function (t) { + typeof a == "string" && + e("ace/config").loadModule(a, function () { + (a = null), t && t(); }); - })(); - \ No newline at end of file + }), + (t.AceEmmetEditor = f), + e("ace/config").defineOptions(i.prototype, "editor", { + enableEmmet: { + set: function (e) { + this[e ? "on" : "removeListener"]("changeMode", p), + p({ enableEmmet: !!e }, this); + }, + value: !0, + }, + }), + (t.setCore = function (e) { + typeof e == "string" ? (a = e) : (u = e); + }); + }, + ); +(function () { + window.require(["ace/ext/emmet"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/ext-error_marker.js b/web/static/ace/ext-error_marker.js index 87abca92e..0aac48166 100644 --- a/web/static/ace/ext-error_marker.js +++ b/web/static/ace/ext-error_marker.js @@ -1,9 +1,7 @@ -; - (function() { - window.require(["ace/ext/error_marker"], function(m) { - if (typeof module == "object" && typeof exports == "object" && module) { - module.exports = m; - } - }); - })(); - \ No newline at end of file +(function () { + window.require(["ace/ext/error_marker"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/ext-keybinding_menu.js b/web/static/ace/ext-keybinding_menu.js index 9fb56e34f..e23c45638 100644 --- a/web/static/ace/ext-keybinding_menu.js +++ b/web/static/ace/ext-keybinding_menu.js @@ -1,9 +1,140 @@ -define("ace/ext/menu_tools/overlay_page",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";var r=e("../../lib/dom"),i="#ace_settingsmenu, #kbshortcutmenu {background-color: #F7F7F7;color: black;box-shadow: -5px 4px 5px rgba(126, 126, 126, 0.55);padding: 1em 0.5em 2em 1em;overflow: auto;position: absolute;margin: 0;bottom: 0;right: 0;top: 0;z-index: 9991;cursor: default;}.ace_dark #ace_settingsmenu, .ace_dark #kbshortcutmenu {box-shadow: -20px 10px 25px rgba(126, 126, 126, 0.25);background-color: rgba(255, 255, 255, 0.6);color: black;}.ace_optionsMenuEntry:hover {background-color: rgba(100, 100, 100, 0.1);transition: all 0.3s}.ace_closeButton {background: rgba(245, 146, 146, 0.5);border: 1px solid #F48A8A;border-radius: 50%;padding: 7px;position: absolute;right: -8px;top: -8px;z-index: 100000;}.ace_closeButton{background: rgba(245, 146, 146, 0.9);}.ace_optionsMenuKey {color: darkslateblue;font-weight: bold;}.ace_optionsMenuCommand {color: darkcyan;font-weight: normal;}.ace_optionsMenuEntry input, .ace_optionsMenuEntry button {vertical-align: middle;}.ace_optionsMenuEntry button[ace_selected_button=true] {background: #e7e7e7;box-shadow: 1px 0px 2px 0px #adadad inset;border-color: #adadad;}.ace_optionsMenuEntry button {background: white;border: 1px solid lightgray;margin: 0px;}.ace_optionsMenuEntry button:hover{background: #f0f0f0;}";r.importCssString(i),n.exports.overlayPage=function(t,n,i,s,o,u){function l(e){e.keyCode===27&&a.click()}i=i?"top: "+i+";":"",o=o?"bottom: "+o+";":"",s=s?"right: "+s+";":"",u=u?"left: "+u+";":"";var a=document.createElement("div"),f=document.createElement("div");a.style.cssText="margin: 0; padding: 0; position: fixed; top:0; bottom:0; left:0; right:0;z-index: 9990; background-color: rgba(0, 0, 0, 0.3);",a.addEventListener("click",function(){document.removeEventListener("keydown",l),a.parentNode.removeChild(a),t.focus(),a=null}),document.addEventListener("keydown",l),f.style.cssText=i+s+o+u,f.addEventListener("click",function(e){e.stopPropagation()});var c=r.createElement("div");c.style.position="relative";var h=r.createElement("div");h.className="ace_closeButton",h.addEventListener("click",function(){a.click()}),c.appendChild(h),f.appendChild(c),f.appendChild(n),a.appendChild(f),document.body.appendChild(a),t.blur()}}),define("ace/ext/menu_tools/get_editor_keyboard_shortcuts",["require","exports","module","ace/lib/keys"],function(e,t,n){"use strict";var r=e("../../lib/keys");n.exports.getEditorKeybordShortcuts=function(e){var t=r.KEY_MODS,n=[],i={};return e.keyBinding.$handlers.forEach(function(e){var t=e.commandKeyBinding;for(var r in t){var s=r.replace(/(^|-)\w/g,function(e){return e.toUpperCase()}),o=t[r];Array.isArray(o)||(o=[o]),o.forEach(function(e){typeof e!="string"&&(e=e.name),i[e]?i[e].key+="|"+s:(i[e]={key:s,command:e},n.push(i[e]))})}}),n}}),define("ace/ext/keybinding_menu",["require","exports","module","ace/editor","ace/ext/menu_tools/overlay_page","ace/ext/menu_tools/get_editor_keyboard_shortcuts"],function(e,t,n){"use strict";function i(t){if(!document.getElementById("kbshortcutmenu")){var n=e("./menu_tools/overlay_page").overlayPage,r=e("./menu_tools/get_editor_keyboard_shortcuts").getEditorKeybordShortcuts,i=r(t),s=document.createElement("div"),o=i.reduce(function(e,t){return e+'
'+t.command+" : "+''+t.key+"
"},"");s.id="kbshortcutmenu",s.innerHTML="

Keyboard Shortcuts

"+o+"",n(t,s,"0","0","0",null)}}var r=e("ace/editor").Editor;n.exports.init=function(e){r.prototype.showKeyboardShortcuts=function(){i(this)},e.commands.addCommands([{name:"showKeyboardShortcuts",bindKey:{win:"Ctrl-Alt-h",mac:"Command-Alt-h"},exec:function(e,t){e.showKeyboardShortcuts()}}])}}); - (function() { - window.require(["ace/ext/keybinding_menu"], function(m) { - if (typeof module == "object" && typeof exports == "object" && module) { - module.exports = m; - } +define( + "ace/ext/menu_tools/overlay_page", + ["require", "exports", "module", "ace/lib/dom"], + function (e, t, n) { + "use strict"; + var r = e("../../lib/dom"), + i = + "#ace_settingsmenu, #kbshortcutmenu {background-color: #F7F7F7;color: black;box-shadow: -5px 4px 5px rgba(126, 126, 126, 0.55);padding: 1em 0.5em 2em 1em;overflow: auto;position: absolute;margin: 0;bottom: 0;right: 0;top: 0;z-index: 9991;cursor: default;}.ace_dark #ace_settingsmenu, .ace_dark #kbshortcutmenu {box-shadow: -20px 10px 25px rgba(126, 126, 126, 0.25);background-color: rgba(255, 255, 255, 0.6);color: black;}.ace_optionsMenuEntry:hover {background-color: rgba(100, 100, 100, 0.1);transition: all 0.3s}.ace_closeButton {background: rgba(245, 146, 146, 0.5);border: 1px solid #F48A8A;border-radius: 50%;padding: 7px;position: absolute;right: -8px;top: -8px;z-index: 100000;}.ace_closeButton{background: rgba(245, 146, 146, 0.9);}.ace_optionsMenuKey {color: darkslateblue;font-weight: bold;}.ace_optionsMenuCommand {color: darkcyan;font-weight: normal;}.ace_optionsMenuEntry input, .ace_optionsMenuEntry button {vertical-align: middle;}.ace_optionsMenuEntry button[ace_selected_button=true] {background: #e7e7e7;box-shadow: 1px 0px 2px 0px #adadad inset;border-color: #adadad;}.ace_optionsMenuEntry button {background: white;border: 1px solid lightgray;margin: 0px;}.ace_optionsMenuEntry button:hover{background: #f0f0f0;}"; + r.importCssString(i), + (n.exports.overlayPage = function (t, n, i, s, o, u) { + function l(e) { + e.keyCode === 27 && a.click(); + } + (i = i ? "top: " + i + ";" : ""), + (o = o ? "bottom: " + o + ";" : ""), + (s = s ? "right: " + s + ";" : ""), + (u = u ? "left: " + u + ";" : ""); + var a = document.createElement("div"), + f = document.createElement("div"); + (a.style.cssText = + "margin: 0; padding: 0; position: fixed; top:0; bottom:0; left:0; right:0;z-index: 9990; background-color: rgba(0, 0, 0, 0.3);"), + a.addEventListener("click", function () { + document.removeEventListener("keydown", l), + a.parentNode.removeChild(a), + t.focus(), + (a = null); + }), + document.addEventListener("keydown", l), + (f.style.cssText = i + s + o + u), + f.addEventListener("click", function (e) { + e.stopPropagation(); }); - })(); - \ No newline at end of file + var c = r.createElement("div"); + c.style.position = "relative"; + var h = r.createElement("div"); + (h.className = "ace_closeButton"), + h.addEventListener("click", function () { + a.click(); + }), + c.appendChild(h), + f.appendChild(c), + f.appendChild(n), + a.appendChild(f), + document.body.appendChild(a), + t.blur(); + }); + }, +), + define( + "ace/ext/menu_tools/get_editor_keyboard_shortcuts", + ["require", "exports", "module", "ace/lib/keys"], + function (e, t, n) { + "use strict"; + var r = e("../../lib/keys"); + n.exports.getEditorKeybordShortcuts = function (e) { + var t = r.KEY_MODS, + n = [], + i = {}; + return ( + e.keyBinding.$handlers.forEach(function (e) { + var t = e.commandKeyBinding; + for (var r in t) { + var s = r.replace(/(^|-)\w/g, function (e) { + return e.toUpperCase(); + }), + o = t[r]; + Array.isArray(o) || (o = [o]), + o.forEach(function (e) { + typeof e != "string" && (e = e.name), + i[e] + ? (i[e].key += "|" + s) + : ((i[e] = { key: s, command: e }), n.push(i[e])); + }); + } + }), + n + ); + }; + }, + ), + define( + "ace/ext/keybinding_menu", + [ + "require", + "exports", + "module", + "ace/editor", + "ace/ext/menu_tools/overlay_page", + "ace/ext/menu_tools/get_editor_keyboard_shortcuts", + ], + function (e, t, n) { + "use strict"; + function i(t) { + if (!document.getElementById("kbshortcutmenu")) { + var n = e("./menu_tools/overlay_page").overlayPage, + r = e( + "./menu_tools/get_editor_keyboard_shortcuts", + ).getEditorKeybordShortcuts, + i = r(t), + s = document.createElement("div"), + o = i.reduce(function (e, t) { + return ( + e + + '
' + + t.command + + " : " + + '' + + t.key + + "
" + ); + }, ""); + (s.id = "kbshortcutmenu"), + (s.innerHTML = "

Keyboard Shortcuts

" + o + ""), + n(t, s, "0", "0", "0", null); + } + } + var r = e("ace/editor").Editor; + n.exports.init = function (e) { + (r.prototype.showKeyboardShortcuts = function () { + i(this); + }), + e.commands.addCommands([ + { + name: "showKeyboardShortcuts", + bindKey: { win: "Ctrl-Alt-h", mac: "Command-Alt-h" }, + exec: function (e, t) { + e.showKeyboardShortcuts(); + }, + }, + ]); + }; + }, + ); +(function () { + window.require(["ace/ext/keybinding_menu"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/ext-language_tools.js b/web/static/ace/ext-language_tools.js index 6ef038b54..73db3d7c6 100644 --- a/web/static/ace/ext-language_tools.js +++ b/web/static/ace/ext-language_tools.js @@ -1,9 +1,1689 @@ -define("ace/snippets",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/lib/lang","ace/range","ace/anchor","ace/keyboard/hash_handler","ace/tokenizer","ace/lib/dom","ace/editor"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./lib/event_emitter").EventEmitter,s=e("./lib/lang"),o=e("./range").Range,u=e("./anchor").Anchor,a=e("./keyboard/hash_handler").HashHandler,f=e("./tokenizer").Tokenizer,l=o.comparePoints,c=function(){this.snippetMap={},this.snippetNameMap={}};(function(){r.implement(this,i),this.getTokenizer=function(){function e(e,t,n){return e=e.substr(1),/^\d+$/.test(e)&&!n.inFormatString?[{tabstopId:parseInt(e,10)}]:[{text:e}]}function t(e){return"(?:[^\\\\"+e+"]|\\\\.)"}return c.$tokenizer=new f({start:[{regex:/:/,onMatch:function(e,t,n){return n.length&&n[0].expectIf?(n[0].expectIf=!1,n[0].elseBranch=n[0],[n[0]]):":"}},{regex:/\\./,onMatch:function(e,t,n){var r=e[1];return r=="}"&&n.length?e=r:"`$\\".indexOf(r)!=-1?e=r:n.inFormatString&&(r=="n"?e="\n":r=="t"?e="\n":"ulULE".indexOf(r)!=-1&&(e={changeCase:r,local:r>"a"})),[e]}},{regex:/}/,onMatch:function(e,t,n){return[n.length?n.shift():e]}},{regex:/\$(?:\d+|\w+)/,onMatch:e},{regex:/\$\{[\dA-Z_a-z]+/,onMatch:function(t,n,r){var i=e(t.substr(1),n,r);return r.unshift(i[0]),i},next:"snippetVar"},{regex:/\n/,token:"newline",merge:!1}],snippetVar:[{regex:"\\|"+t("\\|")+"*\\|",onMatch:function(e,t,n){n[0].choices=e.slice(1,-1).split(",")},next:"start"},{regex:"/("+t("/")+"+)/(?:("+t("/")+"*)/)(\\w*):?",onMatch:function(e,t,n){var r=n[0];return r.fmtString=e,e=this.splitRegex.exec(e),r.guard=e[1],r.fmt=e[2],r.flag=e[3],""},next:"start"},{regex:"`"+t("`")+"*`",onMatch:function(e,t,n){return n[0].code=e.splice(1,-1),""},next:"start"},{regex:"\\?",onMatch:function(e,t,n){n[0]&&(n[0].expectIf=!0)},next:"start"},{regex:"([^:}\\\\]|\\\\.)*:?",token:"",next:"start"}],formatString:[{regex:"/("+t("/")+"+)/",token:"regex"},{regex:"",onMatch:function(e,t,n){n.inFormatString=!0},next:"start"}]}),c.prototype.getTokenizer=function(){return c.$tokenizer},c.$tokenizer},this.tokenizeTmSnippet=function(e,t){return this.getTokenizer().getLineTokens(e,t).tokens.map(function(e){return e.value||e})},this.$getDefaultValue=function(e,t){if(/^[A-Z]\d+$/.test(t)){var n=t.substr(1);return(this.variables[t[0]+"__"]||{})[n]}if(/^\d+$/.test(t))return(this.variables.__||{})[t];t=t.replace(/^TM_/,"");if(!e)return;var r=e.session;switch(t){case"CURRENT_WORD":var i=r.getWordRange();case"SELECTION":case"SELECTED_TEXT":return r.getTextRange(i);case"CURRENT_LINE":return r.getLine(e.getCursorPosition().row);case"PREV_LINE":return r.getLine(e.getCursorPosition().row-1);case"LINE_INDEX":return e.getCursorPosition().column;case"LINE_NUMBER":return e.getCursorPosition().row+1;case"SOFT_TABS":return r.getUseSoftTabs()?"YES":"NO";case"TAB_SIZE":return r.getTabSize();case"FILENAME":case"FILEPATH":return"";case"FULLNAME":return"Ace"}},this.variables={},this.getVariableValue=function(e,t){return this.variables.hasOwnProperty(t)?this.variables[t](e,t)||"":this.$getDefaultValue(e,t)||""},this.tmStrFormat=function(e,t,n){var r=t.flag||"",i=t.guard;i=new RegExp(i,r.replace(/[^gi]/,""));var s=this.tokenizeTmSnippet(t.fmt,"formatString"),o=this,u=e.replace(i,function(){o.variables.__=arguments;var e=o.resolveVariables(s,n),t="E";for(var r=0;r1?(y=t[t.length-1].length,g+=t.length-1):y+=e.length,b+=e}else e.start?e.end={row:g,column:y}:e.start={row:g,column:y}});var w=e.getSelectionRange(),E=e.session.replace(w,b),S=new h(e),x=e.inVirtualSelectionMode&&e.selection.index;S.addTabstops(u,w.start,E,x)},this.insertSnippet=function(e,t){var n=this;if(e.inVirtualSelectionMode)return n.insertSnippetForSelection(e,t);e.forEachSelection(function(){n.insertSnippetForSelection(e,t)},null,{keepOrder:!0}),e.tabstopManager&&e.tabstopManager.tabNext()},this.$getScope=function(e){var t=e.session.$mode.$id||"";t=t.split("/").pop();if(t==="html"||t==="php"){t==="php"&&!e.session.$mode.inlinePhp&&(t="html");var n=e.getCursorPosition(),r=e.session.getState(n.row);typeof r=="object"&&(r=r[0]),r.substring&&(r.substring(0,3)=="js-"?t="javascript":r.substring(0,4)=="css-"?t="css":r.substring(0,4)=="php-"&&(t="php"))}return t},this.getActiveScopes=function(e){var t=this.$getScope(e),n=[t],r=this.snippetMap;return r[t]&&r[t].includeScopes&&n.push.apply(n,r[t].includeScopes),n.push("_"),n},this.expandWithTab=function(e,t){var n=this,r=e.forEachSelection(function(){return n.expandSnippetForSelection(e,t)},null,{keepOrder:!0});return r&&e.tabstopManager&&e.tabstopManager.tabNext(),r},this.expandSnippetForSelection=function(e,t){var n=e.getCursorPosition(),r=e.session.getLine(n.row),i=r.substring(0,n.column),s=r.substr(n.column),o=this.snippetMap,u;return this.getActiveScopes(e).some(function(e){var t=o[e];return t&&(u=this.findMatchingSnippet(t,i,s)),!!u},this),u?t&&t.dryRun?!0:(e.session.doc.removeInLine(n.row,n.column-u.replaceBefore.length,n.column+u.replaceAfter.length),this.variables.M__=u.matchBefore,this.variables.T__=u.matchAfter,this.insertSnippetForSelection(e,u.content),this.variables.M__=this.variables.T__=null,!0):!1},this.findMatchingSnippet=function(e,t,n){for(var r=e.length;r--;){var i=e[r];if(i.startRe&&!i.startRe.test(t))continue;if(i.endRe&&!i.endRe.test(n))continue;if(!i.startRe&&!i.endRe)continue;return i.matchBefore=i.startRe?i.startRe.exec(t):[""],i.matchAfter=i.endRe?i.endRe.exec(n):[""],i.replaceBefore=i.triggerRe?i.triggerRe.exec(t)[0]:"",i.replaceAfter=i.endTriggerRe?i.endTriggerRe.exec(n)[0]:"",i}},this.snippetMap={},this.snippetNameMap={},this.register=function(e,t){function o(e){return e&&!/^\^?\(.*\)\$?$|^\\b$/.test(e)&&(e="(?:"+e+")"),e||""}function u(e,t,n){return e=o(e),t=o(t),n?(e=t+e,e&&e[e.length-1]!="$"&&(e+="$")):(e+=t,e&&e[0]!="^"&&(e="^"+e)),new RegExp(e)}function a(e){e.scope||(e.scope=t||"_"),t=e.scope,n[t]||(n[t]=[],r[t]={});var o=r[t];if(e.name){var a=o[e.name];a&&i.unregister(a),o[e.name]=e}n[t].push(e),e.tabTrigger&&!e.trigger&&(!e.guard&&/^\w/.test(e.tabTrigger)&&(e.guard="\\b"),e.trigger=s.escapeRegExp(e.tabTrigger));if(!e.trigger&&!e.guard&&!e.endTrigger&&!e.endGuard)return;e.startRe=u(e.trigger,e.guard,!0),e.triggerRe=new RegExp(e.trigger),e.endRe=u(e.endTrigger,e.endGuard,!0),e.endTriggerRe=new RegExp(e.endTrigger)}var n=this.snippetMap,r=this.snippetNameMap,i=this;e||(e=[]),e&&e.content?a(e):Array.isArray(e)&&e.forEach(a),this._signal("registerSnippets",{scope:t})},this.unregister=function(e,t){function i(e){var i=r[e.scope||t];if(i&&i[e.name]){delete i[e.name];var s=n[e.scope||t],o=s&&s.indexOf(e);o>=0&&s.splice(o,1)}}var n=this.snippetMap,r=this.snippetNameMap;e.content?i(e):Array.isArray(e)&&e.forEach(i)},this.parseSnippetFile=function(e){e=e.replace(/\r/g,"");var t=[],n={},r=/^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm,i;while(i=r.exec(e)){if(i[1])try{n=JSON.parse(i[1]),t.push(n)}catch(s){}if(i[4])n.content=i[4].replace(/^\t/gm,""),t.push(n),n={};else{var o=i[2],u=i[3];if(o=="regex"){var a=/\/((?:[^\/\\]|\\.)*)|$/g;n.guard=a.exec(u)[1],n.trigger=a.exec(u)[1],n.endTrigger=a.exec(u)[1],n.endGuard=a.exec(u)[1]}else o=="snippet"?(n.tabTrigger=u.match(/^\S*/)[0],n.name||(n.name=u)):n[o]=u}}return t},this.getSnippetByName=function(e,t){var n=this.snippetNameMap,r;return this.getActiveScopes(t).some(function(t){var i=n[t];return i&&(r=i[e]),!!r},this),r}}).call(c.prototype);var h=function(e){if(e.tabstopManager)return e.tabstopManager;e.tabstopManager=this,this.$onChange=this.onChange.bind(this),this.$onChangeSelection=s.delayedCall(this.onChangeSelection.bind(this)).schedule,this.$onChangeSession=this.onChangeSession.bind(this),this.$onAfterExec=this.onAfterExec.bind(this),this.attach(e)};(function(){this.attach=function(e){this.index=0,this.ranges=[],this.tabstops=[],this.$openTabstops=null,this.selectedTabstop=null,this.editor=e,this.editor.on("change",this.$onChange),this.editor.on("changeSelection",this.$onChangeSelection),this.editor.on("changeSession",this.$onChangeSession),this.editor.commands.on("afterExec",this.$onAfterExec),this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler)},this.detach=function(){this.tabstops.forEach(this.removeTabstopMarkers,this),this.ranges=null,this.tabstops=null,this.selectedTabstop=null,this.editor.removeListener("change",this.$onChange),this.editor.removeListener("changeSelection",this.$onChangeSelection),this.editor.removeListener("changeSession",this.$onChangeSession),this.editor.commands.removeListener("afterExec",this.$onAfterExec),this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler),this.editor.tabstopManager=null,this.editor=null},this.onChange=function(e){var t=e,n=e.action[0]=="r",r=e.start,i=e.end,s=r.row,o=i.row,u=o-s,a=i.column-r.column;n&&(u=-u,a=-a);if(!this.$inChange&&n){var f=this.selectedTabstop,c=f&&!f.some(function(e){return l(e.start,r)<=0&&l(e.end,i)>=0});if(c)return this.detach()}var h=this.ranges;for(var p=0;p0){this.removeRange(d),p--;continue}d.start.row==s&&d.start.column>r.column&&(d.start.column+=a),d.end.row==s&&d.end.column>=r.column&&(d.end.column+=a),d.start.row>=s&&(d.start.row+=u),d.end.row>=s&&(d.end.row+=u),l(d.start,d.end)>0&&this.removeRange(d)}h.length||this.detach()},this.updateLinkedFields=function(){var e=this.selectedTabstop;if(!e||!e.hasLinkedRanges)return;this.$inChange=!0;var n=this.editor.session,r=n.getTextRange(e.firstNonLinked);for(var i=e.length;i--;){var s=e[i];if(!s.linked)continue;var o=t.snippetManager.tmStrFormat(r,s.original);n.replace(s,o)}this.$inChange=!1},this.onAfterExec=function(e){e.command&&!e.command.readOnly&&this.updateLinkedFields()},this.onChangeSelection=function(){if(!this.editor)return;var e=this.editor.selection.lead,t=this.editor.selection.anchor,n=this.editor.selection.isEmpty();for(var r=this.ranges.length;r--;){if(this.ranges[r].linked)continue;var i=this.ranges[r].contains(e.row,e.column),s=n||this.ranges[r].contains(t.row,t.column);if(i&&s)return}this.detach()},this.onChangeSession=function(){this.detach()},this.tabNext=function(e){var t=this.tabstops.length,n=this.index+(e||1);n=Math.min(Math.max(n,1),t),n==t&&(n=0),this.selectTabstop(n),n===0&&this.detach()},this.selectTabstop=function(e){this.$openTabstops=null;var t=this.tabstops[this.index];t&&this.addTabstopMarkers(t),this.index=e,t=this.tabstops[this.index];if(!t||!t.length)return;this.selectedTabstop=t;if(!this.editor.inVirtualSelectionMode){var n=this.editor.multiSelect;n.toSingleRange(t.firstNonLinked.clone());for(var r=t.length;r--;){if(t.hasLinkedRanges&&t[r].linked)continue;n.addRange(t[r].clone(),!0)}n.ranges[0]&&n.addRange(n.ranges[0].clone())}else this.editor.selection.setRange(t.firstNonLinked);this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler)},this.addTabstops=function(e,t,n){this.$openTabstops||(this.$openTabstops=[]);if(!e[0]){var r=o.fromPoints(n,n);v(r.start,t),v(r.end,t),e[0]=[r],e[0].index=0}var i=this.index,s=[i+1,0],u=this.ranges;e.forEach(function(e,n){var r=this.$openTabstops[n]||e;for(var i=e.length;i--;){var a=e[i],f=o.fromPoints(a.start,a.end||a.start);d(f.start,t),d(f.end,t),f.original=a,f.tabstop=r,u.push(f),r!=e?r.unshift(f):r[i]=f,a.fmtString?(f.linked=!0,r.hasLinkedRanges=!0):r.firstNonLinked||(r.firstNonLinked=f)}r.firstNonLinked||(r.hasLinkedRanges=!1),r===e&&(s.push(r),this.$openTabstops[n]=r),this.addTabstopMarkers(r)},this),s.length>2&&(this.tabstops.length&&s.push(s.splice(2,1)[0]),this.tabstops.splice.apply(this.tabstops,s))},this.addTabstopMarkers=function(e){var t=this.editor.session;e.forEach(function(e){e.markerId||(e.markerId=t.addMarker(e,"ace_snippet-marker","text"))})},this.removeTabstopMarkers=function(e){var t=this.editor.session;e.forEach(function(e){t.removeMarker(e.markerId),e.markerId=null})},this.removeRange=function(e){var t=e.tabstop.indexOf(e);e.tabstop.splice(t,1),t=this.ranges.indexOf(e),this.ranges.splice(t,1),this.editor.session.removeMarker(e.markerId),e.tabstop.length||(t=this.tabstops.indexOf(e.tabstop),t!=-1&&this.tabstops.splice(t,1),this.tabstops.length||this.detach())},this.keyboardHandler=new a,this.keyboardHandler.bindKeys({Tab:function(e){if(t.snippetManager&&t.snippetManager.expandWithTab(e))return;e.tabstopManager.tabNext(1)},"Shift-Tab":function(e){e.tabstopManager.tabNext(-1)},Esc:function(e){e.tabstopManager.detach()},Return:function(e){return!1}})}).call(h.prototype);var p={};p.onChange=u.prototype.onChange,p.setPosition=function(e,t){this.pos.row=e,this.pos.column=t},p.update=function(e,t,n){this.$insertRight=n,this.pos=e,this.onChange(t)};var d=function(e,t){e.row==0&&(e.column+=t.column),e.row+=t.row},v=function(e,t){e.row==t.row&&(e.column-=t.column),e.row-=t.row};e("./lib/dom").importCssString(".ace_snippet-marker { -moz-box-sizing: border-box; box-sizing: border-box; background: rgba(194, 193, 208, 0.09); border: 1px dotted rgba(211, 208, 235, 0.62); position: absolute;}"),t.snippetManager=new c;var m=e("./editor").Editor;(function(){this.insertSnippet=function(e,n){return t.snippetManager.insertSnippet(this,e,n)},this.expandSnippet=function(e){return t.snippetManager.expandWithTab(this,e)}}).call(m.prototype)}),define("ace/autocomplete/popup",["require","exports","module","ace/virtual_renderer","ace/editor","ace/range","ace/lib/event","ace/lib/lang","ace/lib/dom"],function(e,t,n){"use strict";var r=e("../virtual_renderer").VirtualRenderer,i=e("../editor").Editor,s=e("../range").Range,o=e("../lib/event"),u=e("../lib/lang"),a=e("../lib/dom"),f=function(e){var t=new r(e);t.$maxLines=4;var n=new i(t);return n.setHighlightActiveLine(!1),n.setShowPrintMargin(!1),n.renderer.setShowGutter(!1),n.renderer.setHighlightGutterLine(!1),n.$mouseHandler.$focusTimeout=0,n.$highlightTagPending=!0,n},l=function(e){var t=a.createElement("div"),n=new f(t);e&&e.appendChild(t),t.style.display="none",n.renderer.content.style.cursor="default",n.renderer.setStyle("ace_autocomplete"),n.setOption("displayIndentGuides",!1),n.setOption("dragDelay",150);var r=function(){};n.focus=r,n.$isFocused=!0,n.renderer.$cursorLayer.restartTimer=r,n.renderer.$cursorLayer.element.style.opacity=0,n.renderer.$maxLines=8,n.renderer.$keepTextAreaAtCursor=!1,n.setHighlightActiveLine(!1),n.session.highlight(""),n.session.$searchHighlight.clazz="ace_highlight-marker",n.on("mousedown",function(e){var t=e.getDocumentPosition();n.selection.moveToPosition(t),c.start.row=c.end.row=t.row,e.stop()});var i,l=new s(-1,0,-1,Infinity),c=new s(-1,0,-1,Infinity);c.id=n.session.addMarker(c,"ace_active-line","fullLine"),n.setSelectOnHover=function(e){e?l.id&&(n.session.removeMarker(l.id),l.id=null):l.id=n.session.addMarker(l,"ace_line-hover","fullLine")},n.setSelectOnHover(!1),n.on("mousemove",function(e){if(!i){i=e;return}if(i.x==e.x&&i.y==e.y)return;i=e,i.scrollTop=n.renderer.scrollTop;var t=i.getDocumentPosition().row;l.start.row!=t&&(l.id||n.setRow(t),p(t))}),n.renderer.on("beforeRender",function(){if(i&&l.start.row!=-1){i.$pos=null;var e=i.getDocumentPosition().row;l.id||n.setRow(e),p(e,!0)}}),n.renderer.on("afterRender",function(){var e=n.getRow(),t=n.renderer.$textLayer,r=t.element.childNodes[e-t.config.firstRow];if(r==t.selectedNode)return;t.selectedNode&&a.removeCssClass(t.selectedNode,"ace_selected"),t.selectedNode=r,r&&a.addCssClass(r,"ace_selected")});var h=function(){p(-1)},p=function(e,t){e!==l.start.row&&(l.start.row=l.end.row=e,t||n.session._emit("changeBackMarker"),n._emit("changeHoverMarker"))};n.getHoveredRow=function(){return l.start.row},o.addListener(n.container,"mouseout",h),n.on("hide",h),n.on("changeSelection",h),n.session.doc.getLength=function(){return n.data.length},n.session.doc.getLine=function(e){var t=n.data[e];return typeof t=="string"?t:t&&t.value||""};var d=n.session.bgTokenizer;return d.$tokenizeRow=function(e){function s(e,n){e&&r.push({type:(t.className||"")+(n||""),value:e})}var t=n.data[e],r=[];if(!t)return r;typeof t=="string"&&(t={value:t});var i=t.caption||t.value||t.name,o=i.toLowerCase(),u=(n.filterText||"").toLowerCase(),a=0,f=0;for(var l=0;l<=u.length;l++)if(l!=f&&(t.matchMask&1<o/2&&!r;c&&l+t+f>o?(a.$maxPixelHeight=l-2*this.$borderSize,s.style.top="",s.style.bottom=o-l+"px",n.isTopdown=!1):(l+=t,a.$maxPixelHeight=o-l-.2*t,s.style.top=l+"px",s.style.bottom="",n.isTopdown=!0),s.style.display="",this.renderer.$textLayer.checkForSizeChanges();var h=e.left;h+s.offsetWidth>u&&(h=u-s.offsetWidth),s.style.left=h+"px",this._signal("show"),i=null,n.isOpen=!0},n.getTextLeftOffset=function(){return this.$borderSize+this.renderer.$padding+this.$imageSize},n.$imageSize=0,n.$borderSize=1,n};a.importCssString(".ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line { background-color: #CAD6FA; z-index: 1;}.ace_dark.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line { background-color: #3a674e;}.ace_editor.ace_autocomplete .ace_line-hover { border: 1px solid #abbffe; margin-top: -1px; background: rgba(233,233,253,0.4); position: absolute; z-index: 2;}.ace_dark.ace_editor.ace_autocomplete .ace_line-hover { border: 1px solid rgba(109, 150, 13, 0.8); background: rgba(58, 103, 78, 0.62);}.ace_completion-meta { opacity: 0.5; margin: 0.9em;}.ace_editor.ace_autocomplete .ace_completion-highlight{ color: #2d69c7;}.ace_dark.ace_editor.ace_autocomplete .ace_completion-highlight{ color: #93ca12;}.ace_editor.ace_autocomplete { width: 300px; z-index: 200000; border: 1px lightgray solid; position: fixed; box-shadow: 2px 3px 5px rgba(0,0,0,.2); line-height: 1.4; background: #fefefe; color: #111;}.ace_dark.ace_editor.ace_autocomplete { border: 1px #484747 solid; box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.51); line-height: 1.4; background: #25282c; color: #c1c1c1;}","autocompletion.css"),t.AcePopup=l}),define("ace/autocomplete/util",["require","exports","module"],function(e,t,n){"use strict";t.parForEach=function(e,t,n){var r=0,i=e.length;i===0&&n();for(var s=0;s=0;s--){if(!n.test(e[s]))break;i.push(e[s])}return i.reverse().join("")},t.retrieveFollowingIdentifier=function(e,t,n){n=n||r;var i=[];for(var s=t;s=n?-1:t+1;break;case"start":t=0;break;case"end":t=n}this.popup.setRow(t)},this.insertMatch=function(e,t){e||(e=this.popup.getData(this.popup.getRow()));if(!e)return!1;if(e.completer&&e.completer.insertMatch)e.completer.insertMatch(this.editor,e);else{if(this.completions.filterText){var n=this.editor.selection.getAllRanges();for(var r=0,i;i=n[r];r++)i.start.column-=this.completions.filterText.length,this.editor.session.remove(i)}e.snippet?f.insertSnippet(this.editor,e.snippet):this.editor.execCommand("insertstring",e.value||e)}this.detach()},this.commands={Up:function(e){e.completer.goTo("up")},Down:function(e){e.completer.goTo("down")},"Ctrl-Up|Ctrl-Home":function(e){e.completer.goTo("start")},"Ctrl-Down|Ctrl-End":function(e){e.completer.goTo("end")},Esc:function(e){e.completer.detach()},Return:function(e){return e.completer.insertMatch()},"Shift-Return":function(e){e.completer.insertMatch(null,{deleteSuffix:!0})},Tab:function(e){var t=e.completer.insertMatch();if(!!t||!!e.tabstopManager)return t;e.completer.goTo("down")},PageUp:function(e){e.completer.popup.gotoPageUp()},PageDown:function(e){e.completer.popup.gotoPageDown()}},this.gatherCompletions=function(e,t){var n=e.getSession(),r=e.getCursorPosition(),i=s.getCompletionPrefix(e);this.base=n.doc.createAnchor(r.row,r.column-i.length),this.base.$insertRight=!0;var o=[],u=e.completers.length;return e.completers.forEach(function(a,f){a.getCompletions(e,n,r,i,function(n,r){!n&&r&&(o=o.concat(r)),t(null,{prefix:s.getCompletionPrefix(e),matches:o,finished:--u===0})})}),!0},this.showPopup=function(e){this.editor&&this.detach(),this.activated=!0,this.editor=e,e.completer!=this&&(e.completer&&e.completer.detach(),e.completer=this),e.on("changeSelection",this.changeListener),e.on("blur",this.blurListener),e.on("mousedown",this.mousedownListener),e.on("mousewheel",this.mousewheelListener),this.updateCompletions()},this.updateCompletions=function(e){if(e&&this.base&&this.completions){var t=this.editor.getCursorPosition(),n=this.editor.session.getTextRange({start:this.base,end:t});if(n==this.completions.filterText)return;this.completions.setFilter(n);if(!this.completions.filtered.length)return this.detach();if(this.completions.filtered.length==1&&this.completions.filtered[0].value==n&&!this.completions.filtered[0].snippet)return this.detach();this.openPopup(this.editor,n,e);return}var r=this.gatherCompletionsId;this.gatherCompletions(this.editor,function(t,n){var i=function(){if(!n.finished)return;return this.detach()}.bind(this),s=n.prefix,o=n&&n.matches;if(!o||!o.length)return i();if(s.indexOf(n.prefix)!==0||r!=this.gatherCompletionsId)return;this.completions=new c(o),this.exactMatch&&(this.completions.exactMatch=!0),this.completions.setFilter(s);var u=this.completions.filtered;if(!u.length)return i();if(u.length==1&&u[0].value==s&&!u[0].snippet)return i();if(this.autoInsert&&u.length==1&&n.finished)return this.insertMatch(u[0]);this.openPopup(this.editor,s,e)}.bind(this))},this.cancelContextMenu=function(){this.editor.$mouseHandler.cancelContextMenu()},this.updateDocTooltip=function(){var e=this.popup,t=e.data,n=t&&(t[e.getHoveredRow()]||t[e.getRow()]),r=null;if(!n||!this.editor||!this.popup.isOpen)return this.hideDocTooltip();this.editor.completers.some(function(e){return e.getDocTooltip&&(r=e.getDocTooltip(n)),r}),r||(r=n),typeof r=="string"&&(r={docText:r});if(!r||!r.docHTML&&!r.docText)return this.hideDocTooltip();this.showDocTooltip(r)},this.showDocTooltip=function(e){this.tooltipNode||(this.tooltipNode=a.createElement("div"),this.tooltipNode.className="ace_tooltip ace_doc-tooltip",this.tooltipNode.style.margin=0,this.tooltipNode.style.pointerEvents="auto",this.tooltipNode.tabIndex=-1,this.tooltipNode.onblur=this.blurListener.bind(this),this.tooltipNode.onclick=this.onTooltipClick.bind(this));var t=this.tooltipNode;e.docHTML?t.innerHTML=e.docHTML:e.docText&&(t.textContent=e.docText),t.parentNode||document.body.appendChild(t);var n=this.popup,r=n.container.getBoundingClientRect();t.style.top=n.container.style.top,t.style.bottom=n.container.style.bottom,t.style.display="block",window.innerWidth-r.right<320?r.left<320?n.isTopdown?(t.style.top=r.bottom+"px",t.style.left=r.left+"px",t.style.right="",t.style.bottom=""):(t.style.top=n.container.offsetTop-t.offsetHeight+"px",t.style.left=r.left+"px",t.style.right="",t.style.bottom=""):(t.style.right=window.innerWidth-r.left+"px",t.style.left=""):(t.style.left=r.right+1+"px",t.style.right="")},this.hideDocTooltip=function(){this.tooltipTimer.cancel();if(!this.tooltipNode)return;var e=this.tooltipNode;!this.editor.isFocused()&&document.activeElement==e&&this.editor.focus(),this.tooltipNode=null,e.parentNode&&e.parentNode.removeChild(e)},this.onTooltipClick=function(e){var t=e.target;while(t&&t!=this.tooltipNode){if(t.nodeName=="A"&&t.href){t.rel="noreferrer",t.target="_blank";break}t=t.parentNode}}}).call(l.prototype),l.startCommand={name:"startAutocomplete",exec:function(e){e.completer||(e.completer=new l),e.completer.autoInsert=!1,e.completer.autoSelect=!0,e.completer.showPopup(e),e.completer.cancelContextMenu()},bindKey:"Ctrl-Space|Ctrl-Shift-Space|Alt-Space"};var c=function(e,t){this.all=e,this.filtered=e,this.filterText=t||"",this.exactMatch=!1};(function(){this.setFilter=function(e){if(e.length>this.filterText&&e.lastIndexOf(this.filterText,0)===0)var t=this.filtered;else var t=this.all;this.filterText=e,t=this.filterCompletions(t,this.filterText),t=t.sort(function(e,t){return t.exactMatch-e.exactMatch||t.$score-e.$score||(e.caption||e.value)<(t.caption||t.value)});var n=null;t=t.filter(function(e){var t=e.snippet||e.caption||e.value;return t===n?!1:(n=t,!0)}),this.filtered=t},this.filterCompletions=function(e,t){var n=[],r=t.toUpperCase(),i=t.toLowerCase();e:for(var s=0,o;o=e[s];s++){var u=o.caption||o.value||o.snippet;if(!u)continue;var a=-1,f=0,l=0,c,h;if(this.exactMatch){if(t!==u.substr(0,t.length))continue e}else{var p=u.toLowerCase().indexOf(i);if(p>-1)l=p;else for(var d=0;d=0?m<0||v0&&(a===-1&&(l+=10),l+=h,f|=1<",o.escapeHTML(e.caption),"","
",o.escapeHTML(e.snippet)].join(""))}},c=[l,a,f];t.setCompleters=function(e){c.length=0,e&&c.push.apply(c,e)},t.addCompleter=function(e){c.push(e)},t.textCompleter=a,t.keyWordCompleter=f,t.snippetCompleter=l;var h={name:"expandSnippet",exec:function(e){return r.expandWithTab(e)},bindKey:"Tab"},p=function(e,t){d(t.session.$mode)},d=function(e){var t=e.$id;r.files||(r.files={}),v(t),e.modes&&e.modes.forEach(d)},v=function(e){if(!e||r.files[e])return;var t=e.replace("mode","snippets");r.files[e]={},s.loadModule(t,function(t){t&&(r.files[e]=t,!t.snippets&&t.snippetText&&(t.snippets=r.parseSnippetFile(t.snippetText)),r.register(t.snippets||[],t.scope),t.includeScopes&&(r.snippetMap[t.scope].includeScopes=t.includeScopes,t.includeScopes.forEach(function(e){v("ace/mode/"+e)})))})},m=function(e){var t=e.editor,n=t.completer&&t.completer.activated;if(e.command.name==="backspace")n&&!u.getCompletionPrefix(t)&&t.completer.detach();else if(e.command.name==="insertstring"){var r=u.getCompletionPrefix(t);r&&!n&&(t.completer||(t.completer=new i),t.completer.autoInsert=!1,t.completer.showPopup(t))}},g=e("../editor").Editor;e("../config").defineOptions(g.prototype,"editor",{enableBasicAutocompletion:{set:function(e){e?(this.completers||(this.completers=Array.isArray(e)?e:c),this.commands.addCommand(i.startCommand)):this.commands.removeCommand(i.startCommand)},value:!1},enableLiveAutocompletion:{set:function(e){e?(this.completers||(this.completers=Array.isArray(e)?e:c),this.commands.on("afterExec",m)):this.commands.removeListener("afterExec",m)},value:!1},enableSnippets:{set:function(e){e?(this.commands.addCommand(h),this.on("changeMode",p),p(null,this)):(this.commands.removeCommand(h),this.off("changeMode",p))},value:!1}})}); - (function() { - window.require(["ace/ext/language_tools"], function(m) { - if (typeof module == "object" && typeof exports == "object" && module) { - module.exports = m; +define( + "ace/snippets", + [ + "require", + "exports", + "module", + "ace/lib/oop", + "ace/lib/event_emitter", + "ace/lib/lang", + "ace/range", + "ace/anchor", + "ace/keyboard/hash_handler", + "ace/tokenizer", + "ace/lib/dom", + "ace/editor", + ], + function (e, t, n) { + "use strict"; + var r = e("./lib/oop"), + i = e("./lib/event_emitter").EventEmitter, + s = e("./lib/lang"), + o = e("./range").Range, + u = e("./anchor").Anchor, + a = e("./keyboard/hash_handler").HashHandler, + f = e("./tokenizer").Tokenizer, + l = o.comparePoints, + c = function () { + (this.snippetMap = {}), (this.snippetNameMap = {}); + }; + (function () { + r.implement(this, i), + (this.getTokenizer = function () { + function e(e, t, n) { + return ( + (e = e.substr(1)), + /^\d+$/.test(e) && !n.inFormatString + ? [{ tabstopId: parseInt(e, 10) }] + : [{ text: e }] + ); + } + function t(e) { + return "(?:[^\\\\" + e + "]|\\\\.)"; + } + return ( + (c.$tokenizer = new f({ + start: [ + { + regex: /:/, + onMatch: function (e, t, n) { + return n.length && n[0].expectIf + ? ((n[0].expectIf = !1), + (n[0].elseBranch = n[0]), + [n[0]]) + : ":"; + }, + }, + { + regex: /\\./, + onMatch: function (e, t, n) { + var r = e[1]; + return ( + r == "}" && n.length + ? (e = r) + : "`$\\".indexOf(r) != -1 + ? (e = r) + : n.inFormatString && + (r == "n" + ? (e = "\n") + : r == "t" + ? (e = "\n") + : "ulULE".indexOf(r) != -1 && + (e = { + changeCase: r, + local: r > "a", + })), + [e] + ); + }, + }, + { + regex: /}/, + onMatch: function (e, t, n) { + return [n.length ? n.shift() : e]; + }, + }, + { regex: /\$(?:\d+|\w+)/, onMatch: e }, + { + regex: /\$\{[\dA-Z_a-z]+/, + onMatch: function (t, n, r) { + var i = e(t.substr(1), n, r); + return r.unshift(i[0]), i; + }, + next: "snippetVar", + }, + { regex: /\n/, token: "newline", merge: !1 }, + ], + snippetVar: [ + { + regex: "\\|" + t("\\|") + "*\\|", + onMatch: function (e, t, n) { + n[0].choices = e.slice(1, -1).split(","); + }, + next: "start", + }, + { + regex: "/(" + t("/") + "+)/(?:(" + t("/") + "*)/)(\\w*):?", + onMatch: function (e, t, n) { + var r = n[0]; + return ( + (r.fmtString = e), + (e = this.splitRegex.exec(e)), + (r.guard = e[1]), + (r.fmt = e[2]), + (r.flag = e[3]), + "" + ); + }, + next: "start", + }, + { + regex: "`" + t("`") + "*`", + onMatch: function (e, t, n) { + return (n[0].code = e.splice(1, -1)), ""; + }, + next: "start", + }, + { + regex: "\\?", + onMatch: function (e, t, n) { + n[0] && (n[0].expectIf = !0); + }, + next: "start", + }, + { regex: "([^:}\\\\]|\\\\.)*:?", token: "", next: "start" }, + ], + formatString: [ + { regex: "/(" + t("/") + "+)/", token: "regex" }, + { + regex: "", + onMatch: function (e, t, n) { + n.inFormatString = !0; + }, + next: "start", + }, + ], + })), + (c.prototype.getTokenizer = function () { + return c.$tokenizer; + }), + c.$tokenizer + ); + }), + (this.tokenizeTmSnippet = function (e, t) { + return this.getTokenizer() + .getLineTokens(e, t) + .tokens.map(function (e) { + return e.value || e; + }); + }), + (this.$getDefaultValue = function (e, t) { + if (/^[A-Z]\d+$/.test(t)) { + var n = t.substr(1); + return (this.variables[t[0] + "__"] || {})[n]; + } + if (/^\d+$/.test(t)) return (this.variables.__ || {})[t]; + t = t.replace(/^TM_/, ""); + if (!e) return; + var r = e.session; + switch (t) { + case "CURRENT_WORD": + var i = r.getWordRange(); + case "SELECTION": + case "SELECTED_TEXT": + return r.getTextRange(i); + case "CURRENT_LINE": + return r.getLine(e.getCursorPosition().row); + case "PREV_LINE": + return r.getLine(e.getCursorPosition().row - 1); + case "LINE_INDEX": + return e.getCursorPosition().column; + case "LINE_NUMBER": + return e.getCursorPosition().row + 1; + case "SOFT_TABS": + return r.getUseSoftTabs() ? "YES" : "NO"; + case "TAB_SIZE": + return r.getTabSize(); + case "FILENAME": + case "FILEPATH": + return ""; + case "FULLNAME": + return "Ace"; + } + }), + (this.variables = {}), + (this.getVariableValue = function (e, t) { + return this.variables.hasOwnProperty(t) + ? this.variables[t](e, t) || "" + : this.$getDefaultValue(e, t) || ""; + }), + (this.tmStrFormat = function (e, t, n) { + var r = t.flag || "", + i = t.guard; + i = new RegExp(i, r.replace(/[^gi]/, "")); + var s = this.tokenizeTmSnippet(t.fmt, "formatString"), + o = this, + u = e.replace(i, function () { + o.variables.__ = arguments; + var e = o.resolveVariables(s, n), + t = "E"; + for (var r = 0; r < e.length; r++) { + var i = e[r]; + if (typeof i == "object") { + e[r] = ""; + if (i.changeCase && i.local) { + var u = e[r + 1]; + u && + typeof u == "string" && + (i.changeCase == "u" + ? (e[r] = u[0].toUpperCase()) + : (e[r] = u[0].toLowerCase()), + (e[r + 1] = u.substr(1))); + } else i.changeCase && (t = i.changeCase); + } else + t == "U" + ? (e[r] = i.toUpperCase()) + : t == "L" && (e[r] = i.toLowerCase()); + } + return e.join(""); + }); + return (this.variables.__ = null), u; + }), + (this.resolveVariables = function (e, t) { + function o(t) { + var n = e.indexOf(t, r + 1); + n != -1 && (r = n); + } + var n = []; + for (var r = 0; r < e.length; r++) { + var i = e[r]; + if (typeof i == "string") n.push(i); + else { + if (typeof i != "object") continue; + if (i.skip) o(i); + else { + if (i.processed < r) continue; + if (i.text) { + var s = this.getVariableValue(t, i.text); + s && i.fmtString && (s = this.tmStrFormat(s, i)), + (i.processed = r), + i.expectIf == null + ? s && (n.push(s), o(i)) + : s + ? (i.skip = i.elseBranch) + : o(i); + } else + i.tabstopId != null + ? n.push(i) + : i.changeCase != null && n.push(i); + } } + } + return n; + }), + (this.insertSnippetForSelection = function (e, t) { + function f(e) { + var t = []; + for (var n = 0; n < e.length; n++) { + var r = e[n]; + if (typeof r == "object") { + if (a[r.tabstopId]) continue; + var i = e.lastIndexOf(r, n - 1); + r = t[i] || { tabstopId: r.tabstopId }; + } + t[n] = r; + } + return t; + } + var n = e.getCursorPosition(), + r = e.session.getLine(n.row), + i = e.session.getTabString(), + s = r.match(/^\s*/)[0]; + n.column < s.length && (s = s.slice(0, n.column)), (t = t.replace(/\r/g, "")); + var o = this.tokenizeTmSnippet(t); + (o = this.resolveVariables(o, e)), + (o = o.map(function (e) { + return e == "\n" + ? e + s + : typeof e == "string" + ? e.replace(/\t/g, i) + : e; + })); + var u = []; + o.forEach(function (e, t) { + if (typeof e != "object") return; + var n = e.tabstopId, + r = u[n]; + r || ((r = u[n] = []), (r.index = n), (r.value = "")); + if (r.indexOf(e) !== -1) return; + r.push(e); + var i = o.indexOf(e, t + 1); + if (i === -1) return; + var s = o.slice(t + 1, i), + a = s.some(function (e) { + return typeof e == "object"; + }); + a && !r.value + ? (r.value = s) + : s.length && + (!r.value || typeof r.value != "string") && + (r.value = s.join("")); + }), + u.forEach(function (e) { + e.length = 0; + }); + var a = {}; + for (var l = 0; l < o.length; l++) { + var c = o[l]; + if (typeof c != "object") continue; + var p = c.tabstopId, + d = o.indexOf(c, l + 1); + if (a[p]) { + a[p] === c && (a[p] = null); + continue; + } + var v = u[p], + m = typeof v.value == "string" ? [v.value] : f(v.value); + m.unshift(l + 1, Math.max(0, d - l)), + m.push(c), + (a[p] = c), + o.splice.apply(o, m), + v.indexOf(c) === -1 && v.push(c); + } + var g = 0, + y = 0, + b = ""; + o.forEach(function (e) { + if (typeof e == "string") { + var t = e.split("\n"); + t.length > 1 + ? ((y = t[t.length - 1].length), (g += t.length - 1)) + : (y += e.length), + (b += e); + } else + e.start + ? (e.end = { row: g, column: y }) + : (e.start = { row: g, column: y }); + }); + var w = e.getSelectionRange(), + E = e.session.replace(w, b), + S = new h(e), + x = e.inVirtualSelectionMode && e.selection.index; + S.addTabstops(u, w.start, E, x); + }), + (this.insertSnippet = function (e, t) { + var n = this; + if (e.inVirtualSelectionMode) return n.insertSnippetForSelection(e, t); + e.forEachSelection( + function () { + n.insertSnippetForSelection(e, t); + }, + null, + { keepOrder: !0 }, + ), + e.tabstopManager && e.tabstopManager.tabNext(); + }), + (this.$getScope = function (e) { + var t = e.session.$mode.$id || ""; + t = t.split("/").pop(); + if (t === "html" || t === "php") { + t === "php" && !e.session.$mode.inlinePhp && (t = "html"); + var n = e.getCursorPosition(), + r = e.session.getState(n.row); + typeof r == "object" && (r = r[0]), + r.substring && + (r.substring(0, 3) == "js-" + ? (t = "javascript") + : r.substring(0, 4) == "css-" + ? (t = "css") + : r.substring(0, 4) == "php-" && (t = "php")); + } + return t; + }), + (this.getActiveScopes = function (e) { + var t = this.$getScope(e), + n = [t], + r = this.snippetMap; + return ( + r[t] && r[t].includeScopes && n.push.apply(n, r[t].includeScopes), + n.push("_"), + n + ); + }), + (this.expandWithTab = function (e, t) { + var n = this, + r = e.forEachSelection( + function () { + return n.expandSnippetForSelection(e, t); + }, + null, + { keepOrder: !0 }, + ); + return r && e.tabstopManager && e.tabstopManager.tabNext(), r; + }), + (this.expandSnippetForSelection = function (e, t) { + var n = e.getCursorPosition(), + r = e.session.getLine(n.row), + i = r.substring(0, n.column), + s = r.substr(n.column), + o = this.snippetMap, + u; + return ( + this.getActiveScopes(e).some(function (e) { + var t = o[e]; + return t && (u = this.findMatchingSnippet(t, i, s)), !!u; + }, this), + u + ? t && t.dryRun + ? !0 + : (e.session.doc.removeInLine( + n.row, + n.column - u.replaceBefore.length, + n.column + u.replaceAfter.length, + ), + (this.variables.M__ = u.matchBefore), + (this.variables.T__ = u.matchAfter), + this.insertSnippetForSelection(e, u.content), + (this.variables.M__ = this.variables.T__ = null), + !0) + : !1 + ); + }), + (this.findMatchingSnippet = function (e, t, n) { + for (var r = e.length; r--; ) { + var i = e[r]; + if (i.startRe && !i.startRe.test(t)) continue; + if (i.endRe && !i.endRe.test(n)) continue; + if (!i.startRe && !i.endRe) continue; + return ( + (i.matchBefore = i.startRe ? i.startRe.exec(t) : [""]), + (i.matchAfter = i.endRe ? i.endRe.exec(n) : [""]), + (i.replaceBefore = i.triggerRe ? i.triggerRe.exec(t)[0] : ""), + (i.replaceAfter = i.endTriggerRe ? i.endTriggerRe.exec(n)[0] : ""), + i + ); + } + }), + (this.snippetMap = {}), + (this.snippetNameMap = {}), + (this.register = function (e, t) { + function o(e) { + return ( + e && !/^\^?\(.*\)\$?$|^\\b$/.test(e) && (e = "(?:" + e + ")"), e || "" + ); + } + function u(e, t, n) { + return ( + (e = o(e)), + (t = o(t)), + n + ? ((e = t + e), e && e[e.length - 1] != "$" && (e += "$")) + : ((e += t), e && e[0] != "^" && (e = "^" + e)), + new RegExp(e) + ); + } + function a(e) { + e.scope || (e.scope = t || "_"), + (t = e.scope), + n[t] || ((n[t] = []), (r[t] = {})); + var o = r[t]; + if (e.name) { + var a = o[e.name]; + a && i.unregister(a), (o[e.name] = e); + } + n[t].push(e), + e.tabTrigger && + !e.trigger && + (!e.guard && /^\w/.test(e.tabTrigger) && (e.guard = "\\b"), + (e.trigger = s.escapeRegExp(e.tabTrigger))); + if (!e.trigger && !e.guard && !e.endTrigger && !e.endGuard) return; + (e.startRe = u(e.trigger, e.guard, !0)), + (e.triggerRe = new RegExp(e.trigger)), + (e.endRe = u(e.endTrigger, e.endGuard, !0)), + (e.endTriggerRe = new RegExp(e.endTrigger)); + } + var n = this.snippetMap, + r = this.snippetNameMap, + i = this; + e || (e = []), + e && e.content ? a(e) : Array.isArray(e) && e.forEach(a), + this._signal("registerSnippets", { scope: t }); + }), + (this.unregister = function (e, t) { + function i(e) { + var i = r[e.scope || t]; + if (i && i[e.name]) { + delete i[e.name]; + var s = n[e.scope || t], + o = s && s.indexOf(e); + o >= 0 && s.splice(o, 1); + } + } + var n = this.snippetMap, + r = this.snippetNameMap; + e.content ? i(e) : Array.isArray(e) && e.forEach(i); + }), + (this.parseSnippetFile = function (e) { + e = e.replace(/\r/g, ""); + var t = [], + n = {}, + r = /^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm, + i; + while ((i = r.exec(e))) { + if (i[1]) + try { + (n = JSON.parse(i[1])), t.push(n); + } catch (s) {} + if (i[4]) (n.content = i[4].replace(/^\t/gm, "")), t.push(n), (n = {}); + else { + var o = i[2], + u = i[3]; + if (o == "regex") { + var a = /\/((?:[^\/\\]|\\.)*)|$/g; + (n.guard = a.exec(u)[1]), + (n.trigger = a.exec(u)[1]), + (n.endTrigger = a.exec(u)[1]), + (n.endGuard = a.exec(u)[1]); + } else + o == "snippet" + ? ((n.tabTrigger = u.match(/^\S*/)[0]), n.name || (n.name = u)) + : (n[o] = u); + } + } + return t; + }), + (this.getSnippetByName = function (e, t) { + var n = this.snippetNameMap, + r; + return ( + this.getActiveScopes(t).some(function (t) { + var i = n[t]; + return i && (r = i[e]), !!r; + }, this), + r + ); + }); + }).call(c.prototype); + var h = function (e) { + if (e.tabstopManager) return e.tabstopManager; + (e.tabstopManager = this), + (this.$onChange = this.onChange.bind(this)), + (this.$onChangeSelection = s.delayedCall( + this.onChangeSelection.bind(this), + ).schedule), + (this.$onChangeSession = this.onChangeSession.bind(this)), + (this.$onAfterExec = this.onAfterExec.bind(this)), + this.attach(e); + }; + (function () { + (this.attach = function (e) { + (this.index = 0), + (this.ranges = []), + (this.tabstops = []), + (this.$openTabstops = null), + (this.selectedTabstop = null), + (this.editor = e), + this.editor.on("change", this.$onChange), + this.editor.on("changeSelection", this.$onChangeSelection), + this.editor.on("changeSession", this.$onChangeSession), + this.editor.commands.on("afterExec", this.$onAfterExec), + this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler); + }), + (this.detach = function () { + this.tabstops.forEach(this.removeTabstopMarkers, this), + (this.ranges = null), + (this.tabstops = null), + (this.selectedTabstop = null), + this.editor.removeListener("change", this.$onChange), + this.editor.removeListener("changeSelection", this.$onChangeSelection), + this.editor.removeListener("changeSession", this.$onChangeSession), + this.editor.commands.removeListener("afterExec", this.$onAfterExec), + this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler), + (this.editor.tabstopManager = null), + (this.editor = null); + }), + (this.onChange = function (e) { + var t = e, + n = e.action[0] == "r", + r = e.start, + i = e.end, + s = r.row, + o = i.row, + u = o - s, + a = i.column - r.column; + n && ((u = -u), (a = -a)); + if (!this.$inChange && n) { + var f = this.selectedTabstop, + c = + f && + !f.some(function (e) { + return l(e.start, r) <= 0 && l(e.end, i) >= 0; + }); + if (c) return this.detach(); + } + var h = this.ranges; + for (var p = 0; p < h.length; p++) { + var d = h[p]; + if (d.end.row < r.row) continue; + if (n && l(r, d.start) < 0 && l(i, d.end) > 0) { + this.removeRange(d), p--; + continue; + } + d.start.row == s && d.start.column > r.column && (d.start.column += a), + d.end.row == s && d.end.column >= r.column && (d.end.column += a), + d.start.row >= s && (d.start.row += u), + d.end.row >= s && (d.end.row += u), + l(d.start, d.end) > 0 && this.removeRange(d); + } + h.length || this.detach(); + }), + (this.updateLinkedFields = function () { + var e = this.selectedTabstop; + if (!e || !e.hasLinkedRanges) return; + this.$inChange = !0; + var n = this.editor.session, + r = n.getTextRange(e.firstNonLinked); + for (var i = e.length; i--; ) { + var s = e[i]; + if (!s.linked) continue; + var o = t.snippetManager.tmStrFormat(r, s.original); + n.replace(s, o); + } + this.$inChange = !1; + }), + (this.onAfterExec = function (e) { + e.command && !e.command.readOnly && this.updateLinkedFields(); + }), + (this.onChangeSelection = function () { + if (!this.editor) return; + var e = this.editor.selection.lead, + t = this.editor.selection.anchor, + n = this.editor.selection.isEmpty(); + for (var r = this.ranges.length; r--; ) { + if (this.ranges[r].linked) continue; + var i = this.ranges[r].contains(e.row, e.column), + s = n || this.ranges[r].contains(t.row, t.column); + if (i && s) return; + } + this.detach(); + }), + (this.onChangeSession = function () { + this.detach(); + }), + (this.tabNext = function (e) { + var t = this.tabstops.length, + n = this.index + (e || 1); + (n = Math.min(Math.max(n, 1), t)), + n == t && (n = 0), + this.selectTabstop(n), + n === 0 && this.detach(); + }), + (this.selectTabstop = function (e) { + this.$openTabstops = null; + var t = this.tabstops[this.index]; + t && this.addTabstopMarkers(t), + (this.index = e), + (t = this.tabstops[this.index]); + if (!t || !t.length) return; + this.selectedTabstop = t; + if (!this.editor.inVirtualSelectionMode) { + var n = this.editor.multiSelect; + n.toSingleRange(t.firstNonLinked.clone()); + for (var r = t.length; r--; ) { + if (t.hasLinkedRanges && t[r].linked) continue; + n.addRange(t[r].clone(), !0); + } + n.ranges[0] && n.addRange(n.ranges[0].clone()); + } else this.editor.selection.setRange(t.firstNonLinked); + this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler); + }), + (this.addTabstops = function (e, t, n) { + this.$openTabstops || (this.$openTabstops = []); + if (!e[0]) { + var r = o.fromPoints(n, n); + v(r.start, t), v(r.end, t), (e[0] = [r]), (e[0].index = 0); + } + var i = this.index, + s = [i + 1, 0], + u = this.ranges; + e.forEach(function (e, n) { + var r = this.$openTabstops[n] || e; + for (var i = e.length; i--; ) { + var a = e[i], + f = o.fromPoints(a.start, a.end || a.start); + d(f.start, t), + d(f.end, t), + (f.original = a), + (f.tabstop = r), + u.push(f), + r != e ? r.unshift(f) : (r[i] = f), + a.fmtString + ? ((f.linked = !0), (r.hasLinkedRanges = !0)) + : r.firstNonLinked || (r.firstNonLinked = f); + } + r.firstNonLinked || (r.hasLinkedRanges = !1), + r === e && (s.push(r), (this.$openTabstops[n] = r)), + this.addTabstopMarkers(r); + }, this), + s.length > 2 && + (this.tabstops.length && s.push(s.splice(2, 1)[0]), + this.tabstops.splice.apply(this.tabstops, s)); + }), + (this.addTabstopMarkers = function (e) { + var t = this.editor.session; + e.forEach(function (e) { + e.markerId || (e.markerId = t.addMarker(e, "ace_snippet-marker", "text")); + }); + }), + (this.removeTabstopMarkers = function (e) { + var t = this.editor.session; + e.forEach(function (e) { + t.removeMarker(e.markerId), (e.markerId = null); + }); + }), + (this.removeRange = function (e) { + var t = e.tabstop.indexOf(e); + e.tabstop.splice(t, 1), + (t = this.ranges.indexOf(e)), + this.ranges.splice(t, 1), + this.editor.session.removeMarker(e.markerId), + e.tabstop.length || + ((t = this.tabstops.indexOf(e.tabstop)), + t != -1 && this.tabstops.splice(t, 1), + this.tabstops.length || this.detach()); + }), + (this.keyboardHandler = new a()), + this.keyboardHandler.bindKeys({ + Tab: function (e) { + if (t.snippetManager && t.snippetManager.expandWithTab(e)) return; + e.tabstopManager.tabNext(1); + }, + "Shift-Tab": function (e) { + e.tabstopManager.tabNext(-1); + }, + Esc: function (e) { + e.tabstopManager.detach(); + }, + Return: function (e) { + return !1; + }, + }); + }).call(h.prototype); + var p = {}; + (p.onChange = u.prototype.onChange), + (p.setPosition = function (e, t) { + (this.pos.row = e), (this.pos.column = t); + }), + (p.update = function (e, t, n) { + (this.$insertRight = n), (this.pos = e), this.onChange(t); + }); + var d = function (e, t) { + e.row == 0 && (e.column += t.column), (e.row += t.row); + }, + v = function (e, t) { + e.row == t.row && (e.column -= t.column), (e.row -= t.row); + }; + e("./lib/dom").importCssString( + ".ace_snippet-marker { -moz-box-sizing: border-box; box-sizing: border-box; background: rgba(194, 193, 208, 0.09); border: 1px dotted rgba(211, 208, 235, 0.62); position: absolute;}", + ), + (t.snippetManager = new c()); + var m = e("./editor").Editor; + (function () { + (this.insertSnippet = function (e, n) { + return t.snippetManager.insertSnippet(this, e, n); + }), + (this.expandSnippet = function (e) { + return t.snippetManager.expandWithTab(this, e); + }); + }).call(m.prototype); + }, +), + define( + "ace/autocomplete/popup", + [ + "require", + "exports", + "module", + "ace/virtual_renderer", + "ace/editor", + "ace/range", + "ace/lib/event", + "ace/lib/lang", + "ace/lib/dom", + ], + function (e, t, n) { + "use strict"; + var r = e("../virtual_renderer").VirtualRenderer, + i = e("../editor").Editor, + s = e("../range").Range, + o = e("../lib/event"), + u = e("../lib/lang"), + a = e("../lib/dom"), + f = function (e) { + var t = new r(e); + t.$maxLines = 4; + var n = new i(t); + return ( + n.setHighlightActiveLine(!1), + n.setShowPrintMargin(!1), + n.renderer.setShowGutter(!1), + n.renderer.setHighlightGutterLine(!1), + (n.$mouseHandler.$focusTimeout = 0), + (n.$highlightTagPending = !0), + n + ); + }, + l = function (e) { + var t = a.createElement("div"), + n = new f(t); + e && e.appendChild(t), + (t.style.display = "none"), + (n.renderer.content.style.cursor = "default"), + n.renderer.setStyle("ace_autocomplete"), + n.setOption("displayIndentGuides", !1), + n.setOption("dragDelay", 150); + var r = function () {}; + (n.focus = r), + (n.$isFocused = !0), + (n.renderer.$cursorLayer.restartTimer = r), + (n.renderer.$cursorLayer.element.style.opacity = 0), + (n.renderer.$maxLines = 8), + (n.renderer.$keepTextAreaAtCursor = !1), + n.setHighlightActiveLine(!1), + n.session.highlight(""), + (n.session.$searchHighlight.clazz = "ace_highlight-marker"), + n.on("mousedown", function (e) { + var t = e.getDocumentPosition(); + n.selection.moveToPosition(t), + (c.start.row = c.end.row = t.row), + e.stop(); + }); + var i, + l = new s(-1, 0, -1, Infinity), + c = new s(-1, 0, -1, Infinity); + (c.id = n.session.addMarker(c, "ace_active-line", "fullLine")), + (n.setSelectOnHover = function (e) { + e + ? l.id && (n.session.removeMarker(l.id), (l.id = null)) + : (l.id = n.session.addMarker(l, "ace_line-hover", "fullLine")); + }), + n.setSelectOnHover(!1), + n.on("mousemove", function (e) { + if (!i) { + i = e; + return; + } + if (i.x == e.x && i.y == e.y) return; + (i = e), (i.scrollTop = n.renderer.scrollTop); + var t = i.getDocumentPosition().row; + l.start.row != t && (l.id || n.setRow(t), p(t)); + }), + n.renderer.on("beforeRender", function () { + if (i && l.start.row != -1) { + i.$pos = null; + var e = i.getDocumentPosition().row; + l.id || n.setRow(e), p(e, !0); + } + }), + n.renderer.on("afterRender", function () { + var e = n.getRow(), + t = n.renderer.$textLayer, + r = t.element.childNodes[e - t.config.firstRow]; + if (r == t.selectedNode) return; + t.selectedNode && a.removeCssClass(t.selectedNode, "ace_selected"), + (t.selectedNode = r), + r && a.addCssClass(r, "ace_selected"); + }); + var h = function () { + p(-1); + }, + p = function (e, t) { + e !== l.start.row && + ((l.start.row = l.end.row = e), + t || n.session._emit("changeBackMarker"), + n._emit("changeHoverMarker")); + }; + (n.getHoveredRow = function () { + return l.start.row; + }), + o.addListener(n.container, "mouseout", h), + n.on("hide", h), + n.on("changeSelection", h), + (n.session.doc.getLength = function () { + return n.data.length; + }), + (n.session.doc.getLine = function (e) { + var t = n.data[e]; + return typeof t == "string" ? t : (t && t.value) || ""; + }); + var d = n.session.bgTokenizer; + return ( + (d.$tokenizeRow = function (e) { + function s(e, n) { + e && r.push({ type: (t.className || "") + (n || ""), value: e }); + } + var t = n.data[e], + r = []; + if (!t) return r; + typeof t == "string" && (t = { value: t }); + var i = t.caption || t.value || t.name, + o = i.toLowerCase(), + u = (n.filterText || "").toLowerCase(), + a = 0, + f = 0; + for (var l = 0; l <= u.length; l++) + if (l != f && (t.matchMask & (1 << l) || l == u.length)) { + var c = u.slice(f, l); + f = l; + var h = o.indexOf(c); + if (h == -1) continue; + s(i.slice(a, h), ""), + (a = h + c.length), + s(i.slice(h, a), "completion-highlight"); + } + return ( + s(i.slice(a, i.length), ""), + t.meta && r.push({ type: "completion-meta", value: t.meta }), + r + ); + }), + (d.$updateOnChange = r), + (d.start = r), + (n.session.$computeWidth = function () { + return (this.screenWidth = 0); + }), + (n.isOpen = !1), + (n.isTopdown = !1), + (n.autoSelect = !0), + (n.filterText = ""), + (n.data = []), + (n.setData = function (e, t) { + (n.filterText = t || ""), + n.setValue(u.stringRepeat("\n", e.length), -1), + (n.data = e || []), + n.setRow(0); + }), + (n.getData = function (e) { + return n.data[e]; + }), + (n.getRow = function () { + return c.start.row; + }), + (n.setRow = function (e) { + (e = Math.max(this.autoSelect ? 0 : -1, Math.min(this.data.length, e))), + c.start.row != e && + (n.selection.clearSelection(), + (c.start.row = c.end.row = e || 0), + n.session._emit("changeBackMarker"), + n.moveCursorTo(e || 0, 0), + n.isOpen && n._signal("select")); + }), + n.on("changeSelection", function () { + n.isOpen && n.setRow(n.selection.lead.row), + n.renderer.scrollCursorIntoView(); + }), + (n.hide = function () { + (this.container.style.display = "none"), + this._signal("hide"), + (n.isOpen = !1); + }), + (n.show = function (e, t, r) { + var s = this.container, + o = window.innerHeight, + u = window.innerWidth, + a = this.renderer, + f = a.$maxLines * t * 1.4, + l = e.top + this.$borderSize, + c = l > o / 2 && !r; + c && l + t + f > o + ? ((a.$maxPixelHeight = l - 2 * this.$borderSize), + (s.style.top = ""), + (s.style.bottom = o - l + "px"), + (n.isTopdown = !1)) + : ((l += t), + (a.$maxPixelHeight = o - l - 0.2 * t), + (s.style.top = l + "px"), + (s.style.bottom = ""), + (n.isTopdown = !0)), + (s.style.display = ""), + this.renderer.$textLayer.checkForSizeChanges(); + var h = e.left; + h + s.offsetWidth > u && (h = u - s.offsetWidth), + (s.style.left = h + "px"), + this._signal("show"), + (i = null), + (n.isOpen = !0); + }), + (n.getTextLeftOffset = function () { + return this.$borderSize + this.renderer.$padding + this.$imageSize; + }), + (n.$imageSize = 0), + (n.$borderSize = 1), + n + ); + }; + a.importCssString( + ".ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line { background-color: #CAD6FA; z-index: 1;}.ace_dark.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line { background-color: #3a674e;}.ace_editor.ace_autocomplete .ace_line-hover { border: 1px solid #abbffe; margin-top: -1px; background: rgba(233,233,253,0.4); position: absolute; z-index: 2;}.ace_dark.ace_editor.ace_autocomplete .ace_line-hover { border: 1px solid rgba(109, 150, 13, 0.8); background: rgba(58, 103, 78, 0.62);}.ace_completion-meta { opacity: 0.5; margin: 0.9em;}.ace_editor.ace_autocomplete .ace_completion-highlight{ color: #2d69c7;}.ace_dark.ace_editor.ace_autocomplete .ace_completion-highlight{ color: #93ca12;}.ace_editor.ace_autocomplete { width: 300px; z-index: 200000; border: 1px lightgray solid; position: fixed; box-shadow: 2px 3px 5px rgba(0,0,0,.2); line-height: 1.4; background: #fefefe; color: #111;}.ace_dark.ace_editor.ace_autocomplete { border: 1px #484747 solid; box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.51); line-height: 1.4; background: #25282c; color: #c1c1c1;}", + "autocompletion.css", + ), + (t.AcePopup = l); + }, + ), + define("ace/autocomplete/util", ["require", "exports", "module"], function (e, t, n) { + "use strict"; + t.parForEach = function (e, t, n) { + var r = 0, + i = e.length; + i === 0 && n(); + for (var s = 0; s < i; s++) + t(e[s], function (e, t) { + r++, r === i && n(e, t); + }); + }; + var r = /[a-zA-Z_0-9\$\-\u00A2-\uFFFF]/; + (t.retrievePrecedingIdentifier = function (e, t, n) { + n = n || r; + var i = []; + for (var s = t - 1; s >= 0; s--) { + if (!n.test(e[s])) break; + i.push(e[s]); + } + return i.reverse().join(""); + }), + (t.retrieveFollowingIdentifier = function (e, t, n) { + n = n || r; + var i = []; + for (var s = t; s < e.length; s++) { + if (!n.test(e[s])) break; + i.push(e[s]); + } + return i; + }), + (t.getCompletionPrefix = function (e) { + var t = e.getCursorPosition(), + n = e.session.getLine(t.row), + r; + return ( + e.completers.forEach( + function (e) { + e.identifierRegexps && + e.identifierRegexps.forEach( + function (e) { + !r && + e && + (r = this.retrievePrecedingIdentifier(n, t.column, e)); + }.bind(this), + ); + }.bind(this), + ), + r || this.retrievePrecedingIdentifier(n, t.column) + ); + }); + }), + define( + "ace/autocomplete", + [ + "require", + "exports", + "module", + "ace/keyboard/hash_handler", + "ace/autocomplete/popup", + "ace/autocomplete/util", + "ace/lib/event", + "ace/lib/lang", + "ace/lib/dom", + "ace/snippets", + ], + function (e, t, n) { + "use strict"; + var r = e("./keyboard/hash_handler").HashHandler, + i = e("./autocomplete/popup").AcePopup, + s = e("./autocomplete/util"), + o = e("./lib/event"), + u = e("./lib/lang"), + a = e("./lib/dom"), + f = e("./snippets").snippetManager, + l = function () { + (this.autoInsert = !1), + (this.autoSelect = !0), + (this.exactMatch = !1), + (this.gatherCompletionsId = 0), + (this.keyboardHandler = new r()), + this.keyboardHandler.bindKeys(this.commands), + (this.blurListener = this.blurListener.bind(this)), + (this.changeListener = this.changeListener.bind(this)), + (this.mousedownListener = this.mousedownListener.bind(this)), + (this.mousewheelListener = this.mousewheelListener.bind(this)), + (this.changeTimer = u.delayedCall( + function () { + this.updateCompletions(!0); + }.bind(this), + )), + (this.tooltipTimer = u.delayedCall(this.updateDocTooltip.bind(this), 50)); + }; + (function () { + (this.$init = function () { + return ( + (this.popup = new i(document.body || document.documentElement)), + this.popup.on( + "click", + function (e) { + this.insertMatch(), e.stop(); + }.bind(this), + ), + (this.popup.focus = this.editor.focus.bind(this.editor)), + this.popup.on("show", this.tooltipTimer.bind(null, null)), + this.popup.on("select", this.tooltipTimer.bind(null, null)), + this.popup.on("changeHoverMarker", this.tooltipTimer.bind(null, null)), + this.popup + ); + }), + (this.getPopup = function () { + return this.popup || this.$init(); + }), + (this.openPopup = function (e, t, n) { + this.popup || this.$init(), + (this.popup.autoSelect = this.autoSelect), + this.popup.setData( + this.completions.filtered, + this.completions.filterText, + ), + e.keyBinding.addKeyboardHandler(this.keyboardHandler); + var r = e.renderer; + this.popup.setRow(this.autoSelect ? 0 : -1); + if (!n) { + this.popup.setTheme(e.getTheme()), + this.popup.setFontSize(e.getFontSize()); + var i = r.layerConfig.lineHeight, + s = r.$cursorLayer.getPixelPosition(this.base, !0); + s.left -= this.popup.getTextLeftOffset(); + var o = e.container.getBoundingClientRect(); + (s.top += o.top - r.layerConfig.offset), + (s.left += o.left - e.renderer.scrollLeft), + (s.left += r.gutterWidth), + this.popup.show(s, i); + } else n && !t && this.detach(); + }), + (this.detach = function () { + this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler), + this.editor.off("changeSelection", this.changeListener), + this.editor.off("blur", this.blurListener), + this.editor.off("mousedown", this.mousedownListener), + this.editor.off("mousewheel", this.mousewheelListener), + this.changeTimer.cancel(), + this.hideDocTooltip(), + (this.gatherCompletionsId += 1), + this.popup && this.popup.isOpen && this.popup.hide(), + this.base && this.base.detach(), + (this.activated = !1), + (this.completions = this.base = null); + }), + (this.changeListener = function (e) { + var t = this.editor.selection.lead; + (t.row != this.base.row || t.column < this.base.column) && this.detach(), + this.activated ? this.changeTimer.schedule() : this.detach(); + }), + (this.blurListener = function (e) { + var t = document.activeElement, + n = this.editor.textInput.getElement(), + r = + e.relatedTarget && + this.tooltipNode && + this.tooltipNode.contains(e.relatedTarget), + i = this.popup && this.popup.container; + t != n && + t.parentNode != i && + !r && + t != this.tooltipNode && + e.relatedTarget != n && + this.detach(); + }), + (this.mousedownListener = function (e) { + this.detach(); + }), + (this.mousewheelListener = function (e) { + this.detach(); + }), + (this.goTo = function (e) { + var t = this.popup.getRow(), + n = this.popup.session.getLength() - 1; + switch (e) { + case "up": + t = t <= 0 ? n : t - 1; + break; + case "down": + t = t >= n ? -1 : t + 1; + break; + case "start": + t = 0; + break; + case "end": + t = n; + } + this.popup.setRow(t); + }), + (this.insertMatch = function (e, t) { + e || (e = this.popup.getData(this.popup.getRow())); + if (!e) return !1; + if (e.completer && e.completer.insertMatch) + e.completer.insertMatch(this.editor, e); + else { + if (this.completions.filterText) { + var n = this.editor.selection.getAllRanges(); + for (var r = 0, i; (i = n[r]); r++) + (i.start.column -= this.completions.filterText.length), + this.editor.session.remove(i); + } + e.snippet + ? f.insertSnippet(this.editor, e.snippet) + : this.editor.execCommand("insertstring", e.value || e); + } + this.detach(); + }), + (this.commands = { + Up: function (e) { + e.completer.goTo("up"); + }, + Down: function (e) { + e.completer.goTo("down"); + }, + "Ctrl-Up|Ctrl-Home": function (e) { + e.completer.goTo("start"); + }, + "Ctrl-Down|Ctrl-End": function (e) { + e.completer.goTo("end"); + }, + Esc: function (e) { + e.completer.detach(); + }, + Return: function (e) { + return e.completer.insertMatch(); + }, + "Shift-Return": function (e) { + e.completer.insertMatch(null, { deleteSuffix: !0 }); + }, + Tab: function (e) { + var t = e.completer.insertMatch(); + if (!!t || !!e.tabstopManager) return t; + e.completer.goTo("down"); + }, + PageUp: function (e) { + e.completer.popup.gotoPageUp(); + }, + PageDown: function (e) { + e.completer.popup.gotoPageDown(); + }, + }), + (this.gatherCompletions = function (e, t) { + var n = e.getSession(), + r = e.getCursorPosition(), + i = s.getCompletionPrefix(e); + (this.base = n.doc.createAnchor(r.row, r.column - i.length)), + (this.base.$insertRight = !0); + var o = [], + u = e.completers.length; + return ( + e.completers.forEach(function (a, f) { + a.getCompletions(e, n, r, i, function (n, r) { + !n && r && (o = o.concat(r)), + t(null, { + prefix: s.getCompletionPrefix(e), + matches: o, + finished: --u === 0, + }); + }); + }), + !0 + ); + }), + (this.showPopup = function (e) { + this.editor && this.detach(), + (this.activated = !0), + (this.editor = e), + e.completer != this && + (e.completer && e.completer.detach(), (e.completer = this)), + e.on("changeSelection", this.changeListener), + e.on("blur", this.blurListener), + e.on("mousedown", this.mousedownListener), + e.on("mousewheel", this.mousewheelListener), + this.updateCompletions(); + }), + (this.updateCompletions = function (e) { + if (e && this.base && this.completions) { + var t = this.editor.getCursorPosition(), + n = this.editor.session.getTextRange({ start: this.base, end: t }); + if (n == this.completions.filterText) return; + this.completions.setFilter(n); + if (!this.completions.filtered.length) return this.detach(); + if ( + this.completions.filtered.length == 1 && + this.completions.filtered[0].value == n && + !this.completions.filtered[0].snippet + ) + return this.detach(); + this.openPopup(this.editor, n, e); + return; + } + var r = this.gatherCompletionsId; + this.gatherCompletions( + this.editor, + function (t, n) { + var i = function () { + if (!n.finished) return; + return this.detach(); + }.bind(this), + s = n.prefix, + o = n && n.matches; + if (!o || !o.length) return i(); + if (s.indexOf(n.prefix) !== 0 || r != this.gatherCompletionsId) + return; + (this.completions = new c(o)), + this.exactMatch && (this.completions.exactMatch = !0), + this.completions.setFilter(s); + var u = this.completions.filtered; + if (!u.length) return i(); + if (u.length == 1 && u[0].value == s && !u[0].snippet) return i(); + if (this.autoInsert && u.length == 1 && n.finished) + return this.insertMatch(u[0]); + this.openPopup(this.editor, s, e); + }.bind(this), + ); + }), + (this.cancelContextMenu = function () { + this.editor.$mouseHandler.cancelContextMenu(); + }), + (this.updateDocTooltip = function () { + var e = this.popup, + t = e.data, + n = t && (t[e.getHoveredRow()] || t[e.getRow()]), + r = null; + if (!n || !this.editor || !this.popup.isOpen) return this.hideDocTooltip(); + this.editor.completers.some(function (e) { + return e.getDocTooltip && (r = e.getDocTooltip(n)), r; + }), + r || (r = n), + typeof r == "string" && (r = { docText: r }); + if (!r || (!r.docHTML && !r.docText)) return this.hideDocTooltip(); + this.showDocTooltip(r); + }), + (this.showDocTooltip = function (e) { + this.tooltipNode || + ((this.tooltipNode = a.createElement("div")), + (this.tooltipNode.className = "ace_tooltip ace_doc-tooltip"), + (this.tooltipNode.style.margin = 0), + (this.tooltipNode.style.pointerEvents = "auto"), + (this.tooltipNode.tabIndex = -1), + (this.tooltipNode.onblur = this.blurListener.bind(this)), + (this.tooltipNode.onclick = this.onTooltipClick.bind(this))); + var t = this.tooltipNode; + e.docHTML + ? (t.innerHTML = e.docHTML) + : e.docText && (t.textContent = e.docText), + t.parentNode || document.body.appendChild(t); + var n = this.popup, + r = n.container.getBoundingClientRect(); + (t.style.top = n.container.style.top), + (t.style.bottom = n.container.style.bottom), + (t.style.display = "block"), + window.innerWidth - r.right < 320 + ? r.left < 320 + ? n.isTopdown + ? ((t.style.top = r.bottom + "px"), + (t.style.left = r.left + "px"), + (t.style.right = ""), + (t.style.bottom = "")) + : ((t.style.top = + n.container.offsetTop - t.offsetHeight + "px"), + (t.style.left = r.left + "px"), + (t.style.right = ""), + (t.style.bottom = "")) + : ((t.style.right = window.innerWidth - r.left + "px"), + (t.style.left = "")) + : ((t.style.left = r.right + 1 + "px"), (t.style.right = "")); + }), + (this.hideDocTooltip = function () { + this.tooltipTimer.cancel(); + if (!this.tooltipNode) return; + var e = this.tooltipNode; + !this.editor.isFocused() && + document.activeElement == e && + this.editor.focus(), + (this.tooltipNode = null), + e.parentNode && e.parentNode.removeChild(e); + }), + (this.onTooltipClick = function (e) { + var t = e.target; + while (t && t != this.tooltipNode) { + if (t.nodeName == "A" && t.href) { + (t.rel = "noreferrer"), (t.target = "_blank"); + break; + } + t = t.parentNode; + } + }); + }).call(l.prototype), + (l.startCommand = { + name: "startAutocomplete", + exec: function (e) { + e.completer || (e.completer = new l()), + (e.completer.autoInsert = !1), + (e.completer.autoSelect = !0), + e.completer.showPopup(e), + e.completer.cancelContextMenu(); + }, + bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space", + }); + var c = function (e, t) { + (this.all = e), + (this.filtered = e), + (this.filterText = t || ""), + (this.exactMatch = !1); + }; + (function () { + (this.setFilter = function (e) { + if (e.length > this.filterText && e.lastIndexOf(this.filterText, 0) === 0) + var t = this.filtered; + else var t = this.all; + (this.filterText = e), + (t = this.filterCompletions(t, this.filterText)), + (t = t.sort(function (e, t) { + return ( + t.exactMatch - e.exactMatch || + t.$score - e.$score || + (e.caption || e.value) < (t.caption || t.value) + ); + })); + var n = null; + (t = t.filter(function (e) { + var t = e.snippet || e.caption || e.value; + return t === n ? !1 : ((n = t), !0); + })), + (this.filtered = t); + }), + (this.filterCompletions = function (e, t) { + var n = [], + r = t.toUpperCase(), + i = t.toLowerCase(); + e: for (var s = 0, o; (o = e[s]); s++) { + var u = o.caption || o.value || o.snippet; + if (!u) continue; + var a = -1, + f = 0, + l = 0, + c, + h; + if (this.exactMatch) { + if (t !== u.substr(0, t.length)) continue e; + } else { + var p = u.toLowerCase().indexOf(i); + if (p > -1) l = p; + else + for (var d = 0; d < t.length; d++) { + var v = u.indexOf(i[d], a + 1), + m = u.indexOf(r[d], a + 1); + c = v >= 0 ? (m < 0 || v < m ? v : m) : m; + if (c < 0) continue e; + (h = c - a - 1), + h > 0 && + (a === -1 && (l += 10), (l += h), (f |= 1 << d)), + (a = c); + } + } + (o.matchMask = f), + (o.exactMatch = l ? 0 : 1), + (o.$score = (o.score || 0) - l), + n.push(o); + } + return n; }); - })(); - \ No newline at end of file + }).call(c.prototype), + (t.Autocomplete = l), + (t.FilteredList = c); + }, + ), + define( + "ace/autocomplete/text_completer", + ["require", "exports", "module", "ace/range"], + function (e, t, n) { + function s(e, t) { + var n = e.getTextRange(r.fromPoints({ row: 0, column: 0 }, t)); + return n.split(i).length - 1; + } + function o(e, t) { + var n = s(e, t), + r = e.getValue().split(i), + o = Object.create(null), + u = r[n]; + return ( + r.forEach(function (e, t) { + if (!e || e === u) return; + var i = Math.abs(n - t), + s = r.length - i; + o[e] ? (o[e] = Math.max(s, o[e])) : (o[e] = s); + }), + o + ); + } + var r = e("../range").Range, + i = /[^a-zA-Z_0-9\$\-\u00C0-\u1FFF\u2C00-\uD7FF\w]+/; + t.getCompletions = function (e, t, n, r, i) { + var s = o(t, n), + u = Object.keys(s); + i( + null, + u.map(function (e) { + return { caption: e, value: e, score: s[e], meta: "local" }; + }), + ); + }; + }, + ), + define( + "ace/ext/language_tools", + [ + "require", + "exports", + "module", + "ace/snippets", + "ace/autocomplete", + "ace/config", + "ace/lib/lang", + "ace/autocomplete/util", + "ace/autocomplete/text_completer", + "ace/editor", + "ace/config", + ], + function (e, t, n) { + "use strict"; + var r = e("../snippets").snippetManager, + i = e("../autocomplete").Autocomplete, + s = e("../config"), + o = e("../lib/lang"), + u = e("../autocomplete/util"), + a = e("../autocomplete/text_completer"), + f = { + getCompletions: function (e, t, n, r, i) { + if (t.$mode.completer) + return t.$mode.completer.getCompletions(e, t, n, r, i); + var s = e.session.getState(n.row), + o = t.$mode.getCompletions(s, t, n, r); + i(null, o); + }, + }, + l = { + getCompletions: function (e, t, n, i, s) { + var o = [], + u = t.getTokenAt(n.row, n.column); + u && + u.type.match( + /(tag-name|tag-open|tag-whitespace|attribute-name|attribute-value)\.xml$/, + ) + ? o.push("html-tag") + : (o = r.getActiveScopes(e)); + var a = r.snippetMap, + f = []; + o.forEach(function (e) { + var t = a[e] || []; + for (var n = t.length; n--; ) { + var r = t[n], + i = r.name || r.tabTrigger; + if (!i) continue; + f.push({ + caption: i, + snippet: r.content, + meta: + r.tabTrigger && !r.name + ? r.tabTrigger + "\u21e5 " + : "snippet", + type: "snippet", + }); + } + }, this), + s(null, f); + }, + getDocTooltip: function (e) { + e.type == "snippet" && + !e.docHTML && + (e.docHTML = [ + "", + o.escapeHTML(e.caption), + "", + "
", + o.escapeHTML(e.snippet), + ].join("")); + }, + }, + c = [l, a, f]; + (t.setCompleters = function (e) { + (c.length = 0), e && c.push.apply(c, e); + }), + (t.addCompleter = function (e) { + c.push(e); + }), + (t.textCompleter = a), + (t.keyWordCompleter = f), + (t.snippetCompleter = l); + var h = { + name: "expandSnippet", + exec: function (e) { + return r.expandWithTab(e); + }, + bindKey: "Tab", + }, + p = function (e, t) { + d(t.session.$mode); + }, + d = function (e) { + var t = e.$id; + r.files || (r.files = {}), v(t), e.modes && e.modes.forEach(d); + }, + v = function (e) { + if (!e || r.files[e]) return; + var t = e.replace("mode", "snippets"); + (r.files[e] = {}), + s.loadModule(t, function (t) { + t && + ((r.files[e] = t), + !t.snippets && + t.snippetText && + (t.snippets = r.parseSnippetFile(t.snippetText)), + r.register(t.snippets || [], t.scope), + t.includeScopes && + ((r.snippetMap[t.scope].includeScopes = t.includeScopes), + t.includeScopes.forEach(function (e) { + v("ace/mode/" + e); + }))); + }); + }, + m = function (e) { + var t = e.editor, + n = t.completer && t.completer.activated; + if (e.command.name === "backspace") + n && !u.getCompletionPrefix(t) && t.completer.detach(); + else if (e.command.name === "insertstring") { + var r = u.getCompletionPrefix(t); + r && + !n && + (t.completer || (t.completer = new i()), + (t.completer.autoInsert = !1), + t.completer.showPopup(t)); + } + }, + g = e("../editor").Editor; + e("../config").defineOptions(g.prototype, "editor", { + enableBasicAutocompletion: { + set: function (e) { + e + ? (this.completers || (this.completers = Array.isArray(e) ? e : c), + this.commands.addCommand(i.startCommand)) + : this.commands.removeCommand(i.startCommand); + }, + value: !1, + }, + enableLiveAutocompletion: { + set: function (e) { + e + ? (this.completers || (this.completers = Array.isArray(e) ? e : c), + this.commands.on("afterExec", m)) + : this.commands.removeListener("afterExec", m); + }, + value: !1, + }, + enableSnippets: { + set: function (e) { + e + ? (this.commands.addCommand(h), this.on("changeMode", p), p(null, this)) + : (this.commands.removeCommand(h), this.off("changeMode", p)); + }, + value: !1, + }, + }); + }, + ); +(function () { + window.require(["ace/ext/language_tools"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/ext-linking.js b/web/static/ace/ext-linking.js index c4a8ad4c3..4e1aed656 100644 --- a/web/static/ace/ext-linking.js +++ b/web/static/ace/ext-linking.js @@ -1,9 +1,49 @@ -define("ace/ext/linking",["require","exports","module","ace/editor","ace/config"],function(e,t,n){function i(e){var n=e.editor,r=e.getAccelKey();if(r){var n=e.editor,i=e.getDocumentPosition(),s=n.session,o=s.getTokenAt(i.row,i.column);t.previousLinkingHover&&t.previousLinkingHover!=o&&n._emit("linkHoverOut"),n._emit("linkHover",{position:i,token:o}),t.previousLinkingHover=o}else t.previousLinkingHover&&(n._emit("linkHoverOut"),t.previousLinkingHover=!1)}function s(e){var t=e.getAccelKey(),n=e.getButton();if(n==0&&t){var r=e.editor,i=e.getDocumentPosition(),s=r.session,o=s.getTokenAt(i.row,i.column);r._emit("linkClick",{position:i,token:o})}}var r=e("ace/editor").Editor;e("../config").defineOptions(r.prototype,"editor",{enableLinking:{set:function(e){e?(this.on("click",s),this.on("mousemove",i)):(this.off("click",s),this.off("mousemove",i))},value:!1}}),t.previousLinkingHover=!1}); - (function() { - window.require(["ace/ext/linking"], function(m) { - if (typeof module == "object" && typeof exports == "object" && module) { - module.exports = m; - } - }); - })(); - \ No newline at end of file +define("ace/ext/linking", ["require", "exports", "module", "ace/editor", "ace/config"], function ( + e, + t, + n, +) { + function i(e) { + var n = e.editor, + r = e.getAccelKey(); + if (r) { + var n = e.editor, + i = e.getDocumentPosition(), + s = n.session, + o = s.getTokenAt(i.row, i.column); + t.previousLinkingHover && t.previousLinkingHover != o && n._emit("linkHoverOut"), + n._emit("linkHover", { position: i, token: o }), + (t.previousLinkingHover = o); + } else t.previousLinkingHover && (n._emit("linkHoverOut"), (t.previousLinkingHover = !1)); + } + function s(e) { + var t = e.getAccelKey(), + n = e.getButton(); + if (n == 0 && t) { + var r = e.editor, + i = e.getDocumentPosition(), + s = r.session, + o = s.getTokenAt(i.row, i.column); + r._emit("linkClick", { position: i, token: o }); + } + } + var r = e("ace/editor").Editor; + e("../config").defineOptions(r.prototype, "editor", { + enableLinking: { + set: function (e) { + e + ? (this.on("click", s), this.on("mousemove", i)) + : (this.off("click", s), this.off("mousemove", i)); + }, + value: !1, + }, + }), + (t.previousLinkingHover = !1); +}); +(function () { + window.require(["ace/ext/linking"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/ext-modelist.js b/web/static/ace/ext-modelist.js index f4a60d691..358629323 100644 --- a/web/static/ace/ext-modelist.js +++ b/web/static/ace/ext-modelist.js @@ -1,9 +1,213 @@ -define("ace/ext/modelist",["require","exports","module"],function(e,t,n){"use strict";function i(e){var t=a.text,n=e.split(/[\/\\]/).pop();for(var i=0;i0?t.getSelection().moveCursorTo(n.row-1,t.session.getLine(n.row-1).length):t.getSelection().isEmpty()?n.column+=1:n.setPosition(n.row,n.column+1))}function a(e){e.editor.session.$bidiHandler.isMoveLeftOperation=/gotoleft|selectleft|backspace|removewordleft/.test(e.command.name)}function f(e,t){t.$bidiHandler.currentRow=null;if(t.$bidiHandler.isRtlLine(e.start.row)&&e.action==="insert"&&e.lines.length>1)for(var n=e.start.row;n 0 + ? t.getSelection().moveCursorTo(n.row - 1, t.session.getLine(n.row - 1).length) + : t.getSelection().isEmpty() + ? (n.column += 1) + : n.setPosition(n.row, n.column + 1)); + } + function a(e) { + e.editor.session.$bidiHandler.isMoveLeftOperation = + /gotoleft|selectleft|backspace|removewordleft/.test(e.command.name); + } + function f(e, t) { + t.$bidiHandler.currentRow = null; + if (t.$bidiHandler.isRtlLine(e.start.row) && e.action === "insert" && e.lines.length > 1) + for (var n = e.start.row; n < e.end.row; n++) + t.getLine(n + 1).charAt(0) !== t.$bidiHandler.RLE && + (t.getDocument().$lines[n + 1] = t.$bidiHandler.RLE + t.getLine(n + 1)); + } + function l(e, t) { + var n = t.session, + r = n.$bidiHandler, + i = t.$textLayer.$lines.cells, + s = t.layerConfig.width - t.layerConfig.padding + "px"; + i.forEach(function (e) { + var t = e.element.style; + r && r.isRtlLine(e.row) + ? ((t.direction = "rtl"), (t.textAlign = "right"), (t.width = s)) + : ((t.direction = ""), (t.textAlign = ""), (t.width = "")); + }); + } + function c(e) { + function n(e) { + var t = e.element.style; + t.direction = t.textAlign = t.width = ""; + } + var t = e.$textLayer.$lines; + t.cells.forEach(n), t.cellCache.forEach(n); + } + var r = e("ace/lib/dom"), + i = e("ace/lib/lang"), + s = [ + { + name: "leftToRight", + bindKey: { win: "Ctrl-Alt-Shift-L", mac: "Command-Alt-Shift-L" }, + exec: function (e) { + e.session.$bidiHandler.setRtlDirection(e, !1); + }, + readOnly: !0, + }, + { + name: "rightToLeft", + bindKey: { win: "Ctrl-Alt-Shift-R", mac: "Command-Alt-Shift-R" }, + exec: function (e) { + e.session.$bidiHandler.setRtlDirection(e, !0); + }, + readOnly: !0, + }, + ], + o = e("../editor").Editor; + e("../config").defineOptions(o.prototype, "editor", { + rtlText: { + set: function (e) { + e + ? (this.on("session", f), + this.on("changeSelection", u), + this.renderer.on("afterRender", l), + this.commands.on("exec", a), + this.commands.addCommands(s)) + : (this.off("session", f), + this.off("changeSelection", u), + this.renderer.off("afterRender", l), + this.commands.off("exec", a), + this.commands.removeCommands(s), + c(this.renderer)), + this.renderer.updateFull(); + }, + }, + }); +}); +(function () { + window.require(["ace/ext/rtl"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/ext-searchbox.js b/web/static/ace/ext-searchbox.js index 163f5e9b3..e2b54f542 100644 --- a/web/static/ace/ext-searchbox.js +++ b/web/static/ace/ext-searchbox.js @@ -1,9 +1,310 @@ -define("ace/ext/searchbox",["require","exports","module","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/keyboard/hash_handler","ace/lib/keys"],function(e,t,n){"use strict";var r=e("../lib/dom"),i=e("../lib/lang"),s=e("../lib/event"),o='.ace_search {background-color: #ddd;color: #666;border: 1px solid #cbcbcb;border-top: 0 none;overflow: hidden;margin: 0;padding: 4px 6px 0 4px;position: absolute;top: 0;z-index: 99;white-space: normal;}.ace_search.left {border-left: 0 none;border-radius: 0px 0px 5px 0px;left: 0;}.ace_search.right {border-radius: 0px 0px 0px 5px;border-right: 0 none;right: 0;}.ace_search_form, .ace_replace_form {margin: 0 20px 4px 0;overflow: hidden;line-height: 1.9;}.ace_replace_form {margin-right: 0;}.ace_search_form.ace_nomatch {outline: 1px solid red;}.ace_search_field {border-radius: 3px 0 0 3px;background-color: white;color: black;border: 1px solid #cbcbcb;border-right: 0 none;outline: 0;padding: 0;font-size: inherit;margin: 0;line-height: inherit;padding: 0 6px;min-width: 17em;vertical-align: top;min-height: 1.8em;box-sizing: content-box;}.ace_searchbtn {border: 1px solid #cbcbcb;line-height: inherit;display: inline-block;padding: 0 6px;background: #fff;border-right: 0 none;border-left: 1px solid #dcdcdc;cursor: pointer;margin: 0;position: relative;color: #666;}.ace_searchbtn:last-child {border-radius: 0 3px 3px 0;border-right: 1px solid #cbcbcb;}.ace_searchbtn:disabled {background: none;cursor: default;}.ace_searchbtn:hover {background-color: #eef1f6;}.ace_searchbtn.prev, .ace_searchbtn.next {padding: 0px 0.7em}.ace_searchbtn.prev:after, .ace_searchbtn.next:after {content: "";border: solid 2px #888;width: 0.5em;height: 0.5em;border-width: 2px 0 0 2px;display:inline-block;transform: rotate(-45deg);}.ace_searchbtn.next:after {border-width: 0 2px 2px 0 ;}.ace_searchbtn_close {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;border-radius: 50%;border: 0 none;color: #656565;cursor: pointer;font: 16px/16px Arial;padding: 0;height: 14px;width: 14px;top: 9px;right: 7px;position: absolute;}.ace_searchbtn_close:hover {background-color: #656565;background-position: 50% 100%;color: white;}.ace_button {margin-left: 2px;cursor: pointer;-webkit-user-select: none;-moz-user-select: none;-o-user-select: none;-ms-user-select: none;user-select: none;overflow: hidden;opacity: 0.7;border: 1px solid rgba(100,100,100,0.23);padding: 1px;box-sizing: border-box!important;color: black;}.ace_button:hover {background-color: #eee;opacity:1;}.ace_button:active {background-color: #ddd;}.ace_button.checked {border-color: #3399ff;opacity:1;}.ace_search_options{margin-bottom: 3px;text-align: right;-webkit-user-select: none;-moz-user-select: none;-o-user-select: none;-ms-user-select: none;user-select: none;clear: both;}.ace_search_counter {float: left;font-family: arial;padding: 0 8px;}',u=e("../keyboard/hash_handler").HashHandler,a=e("../lib/keys"),f=999;r.importCssString(o,"ace_searchbox");var l=''.replace(/> +/g,">"),c=function(e,t,n){var i=r.createElement("div");i.innerHTML=l,this.element=i.firstChild,this.setSession=this.setSession.bind(this),this.$init(),this.setEditor(e),r.importCssString(o,"ace_searchbox",e.container)};(function(){this.setEditor=function(e){e.searchBox=this,e.renderer.scroller.appendChild(this.element),this.editor=e},this.setSession=function(e){this.searchRange=null,this.$syncOptions(!0)},this.$initElements=function(e){this.searchBox=e.querySelector(".ace_search_form"),this.replaceBox=e.querySelector(".ace_replace_form"),this.searchOption=e.querySelector("[action=searchInSelection]"),this.replaceOption=e.querySelector("[action=toggleReplace]"),this.regExpOption=e.querySelector("[action=toggleRegexpMode]"),this.caseSensitiveOption=e.querySelector("[action=toggleCaseSensitive]"),this.wholeWordOption=e.querySelector("[action=toggleWholeWords]"),this.searchInput=this.searchBox.querySelector(".ace_search_field"),this.replaceInput=this.replaceBox.querySelector(".ace_search_field"),this.searchCounter=e.querySelector(".ace_search_counter")},this.$init=function(){var e=this.element;this.$initElements(e);var t=this;s.addListener(e,"mousedown",function(e){setTimeout(function(){t.activeInput.focus()},0),s.stopPropagation(e)}),s.addListener(e,"click",function(e){var n=e.target||e.srcElement,r=n.getAttribute("action");r&&t[r]?t[r]():t.$searchBarKb.commands[r]&&t.$searchBarKb.commands[r].exec(t),s.stopPropagation(e)}),s.addCommandKeyListener(e,function(e,n,r){var i=a.keyCodeToString(r),o=t.$searchBarKb.findKeyCommand(n,i);o&&o.exec&&(o.exec(t),s.stopEvent(e))}),this.$onChange=i.delayedCall(function(){t.find(!1,!1)}),s.addListener(this.searchInput,"input",function(){t.$onChange.schedule(20)}),s.addListener(this.searchInput,"focus",function(){t.activeInput=t.searchInput,t.searchInput.value&&t.highlight()}),s.addListener(this.replaceInput,"focus",function(){t.activeInput=t.replaceInput,t.searchInput.value&&t.highlight()})},this.$closeSearchBarKb=new u([{bindKey:"Esc",name:"closeSearchBar",exec:function(e){e.searchBox.hide()}}]),this.$searchBarKb=new u,this.$searchBarKb.bindKeys({"Ctrl-f|Command-f":function(e){var t=e.isReplace=!e.isReplace;e.replaceBox.style.display=t?"":"none",e.replaceOption.checked=!1,e.$syncOptions(),e.searchInput.focus()},"Ctrl-H|Command-Option-F":function(e){e.replaceOption.checked=!0,e.$syncOptions(),e.replaceInput.focus()},"Ctrl-G|Command-G":function(e){e.findNext()},"Ctrl-Shift-G|Command-Shift-G":function(e){e.findPrev()},esc:function(e){setTimeout(function(){e.hide()})},Return:function(e){e.activeInput==e.replaceInput&&e.replace(),e.findNext()},"Shift-Return":function(e){e.activeInput==e.replaceInput&&e.replace(),e.findPrev()},"Alt-Return":function(e){e.activeInput==e.replaceInput&&e.replaceAll(),e.findAll()},Tab:function(e){(e.activeInput==e.replaceInput?e.searchInput:e.replaceInput).focus()}}),this.$searchBarKb.addCommands([{name:"toggleRegexpMode",bindKey:{win:"Alt-R|Alt-/",mac:"Ctrl-Alt-R|Ctrl-Alt-/"},exec:function(e){e.regExpOption.checked=!e.regExpOption.checked,e.$syncOptions()}},{name:"toggleCaseSensitive",bindKey:{win:"Alt-C|Alt-I",mac:"Ctrl-Alt-R|Ctrl-Alt-I"},exec:function(e){e.caseSensitiveOption.checked=!e.caseSensitiveOption.checked,e.$syncOptions()}},{name:"toggleWholeWords",bindKey:{win:"Alt-B|Alt-W",mac:"Ctrl-Alt-B|Ctrl-Alt-W"},exec:function(e){e.wholeWordOption.checked=!e.wholeWordOption.checked,e.$syncOptions()}},{name:"toggleReplace",exec:function(e){e.replaceOption.checked=!e.replaceOption.checked,e.$syncOptions()}},{name:"searchInSelection",exec:function(e){e.searchOption.checked=!e.searchRange,e.setSearchRange(e.searchOption.checked&&e.editor.getSelectionRange()),e.$syncOptions()}}]),this.setSearchRange=function(e){this.searchRange=e,e?this.searchRangeMarker=this.editor.session.addMarker(e,"ace_active-line"):this.searchRangeMarker&&(this.editor.session.removeMarker(this.searchRangeMarker),this.searchRangeMarker=null)},this.$syncOptions=function(e){r.setCssClass(this.replaceOption,"checked",this.searchRange),r.setCssClass(this.searchOption,"checked",this.searchOption.checked),this.replaceOption.textContent=this.replaceOption.checked?"-":"+",r.setCssClass(this.regExpOption,"checked",this.regExpOption.checked),r.setCssClass(this.wholeWordOption,"checked",this.wholeWordOption.checked),r.setCssClass(this.caseSensitiveOption,"checked",this.caseSensitiveOption.checked),this.replaceBox.style.display=this.replaceOption.checked?"":"none",this.find(!1,!1,e)},this.highlight=function(e){this.editor.session.highlight(e||this.editor.$search.$options.re),this.editor.renderer.updateBackMarkers()},this.find=function(e,t,n){var i=this.editor.find(this.searchInput.value,{skipCurrent:e,backwards:t,wrap:!0,regExp:this.regExpOption.checked,caseSensitive:this.caseSensitiveOption.checked,wholeWord:this.wholeWordOption.checked,preventScroll:n,range:this.searchRange}),s=!i&&this.searchInput.value;r.setCssClass(this.searchBox,"ace_nomatch",s),this.editor._emit("findSearchBox",{match:!s}),this.highlight(),this.updateCounter()},this.updateCounter=function(){var e=this.editor,t=e.$search.$options.re,n=0,r=0;if(t){var i=this.searchRange?e.session.getTextRange(this.searchRange):e.getValue(),s=e.session.doc.positionToIndex(e.selection.anchor);this.searchRange&&(s-=e.session.doc.positionToIndex(this.searchRange.start));var o=t.lastIndex=0,u;while(u=t.exec(i)){n++,o=u.index,o<=s&&r++;if(n>f)break;if(!u[0]){t.lastIndex=o+=1;if(o>=i.length)break}}}this.searchCounter.textContent=r+" of "+(n>f?f+"+":n)},this.findNext=function(){this.find(!0,!1)},this.findPrev=function(){this.find(!0,!0)},this.findAll=function(){var e=this.editor.findAll(this.searchInput.value,{regExp:this.regExpOption.checked,caseSensitive:this.caseSensitiveOption.checked,wholeWord:this.wholeWordOption.checked}),t=!e&&this.searchInput.value;r.setCssClass(this.searchBox,"ace_nomatch",t),this.editor._emit("findSearchBox",{match:!t}),this.highlight(),this.hide()},this.replace=function(){this.editor.getReadOnly()||this.editor.replace(this.replaceInput.value)},this.replaceAndFindNext=function(){this.editor.getReadOnly()||(this.editor.replace(this.replaceInput.value),this.findNext())},this.replaceAll=function(){this.editor.getReadOnly()||this.editor.replaceAll(this.replaceInput.value)},this.hide=function(){this.active=!1,this.setSearchRange(null),this.editor.off("changeSession",this.setSession),this.element.style.display="none",this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb),this.editor.focus()},this.show=function(e,t){this.active=!0,this.editor.on("changeSession",this.setSession),this.element.style.display="",this.replaceOption.checked=t,e&&(this.searchInput.value=e),this.searchInput.focus(),this.searchInput.select(),this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb),this.$syncOptions(!0)},this.isFocused=function(){var e=document.activeElement;return e==this.searchInput||e==this.replaceInput}}).call(c.prototype),t.SearchBox=c,t.Search=function(e,t){var n=e.searchBox||new c(e);n.show(e.session.getTextRange(),t)}}); - (function() { - window.require(["ace/ext/searchbox"], function(m) { - if (typeof module == "object" && typeof exports == "object" && module) { - module.exports = m; - } +define("ace/ext/searchbox", [ + "require", + "exports", + "module", + "ace/lib/dom", + "ace/lib/lang", + "ace/lib/event", + "ace/keyboard/hash_handler", + "ace/lib/keys", +], function (e, t, n) { + "use strict"; + var r = e("../lib/dom"), + i = e("../lib/lang"), + s = e("../lib/event"), + o = + '.ace_search {background-color: #ddd;color: #666;border: 1px solid #cbcbcb;border-top: 0 none;overflow: hidden;margin: 0;padding: 4px 6px 0 4px;position: absolute;top: 0;z-index: 99;white-space: normal;}.ace_search.left {border-left: 0 none;border-radius: 0px 0px 5px 0px;left: 0;}.ace_search.right {border-radius: 0px 0px 0px 5px;border-right: 0 none;right: 0;}.ace_search_form, .ace_replace_form {margin: 0 20px 4px 0;overflow: hidden;line-height: 1.9;}.ace_replace_form {margin-right: 0;}.ace_search_form.ace_nomatch {outline: 1px solid red;}.ace_search_field {border-radius: 3px 0 0 3px;background-color: white;color: black;border: 1px solid #cbcbcb;border-right: 0 none;outline: 0;padding: 0;font-size: inherit;margin: 0;line-height: inherit;padding: 0 6px;min-width: 17em;vertical-align: top;min-height: 1.8em;box-sizing: content-box;}.ace_searchbtn {border: 1px solid #cbcbcb;line-height: inherit;display: inline-block;padding: 0 6px;background: #fff;border-right: 0 none;border-left: 1px solid #dcdcdc;cursor: pointer;margin: 0;position: relative;color: #666;}.ace_searchbtn:last-child {border-radius: 0 3px 3px 0;border-right: 1px solid #cbcbcb;}.ace_searchbtn:disabled {background: none;cursor: default;}.ace_searchbtn:hover {background-color: #eef1f6;}.ace_searchbtn.prev, .ace_searchbtn.next {padding: 0px 0.7em}.ace_searchbtn.prev:after, .ace_searchbtn.next:after {content: "";border: solid 2px #888;width: 0.5em;height: 0.5em;border-width: 2px 0 0 2px;display:inline-block;transform: rotate(-45deg);}.ace_searchbtn.next:after {border-width: 0 2px 2px 0 ;}.ace_searchbtn_close {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;border-radius: 50%;border: 0 none;color: #656565;cursor: pointer;font: 16px/16px Arial;padding: 0;height: 14px;width: 14px;top: 9px;right: 7px;position: absolute;}.ace_searchbtn_close:hover {background-color: #656565;background-position: 50% 100%;color: white;}.ace_button {margin-left: 2px;cursor: pointer;-webkit-user-select: none;-moz-user-select: none;-o-user-select: none;-ms-user-select: none;user-select: none;overflow: hidden;opacity: 0.7;border: 1px solid rgba(100,100,100,0.23);padding: 1px;box-sizing: border-box!important;color: black;}.ace_button:hover {background-color: #eee;opacity:1;}.ace_button:active {background-color: #ddd;}.ace_button.checked {border-color: #3399ff;opacity:1;}.ace_search_options{margin-bottom: 3px;text-align: right;-webkit-user-select: none;-moz-user-select: none;-o-user-select: none;-ms-user-select: none;user-select: none;clear: both;}.ace_search_counter {float: left;font-family: arial;padding: 0 8px;}', + u = e("../keyboard/hash_handler").HashHandler, + a = e("../lib/keys"), + f = 999; + r.importCssString(o, "ace_searchbox"); + var l = + ''.replace( + /> +/g, + ">", + ), + c = function (e, t, n) { + var i = r.createElement("div"); + (i.innerHTML = l), + (this.element = i.firstChild), + (this.setSession = this.setSession.bind(this)), + this.$init(), + this.setEditor(e), + r.importCssString(o, "ace_searchbox", e.container); + }; + (function () { + (this.setEditor = function (e) { + (e.searchBox = this), e.renderer.scroller.appendChild(this.element), (this.editor = e); + }), + (this.setSession = function (e) { + (this.searchRange = null), this.$syncOptions(!0); + }), + (this.$initElements = function (e) { + (this.searchBox = e.querySelector(".ace_search_form")), + (this.replaceBox = e.querySelector(".ace_replace_form")), + (this.searchOption = e.querySelector("[action=searchInSelection]")), + (this.replaceOption = e.querySelector("[action=toggleReplace]")), + (this.regExpOption = e.querySelector("[action=toggleRegexpMode]")), + (this.caseSensitiveOption = e.querySelector("[action=toggleCaseSensitive]")), + (this.wholeWordOption = e.querySelector("[action=toggleWholeWords]")), + (this.searchInput = this.searchBox.querySelector(".ace_search_field")), + (this.replaceInput = this.replaceBox.querySelector(".ace_search_field")), + (this.searchCounter = e.querySelector(".ace_search_counter")); + }), + (this.$init = function () { + var e = this.element; + this.$initElements(e); + var t = this; + s.addListener(e, "mousedown", function (e) { + setTimeout(function () { + t.activeInput.focus(); + }, 0), + s.stopPropagation(e); + }), + s.addListener(e, "click", function (e) { + var n = e.target || e.srcElement, + r = n.getAttribute("action"); + r && t[r] + ? t[r]() + : t.$searchBarKb.commands[r] && t.$searchBarKb.commands[r].exec(t), + s.stopPropagation(e); + }), + s.addCommandKeyListener(e, function (e, n, r) { + var i = a.keyCodeToString(r), + o = t.$searchBarKb.findKeyCommand(n, i); + o && o.exec && (o.exec(t), s.stopEvent(e)); + }), + (this.$onChange = i.delayedCall(function () { + t.find(!1, !1); + })), + s.addListener(this.searchInput, "input", function () { + t.$onChange.schedule(20); + }), + s.addListener(this.searchInput, "focus", function () { + (t.activeInput = t.searchInput), t.searchInput.value && t.highlight(); + }), + s.addListener(this.replaceInput, "focus", function () { + (t.activeInput = t.replaceInput), t.searchInput.value && t.highlight(); + }); + }), + (this.$closeSearchBarKb = new u([ + { + bindKey: "Esc", + name: "closeSearchBar", + exec: function (e) { + e.searchBox.hide(); + }, + }, + ])), + (this.$searchBarKb = new u()), + this.$searchBarKb.bindKeys({ + "Ctrl-f|Command-f": function (e) { + var t = (e.isReplace = !e.isReplace); + (e.replaceBox.style.display = t ? "" : "none"), + (e.replaceOption.checked = !1), + e.$syncOptions(), + e.searchInput.focus(); + }, + "Ctrl-H|Command-Option-F": function (e) { + (e.replaceOption.checked = !0), e.$syncOptions(), e.replaceInput.focus(); + }, + "Ctrl-G|Command-G": function (e) { + e.findNext(); + }, + "Ctrl-Shift-G|Command-Shift-G": function (e) { + e.findPrev(); + }, + esc: function (e) { + setTimeout(function () { + e.hide(); }); - })(); - \ No newline at end of file + }, + Return: function (e) { + e.activeInput == e.replaceInput && e.replace(), e.findNext(); + }, + "Shift-Return": function (e) { + e.activeInput == e.replaceInput && e.replace(), e.findPrev(); + }, + "Alt-Return": function (e) { + e.activeInput == e.replaceInput && e.replaceAll(), e.findAll(); + }, + Tab: function (e) { + (e.activeInput == e.replaceInput ? e.searchInput : e.replaceInput).focus(); + }, + }), + this.$searchBarKb.addCommands([ + { + name: "toggleRegexpMode", + bindKey: { win: "Alt-R|Alt-/", mac: "Ctrl-Alt-R|Ctrl-Alt-/" }, + exec: function (e) { + (e.regExpOption.checked = !e.regExpOption.checked), e.$syncOptions(); + }, + }, + { + name: "toggleCaseSensitive", + bindKey: { win: "Alt-C|Alt-I", mac: "Ctrl-Alt-R|Ctrl-Alt-I" }, + exec: function (e) { + (e.caseSensitiveOption.checked = !e.caseSensitiveOption.checked), + e.$syncOptions(); + }, + }, + { + name: "toggleWholeWords", + bindKey: { win: "Alt-B|Alt-W", mac: "Ctrl-Alt-B|Ctrl-Alt-W" }, + exec: function (e) { + (e.wholeWordOption.checked = !e.wholeWordOption.checked), e.$syncOptions(); + }, + }, + { + name: "toggleReplace", + exec: function (e) { + (e.replaceOption.checked = !e.replaceOption.checked), e.$syncOptions(); + }, + }, + { + name: "searchInSelection", + exec: function (e) { + (e.searchOption.checked = !e.searchRange), + e.setSearchRange( + e.searchOption.checked && e.editor.getSelectionRange(), + ), + e.$syncOptions(); + }, + }, + ]), + (this.setSearchRange = function (e) { + (this.searchRange = e), + e + ? (this.searchRangeMarker = this.editor.session.addMarker( + e, + "ace_active-line", + )) + : this.searchRangeMarker && + (this.editor.session.removeMarker(this.searchRangeMarker), + (this.searchRangeMarker = null)); + }), + (this.$syncOptions = function (e) { + r.setCssClass(this.replaceOption, "checked", this.searchRange), + r.setCssClass(this.searchOption, "checked", this.searchOption.checked), + (this.replaceOption.textContent = this.replaceOption.checked ? "-" : "+"), + r.setCssClass(this.regExpOption, "checked", this.regExpOption.checked), + r.setCssClass(this.wholeWordOption, "checked", this.wholeWordOption.checked), + r.setCssClass( + this.caseSensitiveOption, + "checked", + this.caseSensitiveOption.checked, + ), + (this.replaceBox.style.display = this.replaceOption.checked ? "" : "none"), + this.find(!1, !1, e); + }), + (this.highlight = function (e) { + this.editor.session.highlight(e || this.editor.$search.$options.re), + this.editor.renderer.updateBackMarkers(); + }), + (this.find = function (e, t, n) { + var i = this.editor.find(this.searchInput.value, { + skipCurrent: e, + backwards: t, + wrap: !0, + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked, + preventScroll: n, + range: this.searchRange, + }), + s = !i && this.searchInput.value; + r.setCssClass(this.searchBox, "ace_nomatch", s), + this.editor._emit("findSearchBox", { match: !s }), + this.highlight(), + this.updateCounter(); + }), + (this.updateCounter = function () { + var e = this.editor, + t = e.$search.$options.re, + n = 0, + r = 0; + if (t) { + var i = this.searchRange + ? e.session.getTextRange(this.searchRange) + : e.getValue(), + s = e.session.doc.positionToIndex(e.selection.anchor); + this.searchRange && + (s -= e.session.doc.positionToIndex(this.searchRange.start)); + var o = (t.lastIndex = 0), + u; + while ((u = t.exec(i))) { + n++, (o = u.index), o <= s && r++; + if (n > f) break; + if (!u[0]) { + t.lastIndex = o += 1; + if (o >= i.length) break; + } + } + } + this.searchCounter.textContent = r + " of " + (n > f ? f + "+" : n); + }), + (this.findNext = function () { + this.find(!0, !1); + }), + (this.findPrev = function () { + this.find(!0, !0); + }), + (this.findAll = function () { + var e = this.editor.findAll(this.searchInput.value, { + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked, + }), + t = !e && this.searchInput.value; + r.setCssClass(this.searchBox, "ace_nomatch", t), + this.editor._emit("findSearchBox", { match: !t }), + this.highlight(), + this.hide(); + }), + (this.replace = function () { + this.editor.getReadOnly() || this.editor.replace(this.replaceInput.value); + }), + (this.replaceAndFindNext = function () { + this.editor.getReadOnly() || + (this.editor.replace(this.replaceInput.value), this.findNext()); + }), + (this.replaceAll = function () { + this.editor.getReadOnly() || this.editor.replaceAll(this.replaceInput.value); + }), + (this.hide = function () { + (this.active = !1), + this.setSearchRange(null), + this.editor.off("changeSession", this.setSession), + (this.element.style.display = "none"), + this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb), + this.editor.focus(); + }), + (this.show = function (e, t) { + (this.active = !0), + this.editor.on("changeSession", this.setSession), + (this.element.style.display = ""), + (this.replaceOption.checked = t), + e && (this.searchInput.value = e), + this.searchInput.focus(), + this.searchInput.select(), + this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb), + this.$syncOptions(!0); + }), + (this.isFocused = function () { + var e = document.activeElement; + return e == this.searchInput || e == this.replaceInput; + }); + }).call(c.prototype), + (t.SearchBox = c), + (t.Search = function (e, t) { + var n = e.searchBox || new c(e); + n.show(e.session.getTextRange(), t); + }); +}); +(function () { + window.require(["ace/ext/searchbox"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/ext-settings_menu.js b/web/static/ace/ext-settings_menu.js index 6adfb86f6..55f62a058 100644 --- a/web/static/ace/ext-settings_menu.js +++ b/web/static/ace/ext-settings_menu.js @@ -1,13 +1,493 @@ -define("ace/ext/menu_tools/overlay_page",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";var r=e("../../lib/dom"),i="#ace_settingsmenu, #kbshortcutmenu {background-color: #F7F7F7;color: black;box-shadow: -5px 4px 5px rgba(126, 126, 126, 0.55);padding: 1em 0.5em 2em 1em;overflow: auto;position: absolute;margin: 0;bottom: 0;right: 0;top: 0;z-index: 9991;cursor: default;}.ace_dark #ace_settingsmenu, .ace_dark #kbshortcutmenu {box-shadow: -20px 10px 25px rgba(126, 126, 126, 0.25);background-color: rgba(255, 255, 255, 0.6);color: black;}.ace_optionsMenuEntry:hover {background-color: rgba(100, 100, 100, 0.1);transition: all 0.3s}.ace_closeButton {background: rgba(245, 146, 146, 0.5);border: 1px solid #F48A8A;border-radius: 50%;padding: 7px;position: absolute;right: -8px;top: -8px;z-index: 100000;}.ace_closeButton{background: rgba(245, 146, 146, 0.9);}.ace_optionsMenuKey {color: darkslateblue;font-weight: bold;}.ace_optionsMenuCommand {color: darkcyan;font-weight: normal;}.ace_optionsMenuEntry input, .ace_optionsMenuEntry button {vertical-align: middle;}.ace_optionsMenuEntry button[ace_selected_button=true] {background: #e7e7e7;box-shadow: 1px 0px 2px 0px #adadad inset;border-color: #adadad;}.ace_optionsMenuEntry button {background: white;border: 1px solid lightgray;margin: 0px;}.ace_optionsMenuEntry button:hover{background: #f0f0f0;}";r.importCssString(i),n.exports.overlayPage=function(t,n,i,s,o,u){function l(e){e.keyCode===27&&a.click()}i=i?"top: "+i+";":"",o=o?"bottom: "+o+";":"",s=s?"right: "+s+";":"",u=u?"left: "+u+";":"";var a=document.createElement("div"),f=document.createElement("div");a.style.cssText="margin: 0; padding: 0; position: fixed; top:0; bottom:0; left:0; right:0;z-index: 9990; background-color: rgba(0, 0, 0, 0.3);",a.addEventListener("click",function(){document.removeEventListener("keydown",l),a.parentNode.removeChild(a),t.focus(),a=null}),document.addEventListener("keydown",l),f.style.cssText=i+s+o+u,f.addEventListener("click",function(e){e.stopPropagation()});var c=r.createElement("div");c.style.position="relative";var h=r.createElement("div");h.className="ace_closeButton",h.addEventListener("click",function(){a.click()}),c.appendChild(h),f.appendChild(c),f.appendChild(n),a.appendChild(f),document.body.appendChild(a),t.blur()}}),define("ace/ext/modelist",["require","exports","module"],function(e,t,n){"use strict";function i(e){var t=a.text,n=e.split(/[\/\\]/).pop();for(var i=0;i 0!";if(e==this.$splits)return;if(e>this.$splits){while(this.$splitse)t=this.$editors[this.$splits-1],this.$container.removeChild(t.container),this.$splits--;this.resize()},this.getSplits=function(){return this.$splits},this.getEditor=function(e){return this.$editors[e]},this.getCurrentEditor=function(){return this.$cEditor},this.focus=function(){this.$cEditor.focus()},this.blur=function(){this.$cEditor.blur()},this.setTheme=function(e){this.$editors.forEach(function(t){t.setTheme(e)})},this.setKeyboardHandler=function(e){this.$editors.forEach(function(t){t.setKeyboardHandler(e)})},this.forEach=function(e,t){this.$editors.forEach(e,t)},this.$fontSize="",this.setFontSize=function(e){this.$fontSize=e,this.forEach(function(t){t.setFontSize(e)})},this.$cloneSession=function(e){var t=new a(e.getDocument(),e.getMode()),n=e.getUndoManager();return t.setUndoManager(n),t.setTabSize(e.getTabSize()),t.setUseSoftTabs(e.getUseSoftTabs()),t.setOverwrite(e.getOverwrite()),t.setBreakpoints(e.getBreakpoints()),t.setUseWrapMode(e.getUseWrapMode()),t.setUseWorker(e.getUseWorker()),t.setWrapLimitRange(e.$wrapLimitRange.min,e.$wrapLimitRange.max),t.$foldData=e.$cloneFoldData(),t},this.setSession=function(e,t){var n;t==null?n=this.$cEditor:n=this.$editors[t];var r=this.$editors.some(function(t){return t.session===e});return r&&(e=this.$cloneSession(e)),n.setSession(e),e},this.getOrientation=function(){return this.$orientation},this.setOrientation=function(e){if(this.$orientation==e)return;this.$orientation=e,this.resize()},this.resize=function(){var e=this.$container.clientWidth,t=this.$container.clientHeight,n;if(this.$orientation==this.BESIDE){var r=e/this.$splits;for(var i=0;i 0!"; + if (e == this.$splits) return; + if (e > this.$splits) { + while (this.$splits < this.$editors.length && this.$splits < e) + (t = this.$editors[this.$splits]), + this.$container.appendChild(t.container), + t.setFontSize(this.$fontSize), + this.$splits++; + while (this.$splits < e) this.$createEditor(), this.$splits++; + } else + while (this.$splits > e) + (t = this.$editors[this.$splits - 1]), + this.$container.removeChild(t.container), + this.$splits--; + this.resize(); + }), + (this.getSplits = function () { + return this.$splits; + }), + (this.getEditor = function (e) { + return this.$editors[e]; + }), + (this.getCurrentEditor = function () { + return this.$cEditor; + }), + (this.focus = function () { + this.$cEditor.focus(); + }), + (this.blur = function () { + this.$cEditor.blur(); + }), + (this.setTheme = function (e) { + this.$editors.forEach(function (t) { + t.setTheme(e); }); - })(); - \ No newline at end of file + }), + (this.setKeyboardHandler = function (e) { + this.$editors.forEach(function (t) { + t.setKeyboardHandler(e); + }); + }), + (this.forEach = function (e, t) { + this.$editors.forEach(e, t); + }), + (this.$fontSize = ""), + (this.setFontSize = function (e) { + (this.$fontSize = e), + this.forEach(function (t) { + t.setFontSize(e); + }); + }), + (this.$cloneSession = function (e) { + var t = new a(e.getDocument(), e.getMode()), + n = e.getUndoManager(); + return ( + t.setUndoManager(n), + t.setTabSize(e.getTabSize()), + t.setUseSoftTabs(e.getUseSoftTabs()), + t.setOverwrite(e.getOverwrite()), + t.setBreakpoints(e.getBreakpoints()), + t.setUseWrapMode(e.getUseWrapMode()), + t.setUseWorker(e.getUseWorker()), + t.setWrapLimitRange(e.$wrapLimitRange.min, e.$wrapLimitRange.max), + (t.$foldData = e.$cloneFoldData()), + t + ); + }), + (this.setSession = function (e, t) { + var n; + t == null ? (n = this.$cEditor) : (n = this.$editors[t]); + var r = this.$editors.some(function (t) { + return t.session === e; + }); + return r && (e = this.$cloneSession(e)), n.setSession(e), e; + }), + (this.getOrientation = function () { + return this.$orientation; + }), + (this.setOrientation = function (e) { + if (this.$orientation == e) return; + (this.$orientation = e), this.resize(); + }), + (this.resize = function () { + var e = this.$container.clientWidth, + t = this.$container.clientHeight, + n; + if (this.$orientation == this.BESIDE) { + var r = e / this.$splits; + for (var i = 0; i < this.$splits; i++) + (n = this.$editors[i]), + (n.container.style.width = r + "px"), + (n.container.style.top = "0px"), + (n.container.style.left = i * r + "px"), + (n.container.style.height = t + "px"), + n.resize(); + } else { + var s = t / this.$splits; + for (var i = 0; i < this.$splits; i++) + (n = this.$editors[i]), + (n.container.style.width = e + "px"), + (n.container.style.top = i * s + "px"), + (n.container.style.left = "0px"), + (n.container.style.height = s + "px"), + n.resize(); + } + }); + }).call(f.prototype), + (t.Split = f); + }, +), + define("ace/ext/split", ["require", "exports", "module", "ace/split"], function (e, t, n) { + "use strict"; + n.exports = e("../split"); + }); +(function () { + window.require(["ace/ext/split"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/ext-static_highlight.js b/web/static/ace/ext-static_highlight.js index 313ec8e5f..64958bd8c 100644 --- a/web/static/ace/ext-static_highlight.js +++ b/web/static/ace/ext-static_highlight.js @@ -1,9 +1,146 @@ -define("ace/ext/static_highlight",["require","exports","module","ace/edit_session","ace/layer/text","ace/config","ace/lib/dom"],function(e,t,n){"use strict";function a(e){this.type=e,this.style={},this.textContent=""}var r=e("../edit_session").EditSession,i=e("../layer/text").Text,s=".ace_static_highlight {font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'Droid Sans Mono', monospace;font-size: 12px;white-space: pre-wrap}.ace_static_highlight .ace_gutter {width: 2em;text-align: right;padding: 0 3px 0 0;margin-right: 3px;}.ace_static_highlight.ace_show_gutter .ace_line {padding-left: 2.6em;}.ace_static_highlight .ace_line { position: relative; }.ace_static_highlight .ace_gutter-cell {-moz-user-select: -moz-none;-khtml-user-select: none;-webkit-user-select: none;user-select: none;top: 0;bottom: 0;left: 0;position: absolute;}.ace_static_highlight .ace_gutter-cell:before {content: counter(ace_line, decimal);counter-increment: ace_line;}.ace_static_highlight {counter-reset: ace_line;}",o=e("../config"),u=e("../lib/dom");a.prototype.cloneNode=function(){return this},a.prototype.appendChild=function(e){this.textContent+=e.toString()},a.prototype.toString=function(){var e=[];if(this.type!="fragment"){e.push("<",this.type),this.className&&e.push(" class='",this.className,"'");var t=[];for(var n in this.style)t.push(n,":",this.style[n]);t.length&&e.push(" style='",t.join(""),"'"),e.push(">")}return this.textContent&&e.push(this.textContent),this.type!="fragment"&&e.push(""),e.join("")};var f={createTextNode:function(e,t){return e},createElement:function(e){return new a(e)},createFragment:function(){return new a("fragment")}},l=function(){this.config={},this.dom=f};l.prototype=i.prototype;var c=function(e,t,n){var r=e.className.match(/lang-(\w+)/),i=t.mode||r&&"ace/mode/"+r[1];if(!i)return!1;var s=t.theme||"ace/theme/textmate",o="",a=[];if(e.firstElementChild){var f=0;for(var l=0;l"); + } + return ( + this.textContent && e.push(this.textContent), + this.type != "fragment" && e.push(""), + e.join("") + ); + }); + var f = { + createTextNode: function (e, t) { + return e; + }, + createElement: function (e) { + return new a(e); + }, + createFragment: function () { + return new a("fragment"); + }, + }, + l = function () { + (this.config = {}), (this.dom = f); + }; + l.prototype = i.prototype; + var c = function (e, t, n) { + var r = e.className.match(/lang-(\w+)/), + i = t.mode || (r && "ace/mode/" + r[1]); + if (!i) return !1; + var s = t.theme || "ace/theme/textmate", + o = "", + a = []; + if (e.firstElementChild) { + var f = 0; + for (var l = 0; l < e.childNodes.length; l++) { + var h = e.childNodes[l]; + h.nodeType == 3 ? ((f += h.data.length), (o += h.data)) : a.push(f, h); + } + } else (o = e.textContent), t.trim && (o = o.trim()); + c.render(o, i, s, t.firstLineNumber, !t.showGutter, function (t) { + u.importCssString(t.css, "ace_highlight"), (e.innerHTML = t.html); + var r = e.firstChild.firstChild; + for (var i = 0; i < a.length; i += 2) { + var s = t.session.doc.indexToPosition(a[i]), + o = a[i + 1], + f = r.children[s.row]; + f && f.appendChild(o); + } + n && n(); + }); + }; + (c.render = function (e, t, n, i, s, u) { + function h() { + var r = c.renderSync(e, t, n, i, s); + return u ? u(r) : r; + } + var a = 1, + f = r.prototype.$modes; + typeof n == "string" && + (a++, + o.loadModule(["theme", n], function (e) { + (n = e), --a || h(); + })); + var l; + return ( + t && typeof t == "object" && !t.getTokenizer && ((l = t), (t = l.path)), + typeof t == "string" && + (a++, + o.loadModule(["mode", t], function (e) { + if (!f[t] || l) f[t] = new e.Mode(l); + (t = f[t]), --a || h(); + })), + --a || h() + ); + }), + (c.renderSync = function (e, t, n, i, o) { + i = parseInt(i || 1, 10); + var u = new r(""); + u.setUseWorker(!1), u.setMode(t); + var a = new l(); + a.setSession(u), + Object.keys(a.$tabStrings).forEach(function (e) { + if (typeof a.$tabStrings[e] == "string") { + var t = f.createFragment(); + (t.textContent = a.$tabStrings[e]), (a.$tabStrings[e] = t); + } + }), + u.setValue(e); + var c = u.getLength(), + h = f.createElement("div"); + h.className = n.cssClass; + var p = f.createElement("div"); + (p.className = "ace_static_highlight" + (o ? "" : " ace_show_gutter")), + (p.style["counter-reset"] = "ace_line " + (i - 1)); + for (var d = 0; d < c; d++) { + var v = f.createElement("div"); + v.className = "ace_line"; + if (!o) { + var m = f.createElement("span"); + (m.className = "ace_gutter ace_gutter-cell"), + (m.textContent = ""), + v.appendChild(m); + } + a.$renderLine(v, d, !1), p.appendChild(v); + } + return h.appendChild(p), { css: s + n.cssText, html: h.toString(), session: u }; + }), + (n.exports = c), + (n.exports.highlight = c); +}); +(function () { + window.require(["ace/ext/static_highlight"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/ext-statusbar.js b/web/static/ace/ext-statusbar.js index 6dbb601e5..07a8316ae 100644 --- a/web/static/ace/ext-statusbar.js +++ b/web/static/ace/ext-statusbar.js @@ -1,9 +1,55 @@ -define("ace/ext/statusbar",["require","exports","module","ace/lib/dom","ace/lib/lang"],function(e,t,n){"use strict";var r=e("ace/lib/dom"),i=e("ace/lib/lang"),s=function(e,t){this.element=r.createElement("div"),this.element.className="ace_status-indicator",this.element.style.cssText="display: inline-block;",t.appendChild(this.element);var n=i.delayedCall(function(){this.updateStatus(e)}.bind(this)).schedule.bind(null,100);e.on("changeStatus",n),e.on("changeSelection",n),e.on("keyboardActivity",n)};(function(){this.updateStatus=function(e){function n(e,n){e&&t.push(e,n||"|")}var t=[];n(e.keyBinding.getStatusText(e)),e.commands.recording&&n("REC");var r=e.selection,i=r.lead;if(!r.isEmpty()){var s=e.getSelectionRange();n("("+(s.end.row-s.start.row)+":"+(s.end.column-s.start.column)+")"," ")}n(i.row+":"+i.column," "),r.rangeCount&&n("["+r.rangeCount+"]"," "),t.pop(),this.element.textContent=t.join("")}}).call(s.prototype),t.StatusBar=s}); - (function() { - window.require(["ace/ext/statusbar"], function(m) { - if (typeof module == "object" && typeof exports == "object" && module) { - module.exports = m; - } - }); - })(); - \ No newline at end of file +define("ace/ext/statusbar", [ + "require", + "exports", + "module", + "ace/lib/dom", + "ace/lib/lang", +], function (e, t, n) { + "use strict"; + var r = e("ace/lib/dom"), + i = e("ace/lib/lang"), + s = function (e, t) { + (this.element = r.createElement("div")), + (this.element.className = "ace_status-indicator"), + (this.element.style.cssText = "display: inline-block;"), + t.appendChild(this.element); + var n = i + .delayedCall( + function () { + this.updateStatus(e); + }.bind(this), + ) + .schedule.bind(null, 100); + e.on("changeStatus", n), e.on("changeSelection", n), e.on("keyboardActivity", n); + }; + (function () { + this.updateStatus = function (e) { + function n(e, n) { + e && t.push(e, n || "|"); + } + var t = []; + n(e.keyBinding.getStatusText(e)), e.commands.recording && n("REC"); + var r = e.selection, + i = r.lead; + if (!r.isEmpty()) { + var s = e.getSelectionRange(); + n( + "(" + (s.end.row - s.start.row) + ":" + (s.end.column - s.start.column) + ")", + " ", + ); + } + n(i.row + ":" + i.column, " "), + r.rangeCount && n("[" + r.rangeCount + "]", " "), + t.pop(), + (this.element.textContent = t.join("")); + }; + }).call(s.prototype), + (t.StatusBar = s); +}); +(function () { + window.require(["ace/ext/statusbar"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/ext-textarea.js b/web/static/ace/ext-textarea.js index 97232f8fd..28d80429b 100644 --- a/web/static/ace/ext-textarea.js +++ b/web/static/ace/ext-textarea.js @@ -1,9 +1,377 @@ -define("ace/theme/textmate",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";t.isDark=!1,t.cssClass="ace-tm",t.cssText='.ace-tm .ace_gutter {background: #f0f0f0;color: #333;}.ace-tm .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-tm .ace_fold {background-color: #6B72E6;}.ace-tm {background-color: #FFFFFF;color: black;}.ace-tm .ace_cursor {color: black;}.ace-tm .ace_invisible {color: rgb(191, 191, 191);}.ace-tm .ace_storage,.ace-tm .ace_keyword {color: blue;}.ace-tm .ace_constant {color: rgb(197, 6, 11);}.ace-tm .ace_constant.ace_buildin {color: rgb(88, 72, 246);}.ace-tm .ace_constant.ace_language {color: rgb(88, 92, 246);}.ace-tm .ace_constant.ace_library {color: rgb(6, 150, 14);}.ace-tm .ace_invalid {background-color: rgba(255, 0, 0, 0.1);color: red;}.ace-tm .ace_support.ace_function {color: rgb(60, 76, 114);}.ace-tm .ace_support.ace_constant {color: rgb(6, 150, 14);}.ace-tm .ace_support.ace_type,.ace-tm .ace_support.ace_class {color: rgb(109, 121, 222);}.ace-tm .ace_keyword.ace_operator {color: rgb(104, 118, 135);}.ace-tm .ace_string {color: rgb(3, 106, 7);}.ace-tm .ace_comment {color: rgb(76, 136, 107);}.ace-tm .ace_comment.ace_doc {color: rgb(0, 102, 255);}.ace-tm .ace_comment.ace_doc.ace_tag {color: rgb(128, 159, 191);}.ace-tm .ace_constant.ace_numeric {color: rgb(0, 0, 205);}.ace-tm .ace_variable {color: rgb(49, 132, 149);}.ace-tm .ace_xml-pe {color: rgb(104, 104, 91);}.ace-tm .ace_entity.ace_name.ace_function {color: #0000A2;}.ace-tm .ace_heading {color: rgb(12, 7, 255);}.ace-tm .ace_list {color:rgb(185, 6, 144);}.ace-tm .ace_meta.ace_tag {color:rgb(0, 22, 142);}.ace-tm .ace_string.ace_regex {color: rgb(255, 0, 0)}.ace-tm .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-tm.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px white;}.ace-tm .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-tm .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-tm .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-tm .ace_marker-layer .ace_active-line {background: rgba(0, 0, 0, 0.07);}.ace-tm .ace_gutter-active-line {background-color : #dcdcdc;}.ace-tm .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-tm .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;}',t.$id="ace/theme/textmate";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}),define("ace/ext/textarea",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/lib/net","ace/ace","ace/theme/textmate"],function(e,t,n){"use strict";function a(e,t){for(var n in t)e.style[n]=t[n]}function f(e,t){if(e.type!="textarea")throw new Error("Textarea required!");var n=e.parentNode,i=document.createElement("div"),s=function(){var t="position:relative;";["margin-top","margin-left","margin-right","margin-bottom"].forEach(function(n){t+=n+":"+u(e,i,n)+";"});var n=u(e,i,"width")||e.clientWidth+"px",r=u(e,i,"height")||e.clientHeight+"px";t+="height:"+r+";width:"+n+";",t+="display:inline-block;",i.setAttribute("style",t)};r.addListener(window,"resize",s),s(),n.insertBefore(i,e.nextSibling);while(n!==document){if(n.tagName.toUpperCase()==="FORM"){var o=n.onsubmit;n.onsubmit=function(n){e.value=t(),o&&o.call(this,n)};break}n=n.parentNode}return i}function l(t,n,r){s.loadScript(t,function(){e([n],r)})}function c(e,t,n,r,i){function u(e){return e==="true"||e==1}var s=e.getSession(),o=e.renderer;return e.setDisplaySettings=function(t){t==null&&(t=n.style.display=="none"),t?(n.style.display="block",n.hideButton.focus(),e.on("focus",function r(){e.removeListener("focus",r),n.style.display="none"})):e.focus()},e.$setOption=e.setOption,e.$getOption=e.getOption,e.setOption=function(t,n){switch(t){case"mode":e.$setOption("mode","ace/mode/"+n);break;case"theme":e.$setOption("theme","ace/theme/"+n);break;case"keybindings":switch(n){case"vim":e.setKeyboardHandler("ace/keyboard/vim");break;case"emacs":e.setKeyboardHandler("ace/keyboard/emacs");break;default:e.setKeyboardHandler(null)}break;case"wrap":case"fontSize":e.$setOption(t,n);break;default:e.$setOption(t,u(n))}},e.getOption=function(t){switch(t){case"mode":return e.$getOption("mode").substr("ace/mode/".length);case"theme":return e.$getOption("theme").substr("ace/theme/".length);case"keybindings":var n=e.getKeyboardHandler();switch(n&&n.$id){case"ace/keyboard/vim":return"vim";case"ace/keyboard/emacs":return"emacs";default:return"ace"}break;default:return e.$getOption(t)}},e.setOptions(i),e}function h(e,n,i){function f(e,t,n,r){if(!n){e.push("");return}e.push("")}var s=null,o={mode:"Mode:",wrap:"Soft Wrap:",theme:"Theme:",fontSize:"Font Size:",showGutter:"Display Gutter:",keybindings:"Keyboard",showPrintMargin:"Show Print Margin:",useSoftTabs:"Use Soft Tabs:",showInvisibles:"Show Invisibles"},u={mode:{text:"Plain",javascript:"JavaScript",xml:"XML",html:"HTML",css:"CSS",scss:"SCSS",python:"Python",php:"PHP",java:"Java",ruby:"Ruby",c_cpp:"C/C++",coffee:"CoffeeScript",json:"json",perl:"Perl",clojure:"Clojure",ocaml:"OCaml",csharp:"C#",haxe:"haXe",svg:"SVG",textile:"Textile",groovy:"Groovy",liquid:"Liquid",Scala:"Scala"},theme:{clouds:"Clouds",clouds_midnight:"Clouds Midnight",cobalt:"Cobalt",crimson_editor:"Crimson Editor",dawn:"Dawn",gob:"Green on Black",eclipse:"Eclipse",idle_fingers:"Idle Fingers",kr_theme:"Kr Theme",merbivore:"Merbivore",merbivore_soft:"Merbivore Soft",mono_industrial:"Mono Industrial",monokai:"Monokai",pastel_on_dark:"Pastel On Dark",solarized_dark:"Solarized Dark",solarized_light:"Solarized Light",textmate:"Textmate",twilight:"Twilight",vibrant_ink:"Vibrant Ink"},showGutter:s,fontSize:{"10px":"10px","11px":"11px","12px":"12px","14px":"14px","16px":"16px"},wrap:{off:"Off",40:"40",80:"80",free:"Free"},keybindings:{ace:"ace",vim:"vim",emacs:"emacs"},showPrintMargin:s,useSoftTabs:s,showInvisibles:s},a=[];a.push("");for(var l in t.defaultOptions)a.push(""),a.push("");a.push("
SettingValue
",o[l],""),f(a,l,u[l],i.getOption(l)),a.push("
"),e.innerHTML=a.join("");var c=function(e){var t=e.currentTarget;i.setOption(t.title,t.value)},h=function(e){var t=e.currentTarget;i.setOption(t.title,t.checked)},p=e.getElementsByTagName("select");for(var d=0;d", + ); + return; + } + e.push(""); + } + var s = null, + o = { + mode: "Mode:", + wrap: "Soft Wrap:", + theme: "Theme:", + fontSize: "Font Size:", + showGutter: "Display Gutter:", + keybindings: "Keyboard", + showPrintMargin: "Show Print Margin:", + useSoftTabs: "Use Soft Tabs:", + showInvisibles: "Show Invisibles", + }, + u = { + mode: { + text: "Plain", + javascript: "JavaScript", + xml: "XML", + html: "HTML", + css: "CSS", + scss: "SCSS", + python: "Python", + php: "PHP", + java: "Java", + ruby: "Ruby", + c_cpp: "C/C++", + coffee: "CoffeeScript", + json: "json", + perl: "Perl", + clojure: "Clojure", + ocaml: "OCaml", + csharp: "C#", + haxe: "haXe", + svg: "SVG", + textile: "Textile", + groovy: "Groovy", + liquid: "Liquid", + Scala: "Scala", + }, + theme: { + clouds: "Clouds", + clouds_midnight: "Clouds Midnight", + cobalt: "Cobalt", + crimson_editor: "Crimson Editor", + dawn: "Dawn", + gob: "Green on Black", + eclipse: "Eclipse", + idle_fingers: "Idle Fingers", + kr_theme: "Kr Theme", + merbivore: "Merbivore", + merbivore_soft: "Merbivore Soft", + mono_industrial: "Mono Industrial", + monokai: "Monokai", + pastel_on_dark: "Pastel On Dark", + solarized_dark: "Solarized Dark", + solarized_light: "Solarized Light", + textmate: "Textmate", + twilight: "Twilight", + vibrant_ink: "Vibrant Ink", + }, + showGutter: s, + fontSize: { + "10px": "10px", + "11px": "11px", + "12px": "12px", + "14px": "14px", + "16px": "16px", + }, + wrap: { off: "Off", 40: "40", 80: "80", free: "Free" }, + keybindings: { ace: "ace", vim: "vim", emacs: "emacs" }, + showPrintMargin: s, + useSoftTabs: s, + showInvisibles: s, + }, + a = []; + a.push(""); + for (var l in t.defaultOptions) + a.push(""), + a.push(""); + a.push("
SettingValue
", o[l], ""), + f(a, l, u[l], i.getOption(l)), + a.push("
"), (e.innerHTML = a.join("")); + var c = function (e) { + var t = e.currentTarget; + i.setOption(t.title, t.value); + }, + h = function (e) { + var t = e.currentTarget; + i.setOption(t.title, t.checked); + }, + p = e.getElementsByTagName("select"); + for (var d = 0; d < p.length; d++) p[d].onchange = c; + var v = e.getElementsByTagName("input"); + for (var d = 0; d < v.length; d++) v[d].onclick = h; + var m = document.createElement("input"); + (m.type = "button"), + (m.value = "Hide"), + r.addListener(m, "click", function () { + i.setDisplaySettings(!1); + }), + e.appendChild(m), + (e.hideButton = m); + } + var r = e("../lib/event"), + i = e("../lib/useragent"), + s = e("../lib/net"), + o = e("../ace"); + e("../theme/textmate"), (n.exports = t = o); + var u = function (e, t, n) { + var r = e.style[n]; + r || + (window.getComputedStyle + ? (r = window.getComputedStyle(e, "").getPropertyValue(n)) + : (r = e.currentStyle[n])); + if (!r || r == "auto" || r == "intrinsic") r = t.style[n]; + return r; + }; + (t.transformTextarea = function (e, n) { + var s = e.autofocus || document.activeElement == e, + u, + l = f(e, function () { + return u.getValue(); }); - })(); - \ No newline at end of file + (e.style.display = "none"), (l.style.background = "white"); + var p = document.createElement("div"); + a(p, { + top: "0px", + left: "0px", + right: "0px", + bottom: "0px", + border: "1px solid gray", + position: "absolute", + }), + l.appendChild(p); + var d = document.createElement("div"); + a(d, { + position: "absolute", + right: "0px", + bottom: "0px", + cursor: "nw-resize", + border: "solid 9px", + borderColor: "lightblue gray gray #ceade6", + zIndex: 101, + }); + var v = document.createElement("div"), + m = { + top: "0px", + left: "20%", + right: "0px", + bottom: "0px", + position: "absolute", + padding: "5px", + zIndex: 100, + color: "white", + display: "none", + overflow: "auto", + fontSize: "14px", + boxShadow: "-5px 2px 3px gray", + }; + i.isOldIE + ? (m.backgroundColor = "#333") + : (m.backgroundColor = "rgba(0, 0, 0, 0.6)"), + a(v, m), + l.appendChild(v), + (n = n || t.defaultOptions); + var g = o.edit(p); + (u = g.getSession()), + u.setValue(e.value || e.innerHTML), + s && g.focus(), + l.appendChild(d), + c(g, p, v, o, n), + h(v, d, g); + var y = ""; + return ( + r.addListener(d, "mousemove", function (e) { + var t = this.getBoundingClientRect(), + n = e.clientX - t.left, + r = e.clientY - t.top; + n + r < (t.width + t.height) / 2 + ? ((this.style.cursor = "pointer"), (y = "toggle")) + : ((y = "resize"), (this.style.cursor = "nw-resize")); + }), + r.addListener(d, "mousedown", function (e) { + e.preventDefault(); + if (y == "toggle") { + g.setDisplaySettings(); + return; + } + l.style.zIndex = 1e5; + var t = l.getBoundingClientRect(), + n = t.width + t.left - e.clientX, + i = t.height + t.top - e.clientY; + r.capture( + d, + function (e) { + (l.style.width = e.clientX - t.left + n + "px"), + (l.style.height = e.clientY - t.top + i + "px"), + g.resize(); + }, + function () {}, + ); + }), + g + ); + }), + (t.defaultOptions = { + mode: "javascript", + theme: "textmate", + wrap: "off", + fontSize: "12px", + showGutter: "false", + keybindings: "ace", + showPrintMargin: "false", + useSoftTabs: "true", + showInvisibles: "false", + }); + }, + ); +(function () { + window.require(["ace/ext/textarea"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/ext-themelist.js b/web/static/ace/ext-themelist.js index 7287e335f..145b08752 100644 --- a/web/static/ace/ext-themelist.js +++ b/web/static/ace/ext-themelist.js @@ -1,9 +1,22 @@ -define("ace/ext/themelist",["require","exports","module","ace/lib/fixoldbrowsers"],function(e,t,n){"use strict";e("ace/lib/fixoldbrowsers");var r=[["Light"],["Dark","dark"]];t.themesByName={},t.themes=r.map(function(e){var n=e[1]||e[0].replace(/ /g,"_").toLowerCase(),r={caption:e[0],theme:"ace/theme/"+n,isDark:e[2]=="dark",name:n};return t.themesByName[n]=r,r})}); - (function() { - window.require(["ace/ext/themelist"], function(m) { - if (typeof module == "object" && typeof exports == "object" && module) { - module.exports = m; - } - }); - })(); - \ No newline at end of file +define("ace/ext/themelist", ["require", "exports", "module", "ace/lib/fixoldbrowsers"], function ( + e, + t, + n, +) { + "use strict"; + e("ace/lib/fixoldbrowsers"); + var r = [["Light"], ["Dark", "dark"]]; + (t.themesByName = {}), + (t.themes = r.map(function (e) { + var n = e[1] || e[0].replace(/ /g, "_").toLowerCase(), + r = { caption: e[0], theme: "ace/theme/" + n, isDark: e[2] == "dark", name: n }; + return (t.themesByName[n] = r), r; + })); +}); +(function () { + window.require(["ace/ext/themelist"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/ext-whitespace.js b/web/static/ace/ext-whitespace.js index e495dbf3e..4d51a0639 100644 --- a/web/static/ace/ext-whitespace.js +++ b/web/static/ace/ext-whitespace.js @@ -1,9 +1,156 @@ -define("ace/ext/whitespace",["require","exports","module","ace/lib/lang"],function(e,t,n){"use strict";var r=e("../lib/lang");t.$detectIndentation=function(e,t){function c(e){var t=0;for(var r=e;r0&&!(s%l)&&!(f%l)&&(r[l]=(r[l]||0)+1),n[f]=(n[f]||0)+1}s=f}while(up.score&&(p={score:v,length:u})}if(p.score&&p.score>1.4)var m=p.length;if(i>d+1){if(m==1||di+1)return{ch:" ",length:m}},t.detectIndentation=function(e){var n=e.getLines(0,1e3),r=t.$detectIndentation(n)||{};return r.ch&&e.setUseSoftTabs(r.ch==" "),r.length&&e.setTabSize(r.length),r},t.trimTrailingSpace=function(e,t){var n=e.getDocument(),r=n.getAllLines(),i=t&&t.trimEmpty?-1:0,s=[],o=-1;t&&t.keepCursorPosition&&(e.selection.rangeCount?e.selection.rangeList.ranges.forEach(function(e,t,n){var r=n[t+1];if(r&&r.cursor.row==e.cursor.row)return;s.push(e.cursor)}):s.push(e.selection.getCursor()),o=0);var u=s[o]&&s[o].row;for(var a=0,f=r.length;ai&&(c=s[o].column),o++,u=s[o]?s[o].row:-1),c>i&&n.removeInLine(a,c,l.length)}},t.convertIndentation=function(e,t,n){var i=e.getTabString()[0],s=e.getTabSize();n||(n=s),t||(t=i);var o=t==" "?t:r.stringRepeat(t,n),u=e.doc,a=u.getAllLines(),f={},l={};for(var c=0,h=a.length;c 0 && !(s % l) && !(f % l) && (r[l] = (r[l] || 0) + 1), + (n[f] = (n[f] || 0) + 1); + } + s = f; + } + while (u < o && a[a.length - 1] == "\\") a = e[u++]; + } + var h = r.reduce(function (e, t) { + return e + t; + }, 0), + p = { score: 0, length: 0 }, + d = 0; + for (var u = 1; u < 12; u++) { + var v = c(u); + u == 1 ? ((d = v), (v = n[1] ? 0.9 : 0.8), n.length || (v = 0)) : (v /= d), + r[u] && (v += r[u] / h), + v > p.score && (p = { score: v, length: u }); + } + if (p.score && p.score > 1.4) var m = p.length; + if (i > d + 1) { + if (m == 1 || d < i / 4 || p.score < 1.8) m = undefined; + return { ch: " ", length: m }; + } + if (d > i + 1) return { ch: " ", length: m }; + }), + (t.detectIndentation = function (e) { + var n = e.getLines(0, 1e3), + r = t.$detectIndentation(n) || {}; + return r.ch && e.setUseSoftTabs(r.ch == " "), r.length && e.setTabSize(r.length), r; + }), + (t.trimTrailingSpace = function (e, t) { + var n = e.getDocument(), + r = n.getAllLines(), + i = t && t.trimEmpty ? -1 : 0, + s = [], + o = -1; + t && + t.keepCursorPosition && + (e.selection.rangeCount + ? e.selection.rangeList.ranges.forEach(function (e, t, n) { + var r = n[t + 1]; + if (r && r.cursor.row == e.cursor.row) return; + s.push(e.cursor); + }) + : s.push(e.selection.getCursor()), + (o = 0)); + var u = s[o] && s[o].row; + for (var a = 0, f = r.length; a < f; a++) { + var l = r[a], + c = l.search(/\s+$/); + a == u && + (c < s[o].column && c > i && (c = s[o].column), + o++, + (u = s[o] ? s[o].row : -1)), + c > i && n.removeInLine(a, c, l.length); + } + }), + (t.convertIndentation = function (e, t, n) { + var i = e.getTabString()[0], + s = e.getTabSize(); + n || (n = s), t || (t = i); + var o = t == " " ? t : r.stringRepeat(t, n), + u = e.doc, + a = u.getAllLines(), + f = {}, + l = {}; + for (var c = 0, h = a.length; c < h; c++) { + var p = a[c], + d = p.match(/^\s*/)[0]; + if (d) { + var v = e.$getStringScreenWidth(d)[0], + m = Math.floor(v / s), + g = v % s, + y = f[m] || (f[m] = r.stringRepeat(o, m)); + (y += l[g] || (l[g] = r.stringRepeat(" ", g))), + y != d && + (u.removeInLine(c, 0, d.length), + u.insertInLine({ row: c, column: 0 }, y)); + } + } + e.setTabSize(n), e.setUseSoftTabs(t == " "); + }), + (t.$parseStringArg = function (e) { + var t = {}; + /t/.test(e) ? (t.ch = " ") : /s/.test(e) && (t.ch = " "); + var n = e.match(/\d+/); + return n && (t.length = parseInt(n[0], 10)), t; + }), + (t.$parseArg = function (e) { + return e + ? typeof e == "string" + ? t.$parseStringArg(e) + : typeof e.text == "string" + ? t.$parseStringArg(e.text) + : e + : {}; + }), + (t.commands = [ + { + name: "detectIndentation", + exec: function (e) { + t.detectIndentation(e.session); + }, + }, + { + name: "trimTrailingSpace", + exec: function (e, n) { + t.trimTrailingSpace(e.session, n); + }, + }, + { + name: "convertIndentation", + exec: function (e, n) { + var r = t.$parseArg(n); + t.convertIndentation(e.session, r.ch, r.length); + }, + }, + { + name: "setIndentation", + exec: function (e, n) { + var r = t.$parseArg(n); + r.length && e.session.setTabSize(r.length), + r.ch && e.session.setUseSoftTabs(r.ch == " "); + }, + }, + ]); +}); +(function () { + window.require(["ace/ext/whitespace"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/keybinding-emacs.js b/web/static/ace/keybinding-emacs.js index 4df7befc1..c41c8295b 100644 --- a/web/static/ace/keybinding-emacs.js +++ b/web/static/ace/keybinding-emacs.js @@ -1,9 +1,1084 @@ -define("ace/occur",["require","exports","module","ace/lib/oop","ace/range","ace/search","ace/edit_session","ace/search_highlight","ace/lib/dom"],function(e,t,n){"use strict";function a(){}var r=e("./lib/oop"),i=e("./range").Range,s=e("./search").Search,o=e("./edit_session").EditSession,u=e("./search_highlight").SearchHighlight;r.inherits(a,s),function(){this.enter=function(e,t){if(!t.needle)return!1;var n=e.getCursorPosition();this.displayOccurContent(e,t);var r=this.originalToOccurPosition(e.session,n);return e.moveCursorToPosition(r),!0},this.exit=function(e,t){var n=t.translatePosition&&e.getCursorPosition(),r=n&&this.occurToOriginalPosition(e.session,n);return this.displayOriginalContent(e),r&&e.moveCursorToPosition(r),!0},this.highlight=function(e,t){var n=e.$occurHighlight=e.$occurHighlight||e.addDynamicMarker(new u(null,"ace_occur-highlight","text"));n.setRegexp(t),e._emit("changeBackMarker")},this.displayOccurContent=function(e,t){this.$originalSession=e.session;var n=this.matchingLines(e.session,t),r=n.map(function(e){return e.content}),i=new o(r.join("\n"));i.$occur=this,i.$occurMatchingLines=n,e.setSession(i),this.$useEmacsStyleLineStart=this.$originalSession.$useEmacsStyleLineStart,i.$useEmacsStyleLineStart=this.$useEmacsStyleLineStart,this.highlight(i,t.re),i._emit("changeBackMarker")},this.displayOriginalContent=function(e){e.setSession(this.$originalSession),this.$originalSession.$useEmacsStyleLineStart=this.$useEmacsStyleLineStart},this.originalToOccurPosition=function(e,t){var n=e.$occurMatchingLines,r={row:0,column:0};if(!n)return r;for(var i=0;i30&&this.$data.shift()},append:function(e){var t=this.$data.length-1,n=this.$data[t]||"";e&&(n+=e),n&&(this.$data[t]=n)},get:function(e){return e=e||1,this.$data.slice(this.$data.length-e,this.$data.length).reverse().join("\n")},pop:function(){return this.$data.length>1&&this.$data.pop(),this.get()},rotate:function(){return this.$data.unshift(this.$data.pop()),this.get()}}}); - (function() { - window.require(["ace/keyboard/emacs"], function(m) { - if (typeof module == "object" && typeof exports == "object" && module) { - module.exports = m; - } +define( + "ace/occur", + [ + "require", + "exports", + "module", + "ace/lib/oop", + "ace/range", + "ace/search", + "ace/edit_session", + "ace/search_highlight", + "ace/lib/dom", + ], + function (e, t, n) { + "use strict"; + function a() {} + var r = e("./lib/oop"), + i = e("./range").Range, + s = e("./search").Search, + o = e("./edit_session").EditSession, + u = e("./search_highlight").SearchHighlight; + r.inherits(a, s), + function () { + (this.enter = function (e, t) { + if (!t.needle) return !1; + var n = e.getCursorPosition(); + this.displayOccurContent(e, t); + var r = this.originalToOccurPosition(e.session, n); + return e.moveCursorToPosition(r), !0; + }), + (this.exit = function (e, t) { + var n = t.translatePosition && e.getCursorPosition(), + r = n && this.occurToOriginalPosition(e.session, n); + return this.displayOriginalContent(e), r && e.moveCursorToPosition(r), !0; + }), + (this.highlight = function (e, t) { + var n = (e.$occurHighlight = + e.$occurHighlight || + e.addDynamicMarker(new u(null, "ace_occur-highlight", "text"))); + n.setRegexp(t), e._emit("changeBackMarker"); + }), + (this.displayOccurContent = function (e, t) { + this.$originalSession = e.session; + var n = this.matchingLines(e.session, t), + r = n.map(function (e) { + return e.content; + }), + i = new o(r.join("\n")); + (i.$occur = this), + (i.$occurMatchingLines = n), + e.setSession(i), + (this.$useEmacsStyleLineStart = + this.$originalSession.$useEmacsStyleLineStart), + (i.$useEmacsStyleLineStart = this.$useEmacsStyleLineStart), + this.highlight(i, t.re), + i._emit("changeBackMarker"); + }), + (this.displayOriginalContent = function (e) { + e.setSession(this.$originalSession), + (this.$originalSession.$useEmacsStyleLineStart = + this.$useEmacsStyleLineStart); + }), + (this.originalToOccurPosition = function (e, t) { + var n = e.$occurMatchingLines, + r = { row: 0, column: 0 }; + if (!n) return r; + for (var i = 0; i < n.length; i++) + if (n[i].row === t.row) return { row: i, column: t.column }; + return r; + }), + (this.occurToOriginalPosition = function (e, t) { + var n = e.$occurMatchingLines; + return !n || !n[t.row] ? t : { row: n[t.row].row, column: t.column }; + }), + (this.matchingLines = function (e, t) { + t = r.mixin({}, t); + if (!e || !t.needle) return []; + var n = new s(); + return ( + n.set(t), + n.findAll(e).reduce(function (t, n) { + var r = n.start.row, + i = t[t.length - 1]; + return i && i.row === r + ? t + : t.concat({ row: r, content: e.getLine(r) }); + }, []) + ); }); - })(); - \ No newline at end of file + }.call(a.prototype); + var f = e("./lib/dom"); + f.importCssString( + ".ace_occur-highlight {\n border-radius: 4px;\n background-color: rgba(87, 255, 8, 0.25);\n position: absolute;\n z-index: 4;\n box-sizing: border-box;\n box-shadow: 0 0 4px rgb(91, 255, 50);\n}\n.ace_dark .ace_occur-highlight {\n background-color: rgb(80, 140, 85);\n box-shadow: 0 0 4px rgb(60, 120, 70);\n}\n", + "incremental-occur-highlighting", + ), + (t.Occur = a); + }, +), + define( + "ace/commands/occur_commands", + [ + "require", + "exports", + "module", + "ace/config", + "ace/occur", + "ace/keyboard/hash_handler", + "ace/lib/oop", + ], + function (e, t, n) { + function f() {} + var r = e("../config"), + i = e("../occur").Occur, + s = { + name: "occur", + exec: function (e, t) { + var n = !!e.session.$occur, + r = new i().enter(e, t); + r && !n && f.installIn(e); + }, + readOnly: !0, + }, + o = [ + { + name: "occurexit", + bindKey: "esc|Ctrl-G", + exec: function (e) { + var t = e.session.$occur; + if (!t) return; + t.exit(e, {}), e.session.$occur || f.uninstallFrom(e); + }, + readOnly: !0, + }, + { + name: "occuraccept", + bindKey: "enter", + exec: function (e) { + var t = e.session.$occur; + if (!t) return; + t.exit(e, { translatePosition: !0 }), + e.session.$occur || f.uninstallFrom(e); + }, + readOnly: !0, + }, + ], + u = e("../keyboard/hash_handler").HashHandler, + a = e("../lib/oop"); + a.inherits(f, u), + function () { + (this.isOccurHandler = !0), + (this.attach = function (e) { + u.call(this, o, e.commands.platform), (this.$editor = e); + }); + var e = this.handleKeyboard; + this.handleKeyboard = function (t, n, r, i) { + var s = e.call(this, t, n, r, i); + return s && s.command ? s : undefined; + }; + }.call(f.prototype), + (f.installIn = function (e) { + var t = new this(); + e.keyBinding.addKeyboardHandler(t), e.commands.addCommands(o); + }), + (f.uninstallFrom = function (e) { + e.commands.removeCommands(o); + var t = e.getKeyboardHandler(); + t.isOccurHandler && e.keyBinding.removeKeyboardHandler(t); + }), + (t.occurStartCommand = s); + }, + ), + define( + "ace/commands/incremental_search_commands", + [ + "require", + "exports", + "module", + "ace/config", + "ace/lib/oop", + "ace/keyboard/hash_handler", + "ace/commands/occur_commands", + ], + function (e, t, n) { + function u(e) { + this.$iSearch = e; + } + var r = e("../config"), + i = e("../lib/oop"), + s = e("../keyboard/hash_handler").HashHandler, + o = e("./occur_commands").occurStartCommand; + (t.iSearchStartCommands = [ + { + name: "iSearch", + bindKey: { win: "Ctrl-F", mac: "Command-F" }, + exec: function (e, t) { + r.loadModule(["core", "ace/incremental_search"], function (n) { + var r = (n.iSearch = n.iSearch || new n.IncrementalSearch()); + r.activate(e, t.backwards), t.jumpToFirstMatch && r.next(t); + }); + }, + readOnly: !0, + }, + { + name: "iSearchBackwards", + exec: function (e, t) { + e.execCommand("iSearch", { backwards: !0 }); + }, + readOnly: !0, + }, + { + name: "iSearchAndGo", + bindKey: { win: "Ctrl-K", mac: "Command-G" }, + exec: function (e, t) { + e.execCommand("iSearch", { + jumpToFirstMatch: !0, + useCurrentOrPrevSearch: !0, + }); + }, + readOnly: !0, + }, + { + name: "iSearchBackwardsAndGo", + bindKey: { win: "Ctrl-Shift-K", mac: "Command-Shift-G" }, + exec: function (e) { + e.execCommand("iSearch", { + jumpToFirstMatch: !0, + backwards: !0, + useCurrentOrPrevSearch: !0, + }); + }, + readOnly: !0, + }, + ]), + (t.iSearchCommands = [ + { + name: "restartSearch", + bindKey: { win: "Ctrl-F", mac: "Command-F" }, + exec: function (e) { + e.cancelSearch(!0); + }, + }, + { + name: "searchForward", + bindKey: { win: "Ctrl-S|Ctrl-K", mac: "Ctrl-S|Command-G" }, + exec: function (e, t) { + (t.useCurrentOrPrevSearch = !0), e.next(t); + }, + }, + { + name: "searchBackward", + bindKey: { win: "Ctrl-R|Ctrl-Shift-K", mac: "Ctrl-R|Command-Shift-G" }, + exec: function (e, t) { + (t.useCurrentOrPrevSearch = !0), (t.backwards = !0), e.next(t); + }, + }, + { + name: "extendSearchTerm", + exec: function (e, t) { + e.addString(t); + }, + }, + { + name: "extendSearchTermSpace", + bindKey: "space", + exec: function (e) { + e.addString(" "); + }, + }, + { + name: "shrinkSearchTerm", + bindKey: "backspace", + exec: function (e) { + e.removeChar(); + }, + }, + { + name: "confirmSearch", + bindKey: "return", + exec: function (e) { + e.deactivate(); + }, + }, + { + name: "cancelSearch", + bindKey: "esc|Ctrl-G", + exec: function (e) { + e.deactivate(!0); + }, + }, + { + name: "occurisearch", + bindKey: "Ctrl-O", + exec: function (e) { + var t = i.mixin({}, e.$options); + e.deactivate(), o.exec(e.$editor, t); + }, + }, + { + name: "yankNextWord", + bindKey: "Ctrl-w", + exec: function (e) { + var t = e.$editor, + n = t.selection.getRangeOfMovements(function (e) { + e.moveCursorWordRight(); + }), + r = t.session.getTextRange(n); + e.addString(r); + }, + }, + { + name: "yankNextChar", + bindKey: "Ctrl-Alt-y", + exec: function (e) { + var t = e.$editor, + n = t.selection.getRangeOfMovements(function (e) { + e.moveCursorRight(); + }), + r = t.session.getTextRange(n); + e.addString(r); + }, + }, + { + name: "recenterTopBottom", + bindKey: "Ctrl-l", + exec: function (e) { + e.$editor.execCommand("recenterTopBottom"); + }, + }, + { + name: "selectAllMatches", + bindKey: "Ctrl-space", + exec: function (e) { + var t = e.$editor, + n = t.session.$isearchHighlight, + r = + n && n.cache + ? n.cache.reduce(function (e, t) { + return e.concat(t ? t : []); + }, []) + : []; + e.deactivate(!1), r.forEach(t.selection.addRange.bind(t.selection)); + }, + }, + { + name: "searchAsRegExp", + bindKey: "Alt-r", + exec: function (e) { + e.convertNeedleToRegExp(); + }, + }, + ].map(function (e) { + return ( + (e.readOnly = !0), + (e.isIncrementalSearchCommand = !0), + (e.scrollIntoView = "animate-cursor"), + e + ); + })), + i.inherits(u, s), + function () { + (this.attach = function (e) { + var n = this.$iSearch; + s.call(this, t.iSearchCommands, e.commands.platform), + (this.$commandExecHandler = e.commands.addEventListener( + "exec", + function (t) { + if (!t.command.isIncrementalSearchCommand) + return n.deactivate(); + t.stopPropagation(), t.preventDefault(); + var r = e.session.getScrollTop(), + i = t.command.exec(n, t.args || {}); + return ( + e.renderer.scrollCursorIntoView(null, 0.5), + e.renderer.animateScrolling(r), + i + ); + }, + )); + }), + (this.detach = function (e) { + if (!this.$commandExecHandler) return; + e.commands.removeEventListener("exec", this.$commandExecHandler), + delete this.$commandExecHandler; + }); + var e = this.handleKeyboard; + this.handleKeyboard = function (t, n, r, i) { + if (((n === 1 || n === 8) && r === "v") || (n === 1 && r === "y")) + return null; + var s = e.call(this, t, n, r, i); + if (s.command) return s; + if (n == -1) { + var o = this.commands.extendSearchTerm; + if (o) return { command: o, args: r }; + } + return !1; + }; + }.call(u.prototype), + (t.IncrementalSearchKeyboardHandler = u); + }, + ), + define( + "ace/incremental_search", + [ + "require", + "exports", + "module", + "ace/lib/oop", + "ace/range", + "ace/search", + "ace/search_highlight", + "ace/commands/incremental_search_commands", + "ace/lib/dom", + "ace/commands/command_manager", + "ace/editor", + "ace/config", + ], + function (e, t, n) { + "use strict"; + function f() { + (this.$options = { wrap: !1, skipCurrent: !1 }), + (this.$keyboardHandler = new a(this)); + } + function l(e) { + return e instanceof RegExp; + } + function c(e) { + var t = String(e), + n = t.indexOf("/"), + r = t.lastIndexOf("/"); + return { expression: t.slice(n + 1, r), flags: t.slice(r + 1) }; + } + function h(e, t) { + try { + return new RegExp(e, t); + } catch (n) { + return e; + } + } + function p(e) { + return h(e.expression, e.flags); + } + var r = e("./lib/oop"), + i = e("./range").Range, + s = e("./search").Search, + o = e("./search_highlight").SearchHighlight, + u = e("./commands/incremental_search_commands"), + a = u.IncrementalSearchKeyboardHandler; + r.inherits(f, s), + function () { + (this.activate = function (e, t) { + (this.$editor = e), + (this.$startPos = this.$currentPos = e.getCursorPosition()), + (this.$options.needle = ""), + (this.$options.backwards = t), + e.keyBinding.addKeyboardHandler(this.$keyboardHandler), + (this.$originalEditorOnPaste = e.onPaste), + (e.onPaste = this.onPaste.bind(this)), + (this.$mousedownHandler = e.addEventListener( + "mousedown", + this.onMouseDown.bind(this), + )), + this.selectionFix(e), + this.statusMessage(!0); + }), + (this.deactivate = function (e) { + this.cancelSearch(e); + var t = this.$editor; + t.keyBinding.removeKeyboardHandler(this.$keyboardHandler), + this.$mousedownHandler && + (t.removeEventListener("mousedown", this.$mousedownHandler), + delete this.$mousedownHandler), + (t.onPaste = this.$originalEditorOnPaste), + this.message(""); + }), + (this.selectionFix = function (e) { + e.selection.isEmpty() && !e.session.$emacsMark && e.clearSelection(); + }), + (this.highlight = function (e) { + var t = this.$editor.session, + n = (t.$isearchHighlight = + t.$isearchHighlight || + t.addDynamicMarker(new o(null, "ace_isearch-result", "text"))); + n.setRegexp(e), t._emit("changeBackMarker"); + }), + (this.cancelSearch = function (e) { + var t = this.$editor; + return ( + (this.$prevNeedle = this.$options.needle), + (this.$options.needle = ""), + e + ? (t.moveCursorToPosition(this.$startPos), + (this.$currentPos = this.$startPos)) + : t.pushEmacsMark && t.pushEmacsMark(this.$startPos, !1), + this.highlight(null), + i.fromPoints(this.$currentPos, this.$currentPos) + ); + }), + (this.highlightAndFindWithNeedle = function (e, t) { + if (!this.$editor) return null; + var n = this.$options; + t && (n.needle = t.call(this, n.needle || "") || ""); + if (n.needle.length === 0) + return this.statusMessage(!0), this.cancelSearch(!0); + n.start = this.$currentPos; + var r = this.$editor.session, + s = this.find(r), + o = this.$editor.emacsMark + ? !!this.$editor.emacsMark() + : !this.$editor.selection.isEmpty(); + return ( + s && + (n.backwards && (s = i.fromPoints(s.end, s.start)), + this.$editor.selection.setRange( + i.fromPoints(o ? this.$startPos : s.end, s.end), + ), + e && (this.$currentPos = s.end), + this.highlight(n.re)), + this.statusMessage(s), + s + ); + }), + (this.addString = function (e) { + return this.highlightAndFindWithNeedle(!1, function (t) { + if (!l(t)) return t + e; + var n = c(t); + return (n.expression += e), p(n); + }); + }), + (this.removeChar = function (e) { + return this.highlightAndFindWithNeedle(!1, function (e) { + if (!l(e)) return e.substring(0, e.length - 1); + var t = c(e); + return ( + (t.expression = t.expression.substring( + 0, + t.expression.length - 1, + )), + p(t) + ); + }); + }), + (this.next = function (e) { + return ( + (e = e || {}), + (this.$options.backwards = !!e.backwards), + (this.$currentPos = this.$editor.getCursorPosition()), + this.highlightAndFindWithNeedle(!0, function (t) { + return e.useCurrentOrPrevSearch && t.length === 0 + ? this.$prevNeedle || "" + : t; + }) + ); + }), + (this.onMouseDown = function (e) { + return this.deactivate(), !0; + }), + (this.onPaste = function (e) { + this.addString(e); + }), + (this.convertNeedleToRegExp = function () { + return this.highlightAndFindWithNeedle(!1, function (e) { + return l(e) ? e : h(e, "ig"); + }); + }), + (this.convertNeedleToString = function () { + return this.highlightAndFindWithNeedle(!1, function (e) { + return l(e) ? c(e).expression : e; + }); + }), + (this.statusMessage = function (e) { + var t = this.$options, + n = ""; + (n += t.backwards ? "reverse-" : ""), + (n += "isearch: " + t.needle), + (n += e ? "" : " (not found)"), + this.message(n); + }), + (this.message = function (e) { + this.$editor.showCommandLine + ? (this.$editor.showCommandLine(e), this.$editor.focus()) + : console.log(e); + }); + }.call(f.prototype), + (t.IncrementalSearch = f); + var d = e("./lib/dom"); + d.importCssString && + d.importCssString( + ".ace_marker-layer .ace_isearch-result { position: absolute; z-index: 6; box-sizing: border-box;}div.ace_isearch-result { border-radius: 4px; background-color: rgba(255, 200, 0, 0.5); box-shadow: 0 0 4px rgb(255, 200, 0);}.ace_dark div.ace_isearch-result { background-color: rgb(100, 110, 160); box-shadow: 0 0 4px rgb(80, 90, 140);}", + "incremental-search-highlighting", + ); + var v = e("./commands/command_manager"); + (function () { + this.setupIncrementalSearch = function (e, t) { + if (this.usesIncrementalSearch == t) return; + this.usesIncrementalSearch = t; + var n = u.iSearchStartCommands, + r = t ? "addCommands" : "removeCommands"; + this[r](n); + }; + }).call(v.CommandManager.prototype); + var m = e("./editor").Editor; + e("./config").defineOptions(m.prototype, "editor", { + useIncrementalSearch: { + set: function (e) { + this.keyBinding.$handlers.forEach(function (t) { + t.setupIncrementalSearch && t.setupIncrementalSearch(this, e); + }), + this._emit("incrementalSearchSettingChanged", { isEnabled: e }); + }, + }, + }); + }, + ), + define( + "ace/keyboard/emacs", + [ + "require", + "exports", + "module", + "ace/lib/dom", + "ace/incremental_search", + "ace/commands/incremental_search_commands", + "ace/keyboard/hash_handler", + "ace/lib/keys", + ], + function (e, t, n) { + "use strict"; + var r = e("../lib/dom"); + e("../incremental_search"); + var i = e("../commands/incremental_search_commands"), + s = e("./hash_handler").HashHandler; + (t.handler = new s()), (t.handler.isEmacs = !0), (t.handler.$id = "ace/keyboard/emacs"); + var o = !1, + u, + a; + (t.handler.attach = function (e) { + o || + ((o = !0), + r.importCssString( + " .emacs-mode .ace_cursor{ border: 1px rgba(50,250,50,0.8) solid!important; box-sizing: border-box!important; background-color: rgba(0,250,0,0.9); opacity: 0.5; } .emacs-mode .ace_hidden-cursors .ace_cursor{ opacity: 1; background-color: transparent; } .emacs-mode .ace_overwrite-cursors .ace_cursor { opacity: 1; background-color: transparent; border-width: 0 0 2px 2px !important; } .emacs-mode .ace_text-layer { z-index: 4 } .emacs-mode .ace_cursor-layer { z-index: 2 }", + "emacsMode", + )), + (u = e.session.$selectLongWords), + (e.session.$selectLongWords = !0), + (a = e.session.$useEmacsStyleLineStart), + (e.session.$useEmacsStyleLineStart = !0), + (e.session.$emacsMark = null), + (e.session.$emacsMarkRing = e.session.$emacsMarkRing || []), + (e.emacsMark = function () { + return this.session.$emacsMark; + }), + (e.setEmacsMark = function (e) { + this.session.$emacsMark = e; + }), + (e.pushEmacsMark = function (e, t) { + var n = this.session.$emacsMark; + n && this.session.$emacsMarkRing.push(n), + !e || t ? this.setEmacsMark(e) : this.session.$emacsMarkRing.push(e); + }), + (e.popEmacsMark = function () { + var e = this.emacsMark(); + return e ? (this.setEmacsMark(null), e) : this.session.$emacsMarkRing.pop(); + }), + (e.getLastEmacsMark = function (e) { + return this.session.$emacsMark || this.session.$emacsMarkRing.slice(-1)[0]; + }), + (e.emacsMarkForSelection = function (e) { + var t = this.selection, + n = this.multiSelect ? this.multiSelect.getAllRanges().length : 1, + r = t.index || 0, + i = this.session.$emacsMarkRing, + s = i.length - (n - r), + o = i[s] || t.anchor; + return e && i.splice(s, 1, "row" in e && "column" in e ? e : undefined), o; + }), + e.on("click", l), + e.on("changeSession", f), + (e.renderer.$blockCursor = !0), + e.setStyle("emacs-mode"), + e.commands.addCommands(d), + (t.handler.platform = e.commands.platform), + (e.$emacsModeHandler = this), + e.addEventListener("copy", this.onCopy), + e.addEventListener("paste", this.onPaste); + }), + (t.handler.detach = function (e) { + (e.renderer.$blockCursor = !1), + (e.session.$selectLongWords = u), + (e.session.$useEmacsStyleLineStart = a), + e.removeEventListener("click", l), + e.removeEventListener("changeSession", f), + e.unsetStyle("emacs-mode"), + e.commands.removeCommands(d), + e.removeEventListener("copy", this.onCopy), + e.removeEventListener("paste", this.onPaste), + (e.$emacsModeHandler = null); + }); + var f = function (e) { + e.oldSession && + ((e.oldSession.$selectLongWords = u), + (e.oldSession.$useEmacsStyleLineStart = a)), + (u = e.session.$selectLongWords), + (e.session.$selectLongWords = !0), + (a = e.session.$useEmacsStyleLineStart), + (e.session.$useEmacsStyleLineStart = !0), + e.session.hasOwnProperty("$emacsMark") || (e.session.$emacsMark = null), + e.session.hasOwnProperty("$emacsMarkRing") || + (e.session.$emacsMarkRing = []); + }, + l = function (e) { + e.editor.session.$emacsMark = null; + }, + c = e("../lib/keys").KEY_MODS, + h = { C: "ctrl", S: "shift", M: "alt", CMD: "command" }, + p = [ + "C-S-M-CMD", + "S-M-CMD", + "C-M-CMD", + "C-S-CMD", + "C-S-M", + "M-CMD", + "S-CMD", + "S-M", + "C-CMD", + "C-M", + "C-S", + "CMD", + "M", + "S", + "C", + ]; + p.forEach(function (e) { + var t = 0; + e.split("-").forEach(function (e) { + t |= c[h[e]]; + }), + (h[t] = e.toLowerCase() + "-"); + }), + (t.handler.onCopy = function (e, n) { + if (n.$handlesEmacsOnCopy) return; + (n.$handlesEmacsOnCopy = !0), + t.handler.commands.killRingSave.exec(n), + (n.$handlesEmacsOnCopy = !1); + }), + (t.handler.onPaste = function (e, t) { + t.pushEmacsMark(t.getCursorPosition()); + }), + (t.handler.bindKey = function (e, t) { + typeof e == "object" && (e = e[this.platform]); + if (!e) return; + var n = this.commandKeyBinding; + e.split("|").forEach(function (e) { + (e = e.toLowerCase()), (n[e] = t); + var r = e.split(" ").slice(0, -1); + r.reduce(function (e, t, n) { + var r = e[n - 1] ? e[n - 1] + " " : ""; + return e.concat([r + t]); + }, []).forEach(function (e) { + n[e] || (n[e] = "null"); + }); + }, this); + }), + (t.handler.getStatusText = function (e, t) { + var n = ""; + return t.count && (n += t.count), t.keyChain && (n += " " + t.keyChain), n; + }), + (t.handler.handleKeyboard = function (e, t, n, r) { + if (r === -1) return undefined; + var i = e.editor; + i._signal("changeStatus"); + if (t == -1) { + i.pushEmacsMark(); + if (e.count) { + var s = new Array(e.count + 1).join(n); + return (e.count = null), { command: "insertstring", args: s }; + } + } + var o = h[t]; + if (o == "c-" || e.count) { + var u = parseInt(n[n.length - 1]); + if (typeof u == "number" && !isNaN(u)) + return ( + (e.count = Math.max(e.count, 0) || 0), + (e.count = 10 * e.count + u), + { command: "null" } + ); + } + o && (n = o + n), e.keyChain && (n = e.keyChain += " " + n); + var a = this.commandKeyBinding[n]; + e.keyChain = a == "null" ? n : ""; + if (!a) return undefined; + if (a === "null") return { command: "null" }; + if (a === "universalArgument") return (e.count = -4), { command: "null" }; + var f; + typeof a != "string" && + ((f = a.args), + a.command && (a = a.command), + a === "goorselect" && ((a = i.emacsMark() ? f[1] : f[0]), (f = null))); + if (typeof a == "string") { + (a === "insertstring" || a === "splitline" || a === "togglecomment") && + i.pushEmacsMark(), + (a = this.commands[a] || i.commands.commands[a]); + if (!a) return undefined; + } + !a.readOnly && !a.isYank && (e.lastCommand = null), + !a.readOnly && i.emacsMark() && i.setEmacsMark(null); + if (e.count) { + var u = e.count; + e.count = 0; + if (!a || !a.handlesCount) + return { + args: f, + command: { + exec: function (e, t) { + for (var n = 0; n < u; n++) a.exec(e, t); + }, + multiSelectAction: a.multiSelectAction, + }, + }; + f || (f = {}), typeof f == "object" && (f.count = u); + } + return { command: a, args: f }; + }), + (t.emacsKeys = { + "Up|C-p": { command: "goorselect", args: ["golineup", "selectup"] }, + "Down|C-n": { command: "goorselect", args: ["golinedown", "selectdown"] }, + "Left|C-b": { command: "goorselect", args: ["gotoleft", "selectleft"] }, + "Right|C-f": { command: "goorselect", args: ["gotoright", "selectright"] }, + "C-Left|M-b": { + command: "goorselect", + args: ["gotowordleft", "selectwordleft"], + }, + "C-Right|M-f": { + command: "goorselect", + args: ["gotowordright", "selectwordright"], + }, + "Home|C-a": { + command: "goorselect", + args: ["gotolinestart", "selecttolinestart"], + }, + "End|C-e": { command: "goorselect", args: ["gotolineend", "selecttolineend"] }, + "C-Home|S-M-,": { command: "goorselect", args: ["gotostart", "selecttostart"] }, + "C-End|S-M-.": { command: "goorselect", args: ["gotoend", "selecttoend"] }, + "S-Up|S-C-p": "selectup", + "S-Down|S-C-n": "selectdown", + "S-Left|S-C-b": "selectleft", + "S-Right|S-C-f": "selectright", + "S-C-Left|S-M-b": "selectwordleft", + "S-C-Right|S-M-f": "selectwordright", + "S-Home|S-C-a": "selecttolinestart", + "S-End|S-C-e": "selecttolineend", + "S-C-Home": "selecttostart", + "S-C-End": "selecttoend", + "C-l": "recenterTopBottom", + "M-s": "centerselection", + "M-g": "gotoline", + "C-x C-p": "selectall", + "C-Down": { command: "goorselect", args: ["gotopagedown", "selectpagedown"] }, + "C-Up": { command: "goorselect", args: ["gotopageup", "selectpageup"] }, + "PageDown|C-v": { + command: "goorselect", + args: ["gotopagedown", "selectpagedown"], + }, + "PageUp|M-v": { command: "goorselect", args: ["gotopageup", "selectpageup"] }, + "S-C-Down": "selectpagedown", + "S-C-Up": "selectpageup", + "C-s": "iSearch", + "C-r": "iSearchBackwards", + "M-C-s": "findnext", + "M-C-r": "findprevious", + "S-M-5": "replace", + Backspace: "backspace", + "Delete|C-d": "del", + "Return|C-m": { command: "insertstring", args: "\n" }, + "C-o": "splitline", + "M-d|C-Delete": { command: "killWord", args: "right" }, + "C-Backspace|M-Backspace|M-Delete": { command: "killWord", args: "left" }, + "C-k": "killLine", + "C-y|S-Delete": "yank", + "M-y": "yankRotate", + "C-g": "keyboardQuit", + "C-w|C-S-W": "killRegion", + "M-w": "killRingSave", + "C-Space": "setMark", + "C-x C-x": "exchangePointAndMark", + "C-t": "transposeletters", + "M-u": "touppercase", + "M-l": "tolowercase", + "M-/": "autocomplete", + "C-u": "universalArgument", + "M-;": "togglecomment", + "C-/|C-x u|S-C--|C-z": "undo", + "S-C-/|S-C-x u|C--|S-C-z": "redo", + "C-x r": "selectRectangularRegion", + "M-x": { command: "focusCommandLine", args: "M-x " }, + }), + t.handler.bindKeys(t.emacsKeys), + t.handler.addCommands({ + recenterTopBottom: function (e) { + var t = e.renderer, + n = t.$cursorLayer.getPixelPosition(), + r = t.$size.scrollerHeight - t.lineHeight, + i = t.scrollTop; + Math.abs(n.top - i) < 2 + ? (i = n.top - r) + : Math.abs(n.top - i - r * 0.5) < 2 + ? (i = n.top) + : (i = n.top - r * 0.5), + e.session.setScrollTop(i); + }, + selectRectangularRegion: function (e) { + e.multiSelect.toggleBlockSelection(); + }, + setMark: { + exec: function (e, t) { + function u() { + var t = e.popEmacsMark(); + t && e.moveCursorToPosition(t); + } + if (t && t.count) { + e.inMultiSelectMode ? e.forEachSelection(u) : u(), u(); + return; + } + var n = e.emacsMark(), + r = e.selection.getAllRanges(), + i = r.map(function (e) { + return { row: e.start.row, column: e.start.column }; + }), + s = !0, + o = r.every(function (e) { + return e.isEmpty(); + }); + if (s && (n || !o)) { + e.inMultiSelectMode + ? e.forEachSelection({ exec: e.clearSelection.bind(e) }) + : e.clearSelection(), + n && e.pushEmacsMark(null); + return; + } + if (!n) { + i.forEach(function (t) { + e.pushEmacsMark(t); + }), + e.setEmacsMark(i[i.length - 1]); + return; + } + }, + readOnly: !0, + handlesCount: !0, + }, + exchangePointAndMark: { + exec: function (t, n) { + var r = t.selection; + if (!n.count && !r.isEmpty()) { + r.setSelectionRange(r.getRange(), !r.isBackwards()); + return; + } + if (n.count) { + var i = { row: r.lead.row, column: r.lead.column }; + r.clearSelection(), + r.moveCursorToPosition(t.emacsMarkForSelection(i)); + } else r.selectToPosition(t.emacsMarkForSelection()); + }, + readOnly: !0, + handlesCount: !0, + multiSelectAction: "forEach", + }, + killWord: { + exec: function (e, n) { + e.clearSelection(), + n == "left" + ? e.selection.selectWordLeft() + : e.selection.selectWordRight(); + var r = e.getSelectionRange(), + i = e.session.getTextRange(r); + t.killRing.add(i), e.session.remove(r), e.clearSelection(); + }, + multiSelectAction: "forEach", + }, + killLine: function (e) { + e.pushEmacsMark(null), e.clearSelection(); + var n = e.getSelectionRange(), + r = e.session.getLine(n.start.row); + (n.end.column = r.length), (r = r.substr(n.start.column)); + var i = e.session.getFoldLine(n.start.row); + i && n.end.row != i.end.row && ((n.end.row = i.end.row), (r = "x")), + /^\s*$/.test(r) && + (n.end.row++, + (r = e.session.getLine(n.end.row)), + (n.end.column = /^\s*$/.test(r) ? r.length : 0)); + var s = e.session.getTextRange(n); + e.prevOp.command == this ? t.killRing.append(s) : t.killRing.add(s), + e.session.remove(n), + e.clearSelection(); + }, + yank: function (e) { + e.onPaste(t.killRing.get() || ""), + (e.keyBinding.$data.lastCommand = "yank"); + }, + yankRotate: function (e) { + if (e.keyBinding.$data.lastCommand != "yank") return; + e.undo(), + e.session.$emacsMarkRing.pop(), + e.onPaste(t.killRing.rotate()), + (e.keyBinding.$data.lastCommand = "yank"); + }, + killRegion: { + exec: function (e) { + t.killRing.add(e.getCopyText()), + e.commands.byName.cut.exec(e), + e.setEmacsMark(null); + }, + readOnly: !0, + multiSelectAction: "forEach", + }, + killRingSave: { + exec: function (e) { + e.$handlesEmacsOnCopy = !0; + var n = e.session.$emacsMarkRing.slice(), + r = []; + t.killRing.add(e.getCopyText()), + setTimeout(function () { + function t() { + var t = e.selection, + n = t.getRange(), + i = t.isBackwards() ? n.end : n.start; + r.push({ row: i.row, column: i.column }), + t.clearSelection(); + } + (e.$handlesEmacsOnCopy = !1), + e.inMultiSelectMode ? e.forEachSelection({ exec: t }) : t(), + (e.session.$emacsMarkRing = n.concat(r.reverse())); + }, 0); + }, + readOnly: !0, + }, + keyboardQuit: function (e) { + e.selection.clearSelection(), + e.setEmacsMark(null), + (e.keyBinding.$data.count = null); + }, + focusCommandLine: function (e, t) { + e.showCommandLine && e.showCommandLine(t); + }, + }), + t.handler.addCommands(i.iSearchStartCommands); + var d = t.handler.commands; + (d.yank.isYank = !0), + (d.yankRotate.isYank = !0), + (t.killRing = { + $data: [], + add: function (e) { + e && this.$data.push(e), this.$data.length > 30 && this.$data.shift(); + }, + append: function (e) { + var t = this.$data.length - 1, + n = this.$data[t] || ""; + e && (n += e), n && (this.$data[t] = n); + }, + get: function (e) { + return ( + (e = e || 1), + this.$data + .slice(this.$data.length - e, this.$data.length) + .reverse() + .join("\n") + ); + }, + pop: function () { + return this.$data.length > 1 && this.$data.pop(), this.get(); + }, + rotate: function () { + return this.$data.unshift(this.$data.pop()), this.get(); + }, + }); + }, + ); +(function () { + window.require(["ace/keyboard/emacs"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/keybinding-vim.js b/web/static/ace/keybinding-vim.js index 3dc7bb320..71dc000c7 100644 --- a/web/static/ace/keybinding-vim.js +++ b/web/static/ace/keybinding-vim.js @@ -1,9 +1,5052 @@ -define("ace/keyboard/vim",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/dom","ace/lib/oop","ace/lib/keys","ace/lib/event","ace/search","ace/lib/useragent","ace/search_highlight","ace/commands/multi_select_commands","ace/mode/text","ace/multi_select"],function(e,t,n){"use strict";function r(){function t(e){return typeof e!="object"?e+"":"line"in e?e.line+":"+e.ch:"anchor"in e?t(e.anchor)+"->"+t(e.head):Array.isArray(e)?"["+e.map(function(e){return t(e)})+"]":JSON.stringify(e)}var e="";for(var n=0;n"):!1}function M(e){var t=e.state.vim;return t.onPasteFn||(t.onPasteFn=function(){t.insertMode||(e.setCursor(St(e.getCursor(),0,1)),yt.enterInsertMode(e,{},t))}),t.onPasteFn}function H(e,t){var n=[];for(var r=e;r=e.firstLine()&&t<=e.lastLine()}function U(e){return/^[a-z]$/.test(e)}function z(e){return"()[]{}".indexOf(e)!=-1}function W(e){return _.test(e)}function X(e){return/^[A-Z]$/.test(e)}function V(e){return/^\s*$/.test(e)}function $(e,t){for(var n=0;n"){var n=t.length-11,r=e.slice(0,n),i=t.slice(0,n);return r==i&&e.length>n?"full":i.indexOf(r)==0?"partial":!1}return e==t?"full":t.indexOf(e)==0?"partial":!1}function Ct(e){var t=/^.*(<[^>]+>)$/.exec(e),n=t?t[1]:e.slice(-1);if(n.length>1)switch(n){case"":n="\n";break;case"":n=" ";break;default:n=""}return n}function kt(e,t,n){return function(){for(var r=0;r2&&(t=Mt.apply(undefined,Array.prototype.slice.call(arguments,1))),Ot(e,t)?e:t}function _t(e,t){return arguments.length>2&&(t=_t.apply(undefined,Array.prototype.slice.call(arguments,1))),Ot(e,t)?t:e}function Dt(e,t,n){var r=Ot(e,t),i=Ot(t,n);return r&&i}function Pt(e,t){return e.getLine(t).length}function Ht(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}function Bt(e){return e.replace(/([.?*+$\[\]\/\\(){}|\-])/g,"\\$1")}function jt(e,t,n){var r=Pt(e,t),i=(new Array(n-r+1)).join(" ");e.setCursor(E(t,r)),e.replaceRange(i,e.getCursor())}function Ft(e,t){var n=[],r=e.listSelections(),i=Lt(e.clipPos(t)),s=!At(t,i),o=e.getCursor("head"),u=qt(r,o),a=At(r[u].head,r[u].anchor),f=r.length-1,l=f-u>u?f:0,c=r[l].anchor,h=Math.min(c.line,i.line),p=Math.max(c.line,i.line),d=c.ch,v=i.ch,m=r[l].head.ch-d,g=v-d;m>0&&g<=0?(d++,s||v--):m<0&&g>=0?(d--,a||v++):m<0&&g==-1&&(d--,v++);for(var y=h;y<=p;y++){var b={anchor:new E(y,d),head:new E(y,v)};n.push(b)}return e.setSelections(n),t.ch=v,c.ch=d,c}function It(e,t,n){var r=[];for(var i=0;ia&&(i.line=a),i.ch=Pt(e,i.line)}else i.ch=0,s.ch=Pt(e,s.line);return{ranges:[{anchor:s,head:i}],primary:0}}if(n=="block"){var f=Math.min(s.line,i.line),l=Math.min(s.ch,i.ch),c=Math.max(s.line,i.line),h=Math.max(s.ch,i.ch)+1,p=c-f+1,d=i.line==f?0:p-1,v=[];for(var m=0;m0&&s&&V(s);s=i.pop())n.line--,n.ch=0;s?(n.line--,n.ch=Pt(e,n.line)):n.ch=0}}function Kt(e,t,n){t.ch=0,n.ch=0,n.line++}function Qt(e){if(!e)return 0;var t=e.search(/\S/);return t==-1?e.length:t}function Gt(e,t,n,r,i){var s=Vt(e),o=e.getLine(s.line),u=s.ch,a=i?D[0]:P[0];while(!a(o.charAt(u))){u++;if(u>=o.length)return null}r?a=P[0]:(a=D[0],a(o.charAt(u))||(a=D[1]));var f=u,l=u;while(a(o.charAt(f))&&f=0)l--;l++;if(t){var c=f;while(/\s/.test(o.charAt(f))&&f0)l--;l||(l=h)}}return{start:E(s.line,l),end:E(s.line,f)}}function Yt(e,t,n){At(t,n)||nt.jumpList.add(e,t,n)}function Zt(e,t){nt.lastCharacterSearch.increment=e,nt.lastCharacterSearch.forward=t.forward,nt.lastCharacterSearch.selectedCharacter=t.selectedCharacter}function nn(e,t,n,r){var i=Lt(e.getCursor()),s=n?1:-1,o=n?e.lineCount():-1,u=i.ch,a=i.line,f=e.getLine(a),l={lineText:f,nextCh:f.charAt(u),lastCh:null,index:u,symb:r,reverseSymb:(n?{")":"(","}":"{"}:{"(":")","{":"}"})[r],forward:n,depth:0,curMoveThrough:!1},c=en[r];if(!c)return i;var h=tn[c].init,p=tn[c].isComplete;h&&h(l);while(a!==o&&t){l.index+=s,l.nextCh=l.lineText.charAt(l.index);if(!l.nextCh){a+=s,l.lineText=e.getLine(a)||"";if(s>0)l.index=0;else{var d=l.lineText.length;l.index=d>0?d-1:0}l.nextCh=l.lineText.charAt(l.index)}p(l)&&(i.line=a,i.ch=l.index,t--)}return l.nextCh||l.curMoveThrough?E(a,l.index):i}function rn(e,t,n,r,i){var s=t.line,o=t.ch,u=e.getLine(s),a=n?1:-1,f=r?P:D;if(i&&u==""){s+=a,u=e.getLine(s);if(!R(e,s))return null;o=n?0:u.length}for(;;){if(i&&u=="")return{from:0,to:0,line:s};var l=a>0?u.length:-1,c=l,h=l;while(o!=l){var p=!1;for(var d=0;d0?0:u.length}}function sn(e,t,n,r,i,s){var o=Lt(t),u=[];(r&&!i||!r&&i)&&n++;var a=!r||!i;for(var f=0;f0?1:-1;var n=e.ace.session.getFoldLine(t);n&&t+r>n.start.row&&t+r0?n.end.row:n.start.row)-t)}var s=t.line,o=e.firstLine(),u=e.lastLine(),a,f,l=s;if(r){while(o<=l&&l<=u&&n>0)p(l),h(l,r)&&n--,l+=r;return new E(l,0)}var d=e.state.vim;if(d.visualLine&&h(s,1,!0)){var v=d.sel.anchor;h(v.line,-1,!0)&&(!i||v.line!=s)&&(s+=1)}var m=c(s);for(l=s;l<=u&&n;l++)h(l,1,!0)&&(!i||c(l)!=m)&&n--;f=new E(l,0),l>u&&!m?m=!0:i=!1;for(l=s;l>o;l--)if(!i||c(l)==m||l==s)if(h(l,-1,!0))break;return a=new E(l,0),{start:a,end:f}}function cn(e,t,n,r){var i=t,s,o,u={"(":/[()]/,")":/[()]/,"[":/[[\]]/,"]":/[[\]]/,"{":/[{}]/,"}":/[{}]/}[n],a={"(":"(",")":"(","[":"[","]":"[","{":"{","}":"{"}[n],f=e.getLine(i.line).charAt(i.ch),l=f===a?1:0;s=e.scanForBracket(E(i.line,i.ch+l),-1,null,{bracketRegex:u}),o=e.scanForBracket(E(i.line,i.ch+l),1,null,{bracketRegex:u});if(!s||!o)return{start:i,end:i};s=s.pos,o=o.pos;if(s.line==o.line&&s.ch>o.ch||s.line>o.line){var c=s;s=o,o=c}return r?o.ch+=1:s.ch+=1,{start:s,end:o}}function hn(e,t,n,r){var i=Lt(t),s=e.getLine(i.line),o=s.split(""),u,a,f,l,c=o.indexOf(n);i.ch-1&&!u;f--)o[f]==n&&(u=f+1);if(u&&!a)for(f=u,l=o.length;f'+t+"",{bottom:!0,duration:5e3}):alert(t)}function kn(e,t){var n=''+(e||"")+'';return t&&(n+=' '+t+""),n}function An(e,t){var n=(t.prefix||"")+" "+(t.desc||""),r=kn(t.prefix,t.desc);vn(e,r,n,t.onClose,t)}function On(e,t){if(e instanceof RegExp&&t instanceof RegExp){var n=["global","multiline","ignoreCase","source"];for(var r=0;r=t&&e<=n:e==t}function jn(e){var t=e.ace.renderer;return{top:t.getFirstFullyVisibleRow(),bottom:t.getLastFullyVisibleRow()}}function Fn(e,t,n){var r=t.marks[n];return r&&r.find()}function Un(e,t,n,r,i,s,o,u,a){function c(){e.operation(function(){while(!f)h(),p();d()})}function h(){var t=e.getRange(s.from(),s.to()),n=t.replace(o,u);s.replace(n)}function p(){while(s.findNext()&&Bn(s.from(),r,i)){if(!n&&l&&s.from().line==l.line)continue;e.scrollIntoView(s.from(),30),e.setSelection(s.from(),s.to()),l=s.from(),f=!1;return}f=!0}function d(t){t&&t(),e.focus();if(l){e.setCursor(l);var n=e.state.vim;n.exMode=!1,n.lastHPos=n.lastHSPos=l.ch}a&&a()}function m(t,n,r){v.e_stop(t);var i=v.keyName(t);switch(i){case"Y":h(),p();break;case"N":p();break;case"A":var s=a;a=undefined,e.operation(c),a=s;break;case"L":h();case"Q":case"Esc":case"Ctrl-C":case"Ctrl-[":d(r)}return f&&d(r),!0}e.state.vim.exMode=!0;var f=!1,l=s.from();p();if(f){Cn(e,"No matches for "+o.source);return}if(!t){c(),a&&a();return}An(e,{prefix:"replace with "+u+" (y/n/a/q/l)",onKeyDown:m})}function zn(e){var t=e.state.vim,n=nt.macroModeState,r=nt.registerController.getRegister("."),i=n.isPlaying,s=n.lastInsertModeChanges,o=[];if(!i){var u=s.inVisualBlock&&t.lastSelection?t.lastSelection.visualBlock.height:1,a=s.changes,o=[],f=0;while(f1&&(nr(e,t,t.insertModeRepeat-1,!0),t.lastEditInputState.repeatOverride=t.insertModeRepeat),delete t.insertModeRepeat,t.insertMode=!1,e.setCursor(e.getCursor().line,e.getCursor().ch-1),e.setOption("keyMap","vim"),e.setOption("disableInput",!0),e.toggleOverwrite(!1),r.setText(s.changes.join("")),v.signal(e,"vim-mode-change",{mode:"normal"}),n.isRecording&&Jn(n)}function Wn(e){b.unshift(e)}function Xn(e,t,n,r,i){var s={keys:e,type:t};s[t]=n,s[t+"Args"]=r;for(var o in i)s[o]=i[o];Wn(s)}function Vn(e,t,n,r){var i=nt.registerController.getRegister(r);if(r==":"){i.keyBuffer[0]&&Rn.processCommand(e,i.keyBuffer[0]),n.isPlaying=!1;return}var s=i.keyBuffer,o=0;n.isPlaying=!0,n.replaySearchQueries=i.searchQueries.slice(0);for(var u=0;u|<\w+>|./.exec(a),l=f[0],a=a.substring(f.index+l.length),v.Vim.handleKey(e,l,"macro");if(t.insertMode){var c=i.insertModeChanges[o++].changes;nt.macroModeState.lastInsertModeChanges.changes=c,rr(e,c,1),zn(e)}}}n.isPlaying=!1}function $n(e,t){if(e.isPlaying)return;var n=e.latestRegister,r=nt.registerController.getRegister(n);r&&r.pushText(t)}function Jn(e){if(e.isPlaying)return;var t=e.latestRegister,n=nt.registerController.getRegister(t);n&&n.pushInsertModeChanges&&n.pushInsertModeChanges(e.lastInsertModeChanges)}function Kn(e,t){if(e.isPlaying)return;var n=e.latestRegister,r=nt.registerController.getRegister(n);r&&r.pushSearchQuery&&r.pushSearchQuery(t)}function Qn(e,t){var n=nt.macroModeState,r=n.lastInsertModeChanges;if(!n.isPlaying)while(t){r.expectCursorActivityForChange=!0;if(t.origin=="+input"||t.origin=="paste"||t.origin===undefined){var i=t.text.join("\n");r.maybeReset&&(r.changes=[],r.maybeReset=!1),e.state.overwrite&&!/\n/.test(i)?r.changes.push([i]):r.changes.push(i)}t=t.next}}function Gn(e){var t=e.state.vim;if(t.insertMode){var n=nt.macroModeState;if(n.isPlaying)return;var r=n.lastInsertModeChanges;r.expectCursorActivityForChange?r.expectCursorActivityForChange=!1:r.maybeReset=!0}else e.curOp.isVimOp||Zn(e,t);t.visualMode&&Yn(e)}function Yn(e){var t=e.state.vim,n=wt(e,Lt(t.sel.head)),r=St(n,0,1);t.fakeCursor&&t.fakeCursor.clear(),t.fakeCursor=e.markText(n,r,{className:"cm-animate-fat-cursor"})}function Zn(e,t){var n=e.getCursor("anchor"),r=e.getCursor("head");t.visualMode&&!e.somethingSelected()?$t(e,!1):!t.visualMode&&!t.insertMode&&e.somethingSelected()&&(t.visualMode=!0,t.visualLine=!1,v.signal(e,"vim-mode-change",{mode:"visual"}));if(t.visualMode){var i=Ot(r,n)?0:-1,s=Ot(r,n)?-1:0;r=St(r,0,i),n=St(n,0,s),t.sel={anchor:n,head:r},an(e,t,"<",Mt(r,n)),an(e,t,">",_t(r,n))}else t.insertMode||(t.lastHPos=e.getCursor().ch)}function er(e){this.keyName=e}function tr(e){function i(){return n.maybeReset&&(n.changes=[],n.maybeReset=!1),n.changes.push(new er(r)),!0}var t=nt.macroModeState,n=t.lastInsertModeChanges,r=v.keyName(e);if(!r)return;(r.indexOf("Delete")!=-1||r.indexOf("Backspace")!=-1)&&v.lookupKey(r,"vim-insert",i)}function nr(e,t,n,r){function u(){s?ht.processAction(e,t,t.lastEditActionCommand):ht.evalInput(e,t)}function a(n){if(i.lastInsertModeChanges.changes.length>0){n=t.lastEditActionCommand?n:1;var r=i.lastInsertModeChanges;rr(e,r.changes,n)}}var i=nt.macroModeState;i.isPlaying=!0;var s=!!t.lastEditActionCommand,o=t.inputState;t.inputState=t.lastEditInputState;if(s&&t.lastEditActionCommand.interlaceInsertRepeat)for(var f=0;f1&&t[0]=="n"&&(t=t.replace("numpad","")),t=ir[t]||t;var r="";return n.ctrlKey&&(r+="C-"),n.altKey&&(r+="A-"),(r||t.length>1)&&n.shiftKey&&(r+="S-"),r+=t,r.length>1&&(r="<"+r+">"),r}function ur(e){var t=new e.constructor;return Object.keys(e).forEach(function(n){var r=e[n];Array.isArray(r)?r=r.slice():r&&typeof r=="object"&&r.constructor!=Object&&(r=ur(r)),t[n]=r}),e.sel&&(t.sel={head:e.sel.head&&Lt(e.sel.head),anchor:e.sel.anchor&&Lt(e.sel.anchor)}),t}function ar(e,t,n){var r=!1,i=S.maybeInitVimState_(e),s=i.visualBlock||i.wasInVisualBlock;i.wasInVisualBlock&&!e.ace.inMultiSelectMode?i.wasInVisualBlock=!1:e.ace.inMultiSelectMode&&i.visualBlock&&(i.wasInVisualBlock=!0);if(t==""&&!i.insertMode&&!i.visualMode&&e.ace.inMultiSelectMode)e.ace.exitMultiSelectMode();else if(s||!e.ace.inMultiSelectMode||e.ace.inVirtualSelectionMode)r=S.handleKey(e,t,n);else{var o=ur(i);e.operation(function(){e.ace.forEachSelection(function(){var i=e.ace.selection;e.state.vim.lastHPos=i.$desiredColumn==null?i.lead.column:i.$desiredColumn;var s=e.getCursor("head"),u=e.getCursor("anchor"),a=Ot(s,u)?0:-1,f=Ot(s,u)?-1:0;s=St(s,0,a),u=St(u,0,f),e.state.vim.sel.head=s,e.state.vim.sel.anchor=u,r=or(e,t,n),i.$desiredColumn=e.state.vim.lastHPos==-1?null:e.state.vim.lastHPos,e.virtualSelectionMode()&&(e.state.vim=ur(o))}),e.curOp.cursorActivity&&!r&&(e.curOp.cursorActivity=!1)},!0)}return r&&Zn(e,i),r}function lr(e,t){t.off("beforeEndOperation",lr);var n=t.state.cm.vimCmd;n&&t.execCommand(n.exec?n:n.name,n.args),t.curOp=t.prevOp}var i=e("../range").Range,s=e("../lib/event_emitter").EventEmitter,o=e("../lib/dom"),u=e("../lib/oop"),a=e("../lib/keys"),f=e("../lib/event"),l=e("../search").Search,c=e("../lib/useragent"),h=e("../search_highlight").SearchHighlight,p=e("../commands/multi_select_commands"),d=e("../mode/text").Mode.prototype.tokenRe;e("../multi_select");var v=function(e){this.ace=e,this.state={},this.marks={},this.$uid=0,this.onChange=this.onChange.bind(this),this.onSelectionChange=this.onSelectionChange.bind(this),this.onBeforeEndOperation=this.onBeforeEndOperation.bind(this),this.ace.on("change",this.onChange),this.ace.on("changeSelection",this.onSelectionChange),this.ace.on("beforeEndOperation",this.onBeforeEndOperation)};v.Pos=function(e,t){if(!(this instanceof E))return new E(e,t);this.line=e,this.ch=t},v.defineOption=function(e,t,n){},v.commands={redo:function(e){e.ace.redo()},undo:function(e){e.ace.undo()},newlineAndIndent:function(e){e.ace.insert("\n")}},v.keyMap={},v.addClass=v.rmClass=function(){},v.e_stop=v.e_preventDefault=f.stopEvent,v.keyName=function(e){var t=a[e.keyCode]||e.key||"";return t.length==1&&(t=t.toUpperCase()),t=f.getModifierString(e).replace(/(^|-)\w/g,function(e){return e.toUpperCase()})+t,t},v.keyMap["default"]=function(e){return function(t){var n=t.ace.commands.commandKeyBinding[e.toLowerCase()];return n&&t.ace.execCommand(n)!==!1}},v.lookupKey=function cr(e,t,n){typeof t=="string"&&(t=v.keyMap[t]);var r=typeof t=="function"?t(e):t[e];if(r===!1)return"nothing";if(r==="...")return"multi";if(r!=null&&n(r))return"handled";if(t.fallthrough){if(!Array.isArray(t.fallthrough))return cr(e,t.fallthrough,n);for(var i=0;i0){a.row+=s,a.column+=a.row==r.row?o:0;continue}!t&&l<=0&&(a.row=n.row,a.column=n.column,l===0&&(a.bias=1))}};var e=function(e,t,n,r){this.cm=e,this.id=t,this.row=n,this.column=r,e.marks[this.id]=this};e.prototype.clear=function(){delete this.cm.marks[this.id]},e.prototype.find=function(){return g(this)},this.setBookmark=function(t,n){var r=new e(this,this.$uid++,t.line,t.ch);if(!n||!n.insertLeft)r.$insertRight=!0;return this.marks[r.id]=r,r},this.moveH=function(e,t){if(t=="char"){var n=this.ace.selection;n.clearSelection(),n.moveCursorBy(0,e)}},this.findPosV=function(e,t,n,r){if(n=="page"){var i=this.ace.renderer,s=i.layerConfig;t*=Math.floor(s.height/s.lineHeight),n="line"}if(n=="line"){var o=this.ace.session.documentToScreenPosition(e.line,e.ch);r!=null&&(o.column=r),o.row+=t,o.row=Math.min(Math.max(0,o.row),this.ace.session.getScreenLength()-1);var u=this.ace.session.screenToDocumentPosition(o.row,o.column);return g(u)}debugger},this.charCoords=function(e,t){if(t=="div"||!t){var n=this.ace.session.documentToScreenPosition(e.line,e.ch);return{left:n.column,top:n.row}}if(t=="local"){var r=this.ace.renderer,n=this.ace.session.documentToScreenPosition(e.line,e.ch),i=r.layerConfig.lineHeight,s=r.layerConfig.characterWidth,o=i*n.row;return{left:n.column*s,top:o,bottom:o+i}}},this.coordsChar=function(e,t){var n=this.ace.renderer;if(t=="local"){var r=Math.max(0,Math.floor(e.top/n.lineHeight)),i=Math.max(0,Math.floor(e.left/n.characterWidth)),s=n.session.screenToDocumentPosition(r,i);return g(s)}if(t=="div")throw"not implemented"},this.getSearchCursor=function(e,t,n){var r=!1,i=!1;e instanceof RegExp&&!e.global&&(r=!e.ignoreCase,e=e.source,i=!0);var s=new l;t.ch==undefined&&(t.ch=Number.MAX_VALUE);var o={row:t.line,column:t.ch},u=this,a=null;return{findNext:function(){return this.find(!1)},findPrevious:function(){return this.find(!0)},find:function(t){s.setOptions({needle:e,caseSensitive:r,wrap:!1,backwards:t,regExp:i,start:a||o});var n=s.find(u.ace.session);return n&&n.isEmpty()&&u.getLine(n.start.row).length==n.start.column&&(s.$options.start=n,n=s.find(u.ace.session)),a=n,a},from:function(){return a&&g(a.start)},to:function(){return a&&g(a.end)},replace:function(e){a&&(a.end=u.ace.session.doc.replace(a,e))}}},this.scrollTo=function(e,t){var n=this.ace.renderer,r=n.layerConfig,i=r.maxHeight;i-=(n.$size.scrollerHeight-n.lineHeight)*n.$scrollPastEnd,t!=null&&this.ace.session.setScrollTop(Math.max(0,Math.min(t,i))),e!=null&&this.ace.session.setScrollLeft(Math.max(0,Math.min(e,r.width)))},this.scrollInfo=function(){return 0},this.scrollIntoView=function(e,t){if(e){var n=this.ace.renderer,r={top:0,bottom:t};n.scrollCursorIntoView(m(e),n.lineHeight*2/n.$size.scrollerHeight,r)}},this.getLine=function(e){return this.ace.session.getLine(e)},this.getRange=function(e,t){return this.ace.session.getTextRange(new i(e.line,e.ch,t.line,t.ch))},this.replaceRange=function(e,t,n){return n||(n=t),this.ace.session.replace(new i(t.line,t.ch,n.line,n.ch),e)},this.replaceSelections=function(e){var t=this.ace.selection;if(this.ace.inVirtualSelectionMode){this.ace.session.replace(t.getRange(),e[0]||"");return}t.inVirtualSelectionMode=!0;var n=t.rangeList.ranges;n.length||(n=[this.ace.multiSelect.getRange()]);for(var r=n.length;r--;)this.ace.session.replace(n[r],e[r]||"");t.inVirtualSelectionMode=!1},this.getSelection=function(){return this.ace.getSelectedText()},this.getSelections=function(){return this.listSelections().map(function(e){return this.getRange(e.anchor,e.head)},this)},this.getInputField=function(){return this.ace.textInput.getElement()},this.getWrapperElement=function(){return this.ace.containter};var t={indentWithTabs:"useSoftTabs",indentUnit:"tabSize",tabSize:"tabSize",firstLineNumber:"firstLineNumber",readOnly:"readOnly"};this.setOption=function(e,n){this.state[e]=n;switch(e){case"indentWithTabs":e=t[e],n=!n;break;default:e=t[e]}e&&this.ace.setOption(e,n)},this.getOption=function(e,n){var r=t[e];r&&(n=this.ace.getOption(r));switch(e){case"indentWithTabs":return e=t[e],!n}return r?n:this.state[e]},this.toggleOverwrite=function(e){return this.state.overwrite=e,this.ace.setOverwrite(e)},this.addOverlay=function(e){if(!this.$searchHighlight||!this.$searchHighlight.session){var t=new h(null,"ace_highlight-marker","text"),n=this.ace.session.addDynamicMarker(t);t.id=n.id,t.session=this.ace.session,t.destroy=function(e){t.session.off("change",t.updateOnChange),t.session.off("changeEditor",t.destroy),t.session.removeMarker(t.id),t.session=null},t.updateOnChange=function(e){var n=e.start.row;n==e.end.row?t.cache[n]=undefined:t.cache.splice(n,t.cache.length)},t.session.on("changeEditor",t.destroy),t.session.on("change",t.updateOnChange)}var r=new RegExp(e.query.source,"gmi");this.$searchHighlight=e.highlight=t,this.$searchHighlight.setRegexp(r),this.ace.renderer.updateBackMarkers()},this.removeOverlay=function(e){this.$searchHighlight&&this.$searchHighlight.session&&this.$searchHighlight.destroy()},this.getScrollInfo=function(){var e=this.ace.renderer,t=e.layerConfig;return{left:e.scrollLeft,top:e.scrollTop,height:t.maxHeight,width:t.width,clientHeight:t.height,clientWidth:t.width}},this.getValue=function(){return this.ace.getValue()},this.setValue=function(e){return this.ace.setValue(e)},this.getTokenTypeAt=function(e){var t=this.ace.session.getTokenAt(e.line,e.ch);return t&&/comment|string/.test(t.type)?"string":""},this.findMatchingBracket=function(e){var t=this.ace.session.findMatchingBracket(m(e));return{to:t&&g(t)}},this.indentLine=function(e,t){t===!0?this.ace.session.indentRows(e,e," "):t===!1&&this.ace.session.outdentRows(new i(e,0,e,0))},this.indexFromPos=function(e){return this.ace.session.doc.positionToIndex(m(e))},this.posFromIndex=function(e){return g(this.ace.session.doc.indexToPosition(e))},this.focus=function(e){return this.ace.textInput.focus()},this.blur=function(e){return this.ace.blur()},this.defaultTextHeight=function(e){return this.ace.renderer.layerConfig.lineHeight},this.scanForBracket=function(e,t,n,r){var i=r.bracketRegex.source;if(t==1)var s=this.ace.session.$findClosingBracket(i.slice(1,2),m(e),/paren|text/);else var s=this.ace.session.$findOpeningBracket(i.slice(-2,-1),{row:e.line,column:e.ch+1},/paren|text/);return s&&{pos:g(s)}},this.refresh=function(){return this.ace.resize(!0)},this.getMode=function(){return{name:this.getOption("mode")}}}.call(v.prototype);var y=v.StringStream=function(e,t){this.pos=this.start=0,this.string=e,this.tabSize=t||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0};y.prototype={eol:function(){return this.pos>=this.string.length},sol:function(){return this.pos==this.lineStart},peek:function(){return this.string.charAt(this.pos)||undefined},next:function(){if(this.post},eatSpace:function(){var e=this.pos;while(/[\s\u00a0]/.test(this.string.charAt(this.pos)))++this.pos;return this.pos>e},skipToEnd:function(){this.pos=this.string.length},skipTo:function(e){var t=this.string.indexOf(e,this.pos);if(t>-1)return this.pos=t,!0},backUp:function(e){this.pos-=e},column:function(){throw"not implemented"},indentation:function(){throw"not implemented"},match:function(e,t,n){if(typeof e!="string"){var s=this.string.slice(this.pos).match(e);return s&&s.index>0?null:(s&&t!==!1&&(this.pos+=s[0].length),s)}var r=function(e){return n?e.toLowerCase():e},i=this.string.substr(this.pos,e.length);if(r(i)==r(e))return t!==!1&&(this.pos+=e.length),!0},current:function(){return this.string.slice(this.start,this.pos)},hideFirstChars:function(e,t){this.lineStart+=e;try{return t()}finally{this.lineStart-=e}}},v.defineExtension=function(e,t){v.prototype[e]=t},o.importCssString(".normal-mode .ace_cursor{ border: 1px solid red; background-color: red; opacity: 0.5;}.normal-mode .ace_hidden-cursors .ace_cursor{ background-color: transparent;}.ace_dialog { position: absolute; left: 0; right: 0; background: inherit; z-index: 15; padding: .1em .8em; overflow: hidden; color: inherit;}.ace_dialog-top { border-bottom: 1px solid #444; top: 0;}.ace_dialog-bottom { border-top: 1px solid #444; bottom: 0;}.ace_dialog input { border: none; outline: none; background: transparent; width: 20em; color: inherit; font-family: monospace;}","vimMode"),function(){function e(e,t,n){var r=e.ace.container,i;return i=r.appendChild(document.createElement("div")),n?i.className="ace_dialog ace_dialog-bottom":i.className="ace_dialog ace_dialog-top",typeof t=="string"?i.innerHTML=t:i.appendChild(t),i}function t(e,t){e.state.currentNotificationClose&&e.state.currentNotificationClose(),e.state.currentNotificationClose=t}v.defineExtension("openDialog",function(n,r,i){function a(e){if(typeof e=="string")f.value=e;else{if(o)return;if(e&&e.type=="blur"&&document.activeElement===f)return;u.state.dialog=null,o=!0,s.parentNode.removeChild(s),u.focus(),i.onClose&&i.onClose(s)}}if(this.virtualSelectionMode())return;i||(i={}),t(this,null);var s=e(this,n,i.bottom),o=!1,u=this;this.state.dialog=s;var f=s.getElementsByTagName("input")[0],l;if(f)i.value&&(f.value=i.value,i.selectValueOnOpen!==!1&&f.select()),i.onInput&&v.on(f,"input",function(e){i.onInput(e,f.value,a)}),i.onKeyUp&&v.on(f,"keyup",function(e){i.onKeyUp(e,f.value,a)}),v.on(f,"keydown",function(e){if(i&&i.onKeyDown&&i.onKeyDown(e,f.value,a))return;if(e.keyCode==27||i.closeOnEnter!==!1&&e.keyCode==13)f.blur(),v.e_stop(e),a();e.keyCode==13&&r(f.value)}),i.closeOnBlur!==!1&&v.on(f,"blur",a),f.focus();else if(l=s.getElementsByTagName("button")[0])v.on(l,"click",function(){a(),u.focus()}),i.closeOnBlur!==!1&&v.on(l,"blur",a),l.focus();return a}),v.defineExtension("openNotification",function(n,r){function a(){if(s)return;s=!0,clearTimeout(o),i.parentNode.removeChild(i)}if(this.virtualSelectionMode())return;t(this,a);var i=e(this,n,r&&r.bottom),s=!1,o,u=r&&typeof r.duration!="undefined"?r.duration:5e3;return v.on(i,"click",function(e){v.e_preventDefault(e),a()}),u&&(o=setTimeout(a,u)),a})}();var b=[{keys:"",type:"keyToKey",toKeys:"h"},{keys:"",type:"keyToKey",toKeys:"l"},{keys:"",type:"keyToKey",toKeys:"k"},{keys:"",type:"keyToKey",toKeys:"j"},{keys:"",type:"keyToKey",toKeys:"l"},{keys:"",type:"keyToKey",toKeys:"h",context:"normal"},{keys:"",type:"keyToKey",toKeys:"W"},{keys:"",type:"keyToKey",toKeys:"B",context:"normal"},{keys:"",type:"keyToKey",toKeys:"w"},{keys:"",type:"keyToKey",toKeys:"b",context:"normal"},{keys:"",type:"keyToKey",toKeys:"j"},{keys:"",type:"keyToKey",toKeys:"k"},{keys:"",type:"keyToKey",toKeys:""},{keys:"",type:"keyToKey",toKeys:""},{keys:"",type:"keyToKey",toKeys:"",context:"insert"},{keys:"",type:"keyToKey",toKeys:"",context:"insert"},{keys:"s",type:"keyToKey",toKeys:"cl",context:"normal"},{keys:"s",type:"keyToKey",toKeys:"c",context:"visual"},{keys:"S",type:"keyToKey",toKeys:"cc",context:"normal"},{keys:"S",type:"keyToKey",toKeys:"VdO",context:"visual"},{keys:"",type:"keyToKey",toKeys:"0"},{keys:"",type:"keyToKey",toKeys:"$"},{keys:"",type:"keyToKey",toKeys:""},{keys:"",type:"keyToKey",toKeys:""},{keys:"",type:"keyToKey",toKeys:"j^",context:"normal"},{keys:"",type:"action",action:"toggleOverwrite",context:"insert"},{keys:"H",type:"motion",motion:"moveToTopLine",motionArgs:{linewise:!0,toJumplist:!0}},{keys:"M",type:"motion",motion:"moveToMiddleLine",motionArgs:{linewise:!0,toJumplist:!0}},{keys:"L",type:"motion",motion:"moveToBottomLine",motionArgs:{linewise:!0,toJumplist:!0}},{keys:"h",type:"motion",motion:"moveByCharacters",motionArgs:{forward:!1}},{keys:"l",type:"motion",motion:"moveByCharacters",motionArgs:{forward:!0}},{keys:"j",type:"motion",motion:"moveByLines",motionArgs:{forward:!0,linewise:!0}},{keys:"k",type:"motion",motion:"moveByLines",motionArgs:{forward:!1,linewise:!0}},{keys:"gj",type:"motion",motion:"moveByDisplayLines",motionArgs:{forward:!0}},{keys:"gk",type:"motion",motion:"moveByDisplayLines",motionArgs:{forward:!1}},{keys:"w",type:"motion",motion:"moveByWords",motionArgs:{forward:!0,wordEnd:!1}},{keys:"W",type:"motion",motion:"moveByWords",motionArgs:{forward:!0,wordEnd:!1,bigWord:!0}},{keys:"e",type:"motion",motion:"moveByWords",motionArgs:{forward:!0,wordEnd:!0,inclusive:!0}},{keys:"E",type:"motion",motion:"moveByWords",motionArgs:{forward:!0,wordEnd:!0,bigWord:!0,inclusive:!0}},{keys:"b",type:"motion",motion:"moveByWords",motionArgs:{forward:!1,wordEnd:!1}},{keys:"B",type:"motion",motion:"moveByWords",motionArgs:{forward:!1,wordEnd:!1,bigWord:!0}},{keys:"ge",type:"motion",motion:"moveByWords",motionArgs:{forward:!1,wordEnd:!0,inclusive:!0}},{keys:"gE",type:"motion",motion:"moveByWords",motionArgs:{forward:!1,wordEnd:!0,bigWord:!0,inclusive:!0}},{keys:"{",type:"motion",motion:"moveByParagraph",motionArgs:{forward:!1,toJumplist:!0}},{keys:"}",type:"motion",motion:"moveByParagraph",motionArgs:{forward:!0,toJumplist:!0}},{keys:"",type:"motion",motion:"moveByPage",motionArgs:{forward:!0}},{keys:"",type:"motion",motion:"moveByPage",motionArgs:{forward:!1}},{keys:"",type:"motion",motion:"moveByScroll",motionArgs:{forward:!0,explicitRepeat:!0}},{keys:"",type:"motion",motion:"moveByScroll",motionArgs:{forward:!1,explicitRepeat:!0}},{keys:"gg",type:"motion",motion:"moveToLineOrEdgeOfDocument",motionArgs:{forward:!1,explicitRepeat:!0,linewise:!0,toJumplist:!0}},{keys:"G",type:"motion",motion:"moveToLineOrEdgeOfDocument",motionArgs:{forward:!0,explicitRepeat:!0,linewise:!0,toJumplist:!0}},{keys:"0",type:"motion",motion:"moveToStartOfLine"},{keys:"^",type:"motion",motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:"+",type:"motion",motion:"moveByLines",motionArgs:{forward:!0,toFirstChar:!0}},{keys:"-",type:"motion",motion:"moveByLines",motionArgs:{forward:!1,toFirstChar:!0}},{keys:"_",type:"motion",motion:"moveByLines",motionArgs:{forward:!0,toFirstChar:!0,repeatOffset:-1}},{keys:"$",type:"motion",motion:"moveToEol",motionArgs:{inclusive:!0}},{keys:"%",type:"motion",motion:"moveToMatchedSymbol",motionArgs:{inclusive:!0,toJumplist:!0}},{keys:"f",type:"motion",motion:"moveToCharacter",motionArgs:{forward:!0,inclusive:!0}},{keys:"F",type:"motion",motion:"moveToCharacter",motionArgs:{forward:!1}},{keys:"t",type:"motion",motion:"moveTillCharacter",motionArgs:{forward:!0,inclusive:!0}},{keys:"T",type:"motion",motion:"moveTillCharacter",motionArgs:{forward:!1}},{keys:";",type:"motion",motion:"repeatLastCharacterSearch",motionArgs:{forward:!0}},{keys:",",type:"motion",motion:"repeatLastCharacterSearch",motionArgs:{forward:!1}},{keys:"'",type:"motion",motion:"goToMark",motionArgs:{toJumplist:!0,linewise:!0}},{keys:"`",type:"motion",motion:"goToMark",motionArgs:{toJumplist:!0}},{keys:"]`",type:"motion",motion:"jumpToMark",motionArgs:{forward:!0}},{keys:"[`",type:"motion",motion:"jumpToMark",motionArgs:{forward:!1}},{keys:"]'",type:"motion",motion:"jumpToMark",motionArgs:{forward:!0,linewise:!0}},{keys:"['",type:"motion",motion:"jumpToMark",motionArgs:{forward:!1,linewise:!0}},{keys:"]p",type:"action",action:"paste",isEdit:!0,actionArgs:{after:!0,isEdit:!0,matchIndent:!0}},{keys:"[p",type:"action",action:"paste",isEdit:!0,actionArgs:{after:!1,isEdit:!0,matchIndent:!0}},{keys:"]",type:"motion",motion:"moveToSymbol",motionArgs:{forward:!0,toJumplist:!0}},{keys:"[",type:"motion",motion:"moveToSymbol",motionArgs:{forward:!1,toJumplist:!0}},{keys:"|",type:"motion",motion:"moveToColumn"},{keys:"o",type:"motion",motion:"moveToOtherHighlightedEnd",context:"visual"},{keys:"O",type:"motion",motion:"moveToOtherHighlightedEnd",motionArgs:{sameLine:!0},context:"visual"},{keys:"d",type:"operator",operator:"delete"},{keys:"y",type:"operator",operator:"yank"},{keys:"c",type:"operator",operator:"change"},{keys:">",type:"operator",operator:"indent",operatorArgs:{indentRight:!0}},{keys:"<",type:"operator",operator:"indent",operatorArgs:{indentRight:!1}},{keys:"g~",type:"operator",operator:"changeCase"},{keys:"gu",type:"operator",operator:"changeCase",operatorArgs:{toLower:!0},isEdit:!0},{keys:"gU",type:"operator",operator:"changeCase",operatorArgs:{toLower:!1},isEdit:!0},{keys:"n",type:"motion",motion:"findNext",motionArgs:{forward:!0,toJumplist:!0}},{keys:"N",type:"motion",motion:"findNext",motionArgs:{forward:!1,toJumplist:!0}},{keys:"x",type:"operatorMotion",operator:"delete",motion:"moveByCharacters",motionArgs:{forward:!0},operatorMotionArgs:{visualLine:!1}},{keys:"X",type:"operatorMotion",operator:"delete",motion:"moveByCharacters",motionArgs:{forward:!1},operatorMotionArgs:{visualLine:!0}},{keys:"D",type:"operatorMotion",operator:"delete",motion:"moveToEol",motionArgs:{inclusive:!0},context:"normal"},{keys:"D",type:"operator",operator:"delete",operatorArgs:{linewise:!0},context:"visual"},{keys:"Y",type:"operatorMotion",operator:"yank",motion:"moveToEol",motionArgs:{inclusive:!0},context:"normal"},{keys:"Y",type:"operator",operator:"yank",operatorArgs:{linewise:!0},context:"visual"},{keys:"C",type:"operatorMotion",operator:"change",motion:"moveToEol",motionArgs:{inclusive:!0},context:"normal"},{keys:"C",type:"operator",operator:"change",operatorArgs:{linewise:!0},context:"visual"},{keys:"~",type:"operatorMotion",operator:"changeCase",motion:"moveByCharacters",motionArgs:{forward:!0},operatorArgs:{shouldMoveCursor:!0},context:"normal"},{keys:"~",type:"operator",operator:"changeCase",context:"visual"},{keys:"",type:"operatorMotion",operator:"delete",motion:"moveByWords",motionArgs:{forward:!1,wordEnd:!1},context:"insert"},{keys:"",type:"action",action:"jumpListWalk",actionArgs:{forward:!0}},{keys:"",type:"action",action:"jumpListWalk",actionArgs:{forward:!1}},{keys:"",type:"action",action:"scroll",actionArgs:{forward:!0,linewise:!0}},{keys:"",type:"action",action:"scroll",actionArgs:{forward:!1,linewise:!0}},{keys:"a",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{insertAt:"charAfter"},context:"normal"},{keys:"A",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{insertAt:"eol"},context:"normal"},{keys:"A",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{insertAt:"endOfSelectedArea"},context:"visual"},{keys:"i",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{insertAt:"inplace"},context:"normal"},{keys:"I",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{insertAt:"firstNonBlank"},context:"normal"},{keys:"I",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{insertAt:"startOfSelectedArea"},context:"visual"},{keys:"o",type:"action",action:"newLineAndEnterInsertMode",isEdit:!0,interlaceInsertRepeat:!0,actionArgs:{after:!0},context:"normal"},{keys:"O",type:"action",action:"newLineAndEnterInsertMode",isEdit:!0,interlaceInsertRepeat:!0,actionArgs:{after:!1},context:"normal"},{keys:"v",type:"action",action:"toggleVisualMode"},{keys:"V",type:"action",action:"toggleVisualMode",actionArgs:{linewise:!0}},{keys:"",type:"action",action:"toggleVisualMode",actionArgs:{blockwise:!0}},{keys:"",type:"action",action:"toggleVisualMode",actionArgs:{blockwise:!0}},{keys:"gv",type:"action",action:"reselectLastSelection"},{keys:"J",type:"action",action:"joinLines",isEdit:!0},{keys:"p",type:"action",action:"paste",isEdit:!0,actionArgs:{after:!0,isEdit:!0}},{keys:"P",type:"action",action:"paste",isEdit:!0,actionArgs:{after:!1,isEdit:!0}},{keys:"r",type:"action",action:"replace",isEdit:!0},{keys:"@",type:"action",action:"replayMacro"},{keys:"q",type:"action",action:"enterMacroRecordMode"},{keys:"R",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{replace:!0}},{keys:"u",type:"action",action:"undo",context:"normal"},{keys:"u",type:"operator",operator:"changeCase",operatorArgs:{toLower:!0},context:"visual",isEdit:!0},{keys:"U",type:"operator",operator:"changeCase",operatorArgs:{toLower:!1},context:"visual",isEdit:!0},{keys:"",type:"action",action:"redo"},{keys:"m",type:"action",action:"setMark"},{keys:'"',type:"action",action:"setRegister"},{keys:"zz",type:"action",action:"scrollToCursor",actionArgs:{position:"center"}},{keys:"z.",type:"action",action:"scrollToCursor",actionArgs:{position:"center"},motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:"zt",type:"action",action:"scrollToCursor",actionArgs:{position:"top"}},{keys:"z",type:"action",action:"scrollToCursor",actionArgs:{position:"top"},motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:"z-",type:"action",action:"scrollToCursor",actionArgs:{position:"bottom"}},{keys:"zb",type:"action",action:"scrollToCursor",actionArgs:{position:"bottom"},motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:".",type:"action",action:"repeatLastEdit"},{keys:"",type:"action",action:"incrementNumberToken",isEdit:!0,actionArgs:{increase:!0,backtrack:!1}},{keys:"",type:"action",action:"incrementNumberToken",isEdit:!0,actionArgs:{increase:!1,backtrack:!1}},{keys:"",type:"action",action:"indent",actionArgs:{indentRight:!0},context:"insert"},{keys:"",type:"action",action:"indent",actionArgs:{indentRight:!1},context:"insert"},{keys:"a",type:"motion",motion:"textObjectManipulation"},{keys:"i",type:"motion",motion:"textObjectManipulation",motionArgs:{textObjectInner:!0}},{keys:"/",type:"search",searchArgs:{forward:!0,querySrc:"prompt",toJumplist:!0}},{keys:"?",type:"search",searchArgs:{forward:!1,querySrc:"prompt",toJumplist:!0}},{keys:"*",type:"search",searchArgs:{forward:!0,querySrc:"wordUnderCursor",wholeWordOnly:!0,toJumplist:!0}},{keys:"#",type:"search",searchArgs:{forward:!1,querySrc:"wordUnderCursor",wholeWordOnly:!0,toJumplist:!0}},{keys:"g*",type:"search",searchArgs:{forward:!0,querySrc:"wordUnderCursor",toJumplist:!0}},{keys:"g#",type:"search",searchArgs:{forward:!1,querySrc:"wordUnderCursor",toJumplist:!0}},{keys:":",type:"ex"}],w=[{name:"colorscheme",shortName:"colo"},{name:"map"},{name:"imap",shortName:"im"},{name:"nmap",shortName:"nm"},{name:"vmap",shortName:"vm"},{name:"unmap"},{name:"write",shortName:"w"},{name:"undo",shortName:"u"},{name:"redo",shortName:"red"},{name:"set",shortName:"se"},{name:"set",shortName:"se"},{name:"setlocal",shortName:"setl"},{name:"setglobal",shortName:"setg"},{name:"sort",shortName:"sor"},{name:"substitute",shortName:"s",possiblyAsync:!0},{name:"nohlsearch",shortName:"noh"},{name:"yank",shortName:"y"},{name:"delmarks",shortName:"delm"},{name:"registers",shortName:"reg",excludeFromCommandHistory:!0},{name:"global",shortName:"g"}],E=v.Pos,S=function(){return st};v.defineOption("vimMode",!1,function(e,t,n){t&&e.getOption("keyMap")!="vim"?e.setOption("keyMap","vim"):!t&&n!=v.Init&&/^vim/.test(e.getOption("keyMap"))&&e.setOption("keyMap","default")});var L={Shift:"S",Ctrl:"C",Alt:"A",Cmd:"D",Mod:"A"},A={Enter:"CR",Backspace:"BS",Delete:"Del",Insert:"Ins"},_=/[\d]/,D=[v.isWordChar,function(e){return e&&!v.isWordChar(e)&&!/\s/.test(e)}],P=[function(e){return/\S/.test(e)}],B=H(65,26),j=H(97,26),F=H(48,10),I=[].concat(B,j,F,["<",">"]),q=[].concat(B,j,F,["-",'"',".",":","/"]),J={};K("filetype",undefined,"string",["ft"],function(e,t){if(t===undefined)return;if(e===undefined){var n=t.getOption("mode");return n=="null"?"":n}var n=e==""?"null":e;t.setOption("mode",n)});var Y=function(){function s(s,o,u){function l(n){var r=++t%e,o=i[r];o&&o.clear(),i[r]=s.setBookmark(n)}var a=t%e,f=i[a];if(f){var c=f.find();c&&!At(c,o)&&l(o)}else l(o);l(u),n=t,r=t-e+1,r<0&&(r=0)}function o(s,o){t+=o,t>n?t=n:t0?1:-1,f,l=s.getCursor();do{t+=a,u=i[(e+t)%e];if(u&&(f=u.find())&&!At(l,f))break}while(tr)}return u}var e=100,t=-1,n=0,r=0,i=new Array(e);return{cachedCursor:undefined,add:s,move:o}},Z=function(e){return e?{changes:e.changes,expectCursorActivityForChange:e.expectCursorActivityForChange}:{changes:[],expectCursorActivityForChange:!1}};et.prototype={exitMacroRecordMode:function(){var e=nt.macroModeState;e.onRecordingDone&&e.onRecordingDone(),e.onRecordingDone=undefined,e.isRecording=!1},enterMacroRecordMode:function(e,t){var n=nt.registerController.getRegister(t);n&&(n.clear(),this.latestRegister=t,e.openDialog&&(this.onRecordingDone=e.openDialog("(recording)["+t+"]",null,{bottom:!0})),this.isRecording=!0)}};var nt,it,st={buildKeyMap:function(){},getRegisterController:function(){return nt.registerController},resetVimGlobalState_:rt,getVimGlobalState_:function(){return nt},maybeInitVimState_:tt,suppressErrorLogging:!1,InsertModeKey:er,map:function(e,t,n){Rn.map(e,t,n)},unmap:function(e,t){Rn.unmap(e,t)},setOption:Q,getOption:G,defineOption:K,defineEx:function(e,t,n){if(!t)t=e;else if(e.indexOf(t)!==0)throw new Error('(Vim.defineEx) "'+t+'" is not a prefix of "'+e+'", command not registered');qn[e]=n,Rn.commandMap_[t]={name:e,shortName:t,type:"api"}},handleKey:function(e,t,n){var r=this.findKey(e,t,n);if(typeof r=="function")return r()},findKey:function(e,t,n){function i(){var r=nt.macroModeState;if(r.isRecording){if(t=="q")return r.exitMacroRecordMode(),ut(e),!0;n!="mapping"&&$n(r,t)}}function s(){if(t=="")return ut(e),r.visualMode?$t(e):r.insertMode&&zn(e),!0}function o(n){var r;while(n)r=/<\w+-.+?>|<\w+>|./.exec(n),t=r[0],n=n.substring(r.index+t.length),v.Vim.handleKey(e,t,"mapping")}function u(){if(s())return!0;var n=r.inputState.keyBuffer=r.inputState.keyBuffer+t,i=t.length==1,o=ht.matchCommand(n,b,r.inputState,"insert");while(n.length>1&&o.type!="full"){var n=r.inputState.keyBuffer=n.slice(1),u=ht.matchCommand(n,b,r.inputState,"insert");u.type!="none"&&(o=u)}if(o.type=="none")return ut(e),!1;if(o.type=="partial")return it&&window.clearTimeout(it),it=window.setTimeout(function(){r.insertMode&&r.inputState.keyBuffer&&ut(e)},G("insertModeEscKeysTimeout")),!i;it&&window.clearTimeout(it);if(i){var a=e.listSelections();for(var f=0;f0||this.motionRepeat.length>0)e=1,this.prefixRepeat.length>0&&(e*=parseInt(this.prefixRepeat.join(""),10)),this.motionRepeat.length>0&&(e*=parseInt(this.motionRepeat.join(""),10));return e},at.prototype={setText:function(e,t,n){this.keyBuffer=[e||""],this.linewise=!!t,this.blockwise=!!n},pushText:function(e,t){t&&(this.linewise||this.keyBuffer.push("\n"),this.linewise=!0),this.keyBuffer.push(e)},pushInsertModeChanges:function(e){this.insertModeChanges.push(Z(e))},pushSearchQuery:function(e){this.searchQueries.push(e)},clear:function(){this.keyBuffer=[],this.insertModeChanges=[],this.searchQueries=[],this.linewise=!1},toString:function(){return this.keyBuffer.join("")}},lt.prototype={pushText:function(e,t,n,r,i){r&&n.charAt(n.length-1)!=="\n"&&(n+="\n");var s=this.isValidRegister(e)?this.getRegister(e):null;if(!s){switch(t){case"yank":this.registers[0]=new at(n,r,i);break;case"delete":case"change":n.indexOf("\n")==-1?this.registers["-"]=new at(n,r):(this.shiftNumericRegisters_(),this.registers[1]=new at(n,r))}this.unnamedRegister.setText(n,r,i);return}var o=X(e);o?s.pushText(n,r):s.setText(n,r,i),this.unnamedRegister.setText(s.toString(),r)},getRegister:function(e){return this.isValidRegister(e)?(e=e.toLowerCase(),this.registers[e]||(this.registers[e]=new at),this.registers[e]):this.unnamedRegister},isValidRegister:function(e){return e&&$(e,q)},shiftNumericRegisters_:function(){for(var e=9;e>=2;e--)this.registers[e]=this.getRegister(""+(e-1))}},ct.prototype={nextMatch:function(e,t){var n=this.historyBuffer,r=t?-1:1;this.initialPrefix===null&&(this.initialPrefix=e);for(var i=this.iterator+r;t?i>=0:i=n.length)return this.iterator=n.length,this.initialPrefix;if(i<0)return e},pushInput:function(e){var t=this.historyBuffer.indexOf(e);t>-1&&this.historyBuffer.splice(t,1),e.length&&this.historyBuffer.push(e)},reset:function(){this.initialPrefix=null,this.iterator=this.historyBuffer.length}};var ht={matchCommand:function(e,t,n,r){var i=Tt(e,t,r,n);if(!i.full&&!i.partial)return{type:"none"};if(!i.full&&i.partial)return{type:"partial"};var s;for(var o=0;o"){var a=Ct(e);if(//.test(a))return{type:"none"};n.selectedCharacter=a}return{type:"full",command:s}},processCommand:function(e,t,n){t.inputState.repeatOverride=n.repeatOverride;switch(n.type){case"motion":this.processMotion(e,t,n);break;case"operator":this.processOperator(e,t,n);break;case"operatorMotion":this.processOperatorMotion(e,t,n);break;case"action":this.processAction(e,t,n);break;case"search":this.processSearch(e,t,n);break;case"ex":case"keyToEx":this.processEx(e,t,n);break;default:}},processMotion:function(e,t,n){t.inputState.motion=n.motion,t.inputState.motionArgs=Et(n.motionArgs),this.evalInput(e,t)},processOperator:function(e,t,n){var r=t.inputState;if(r.operator){if(r.operator==n.operator){r.motion="expandToLine",r.motionArgs={linewise:!0},this.evalInput(e,t);return}ut(e)}r.operator=n.operator,r.operatorArgs=Et(n.operatorArgs),t.visualMode&&this.evalInput(e,t)},processOperatorMotion:function(e,t,n){var r=t.visualMode,i=Et(n.operatorMotionArgs);i&&r&&i.visualLine&&(t.visualLine=!0),this.processOperator(e,t,n),r||this.processMotion(e,t,n)},processAction:function(e,t,n){var r=t.inputState,i=r.getRepeat(),s=!!i,o=Et(n.actionArgs)||{};r.selectedCharacter&&(o.selectedCharacter=r.selectedCharacter),n.operator&&this.processOperator(e,t,n),n.motion&&this.processMotion(e,t,n),(n.motion||n.operator)&&this.evalInput(e,t),o.repeat=i||1,o.repeatIsExplicit=s,o.registerName=r.registerName,ut(e),t.lastMotion=null,n.isEdit&&this.recordLastEdit(t,r,n),yt[n.action](e,o,t)},processSearch:function(e,t,n){function a(r,i,s){nt.searchHistoryController.pushInput(r),nt.searchHistoryController.reset();try{Mn(e,r,i,s)}catch(o){Cn(e,"Invalid regex: "+r),ut(e);return}ht.processMotion(e,t,{type:"motion",motion:"findNext",motionArgs:{forward:!0,toJumplist:n.searchArgs.toJumplist}})}function f(t){e.scrollTo(u.left,u.top),a(t,!0,!0);var n=nt.macroModeState;n.isRecording&&Kn(n,t)}function l(t,n,i){var s=v.keyName(t),o,a;s=="Up"||s=="Down"?(o=s=="Up"?!0:!1,a=t.target?t.target.selectionEnd:0,n=nt.searchHistoryController.nextMatch(n,o)||"",i(n),a&&t.target&&(t.target.selectionEnd=t.target.selectionStart=Math.min(a,t.target.value.length))):s!="Left"&&s!="Right"&&s!="Ctrl"&&s!="Alt"&&s!="Shift"&&nt.searchHistoryController.reset();var f;try{f=Mn(e,n,!0,!0)}catch(t){}f?e.scrollIntoView(Pn(e,!r,f),30):(Hn(e),e.scrollTo(u.left,u.top))}function c(t,n,r){var i=v.keyName(t);i=="Esc"||i=="Ctrl-C"||i=="Ctrl-["||i=="Backspace"&&n==""?(nt.searchHistoryController.pushInput(n),nt.searchHistoryController.reset(),Mn(e,o),Hn(e),e.scrollTo(u.left,u.top),v.e_stop(t),ut(e),r(),e.focus()):i=="Up"||i=="Down"?v.e_stop(t):i=="Ctrl-U"&&(v.e_stop(t),r(""))}if(!e.getSearchCursor)return;var r=n.searchArgs.forward,i=n.searchArgs.wholeWordOnly;dn(e).setReversed(!r);var s=r?"/":"?",o=dn(e).getQuery(),u=e.getScrollInfo();switch(n.searchArgs.querySrc){case"prompt":var h=nt.macroModeState;if(h.isPlaying){var p=h.replaySearchQueries.shift();a(p,!0,!1)}else An(e,{onClose:f,prefix:s,desc:Ln,onKeyUp:l,onKeyDown:c});break;case"wordUnderCursor":var d=Gt(e,!1,!0,!1,!0),m=!0;d||(d=Gt(e,!1,!0,!1,!1),m=!1);if(!d)return;var p=e.getLine(d.start.line).substring(d.start.ch,d.end.ch);m&&i?p="\\b"+p+"\\b":p=Bt(p),nt.jumpList.cachedCursor=e.getCursor(),e.setCursor(d.start),a(p,!0,!1)}},processEx:function(e,t,n){function r(t){nt.exCommandHistoryController.pushInput(t),nt.exCommandHistoryController.reset(),Rn.processCommand(e,t)}function i(t,n,r){var i=v.keyName(t),s,o;if(i=="Esc"||i=="Ctrl-C"||i=="Ctrl-["||i=="Backspace"&&n=="")nt.exCommandHistoryController.pushInput(n),nt.exCommandHistoryController.reset(),v.e_stop(t),ut(e),r(),e.focus();i=="Up"||i=="Down"?(v.e_stop(t),s=i=="Up"?!0:!1,o=t.target?t.target.selectionEnd:0,n=nt.exCommandHistoryController.nextMatch(n,s)||"",r(n),o&&t.target&&(t.target.selectionEnd=t.target.selectionStart=Math.min(o,t.target.value.length))):i=="Ctrl-U"?(v.e_stop(t),r("")):i!="Left"&&i!="Right"&&i!="Ctrl"&&i!="Alt"&&i!="Shift"&&nt.exCommandHistoryController.reset()}n.type=="keyToEx"?Rn.processCommand(e,n.exArgs.input):t.visualMode?An(e,{onClose:r,prefix:":",value:"'<,'>",onKeyDown:i,selectValueOnOpen:!1}):An(e,{onClose:r,prefix:":",onKeyDown:i})},evalInput:function(e,t){var n=t.inputState,r=n.motion,i=n.motionArgs||{},s=n.operator,o=n.operatorArgs||{},u=n.registerName,a=t.sel,f=Lt(t.visualMode?wt(e,a.head):e.getCursor("head")),l=Lt(t.visualMode?wt(e,a.anchor):e.getCursor("anchor")),c=Lt(f),h=Lt(l),p,d,v;s&&this.recordLastEdit(t,n),n.repeatOverride!==undefined?v=n.repeatOverride:v=n.getRepeat();if(v>0&&i.explicitRepeat)i.repeatIsExplicit=!0;else if(i.noRepeat||!i.explicitRepeat&&v===0)v=1,i.repeatIsExplicit=!1;n.selectedCharacter&&(i.selectedCharacter=o.selectedCharacter=n.selectedCharacter),i.repeat=v,ut(e);if(r){var m=pt[r](e,f,i,t);t.lastMotion=pt[r];if(!m)return;if(i.toJumplist){!s&&e.ace.curOp!=null&&(e.ace.curOp.command.scrollIntoView="center-animate");var g=nt.jumpList,y=g.cachedCursor;y?(Yt(e,y,m),delete g.cachedCursor):Yt(e,f,m)}m instanceof Array?(d=m[0],p=m[1]):p=m,p||(p=Lt(f));if(t.visualMode){if(!t.visualBlock||p.ch!==Infinity)p=wt(e,p,t.visualBlock);d&&(d=wt(e,d,!0)),d=d||h,a.anchor=d,a.head=p,Wt(e),an(e,t,"<",Ot(d,p)?d:p),an(e,t,">",Ot(d,p)?p:d)}else s||(p=wt(e,p),e.setCursor(p.line,p.ch))}if(s){if(o.lastSel){d=h;var b=o.lastSel,w=Math.abs(b.head.line-b.anchor.line),S=Math.abs(b.head.ch-b.anchor.ch);b.visualLine?p=E(h.line+w,h.ch):b.visualBlock?p=E(h.line+w,h.ch+S):b.head.line==b.anchor.line?p=E(h.line,h.ch+S):p=E(h.line+w,h.ch),t.visualMode=!0,t.visualLine=b.visualLine,t.visualBlock=b.visualBlock,a=t.sel={anchor:d,head:p},Wt(e)}else t.visualMode&&(o.lastSel={anchor:Lt(a.anchor),head:Lt(a.head),visualBlock:t.visualBlock,visualLine:t.visualLine});var x,T,N,C,k;if(t.visualMode){x=Mt(a.head,a.anchor),T=_t(a.head,a.anchor),N=t.visualLine||o.linewise,C=t.visualBlock?"block":N?"line":"char",k=Xt(e,{anchor:x,head:T},C);if(N){var L=k.ranges;if(C=="block")for(var A=0;Af&&i.line==f)return this.moveToEol(e,t,n,r);var l=e.ace.session.getFoldLine(u);return l&&(n.forward?u>l.start.row&&(u=l.end.row+1):u=l.start.row),n.toFirstChar&&(s=Qt(e.getLine(u)),r.lastHPos=s),r.lastHSPos=e.charCoords(E(u,s),"div").left,E(u,s)},moveByDisplayLines:function(e,t,n,r){var i=t;switch(r.lastMotion){case this.moveByDisplayLines:case this.moveByScroll:case this.moveByLines:case this.moveToColumn:case this.moveToEol:break;default:r.lastHSPos=e.charCoords(i,"div").left}var s=n.repeat,o=e.findPosV(i,n.forward?s:-s,"line",r.lastHSPos);if(o.hitSide)if(n.forward)var u=e.charCoords(o,"div"),a={top:u.top+8,left:r.lastHSPos},o=e.coordsChar(a,"div");else{var f=e.charCoords(E(e.firstLine(),0),"div");f.left=r.lastHSPos,o=e.coordsChar(f,"div")}return r.lastHPos=o.ch,o},moveByPage:function(e,t,n){var r=t,i=n.repeat;return e.findPosV(r,n.forward?i:-i,"page")},moveByParagraph:function(e,t,n){var r=n.forward?1:-1;return ln(e,t,n.repeat,r)},moveByScroll:function(e,t,n,r){var i=e.getScrollInfo(),s=null,o=n.repeat;o||(o=i.clientHeight/(2*e.defaultTextHeight()));var u=e.charCoords(t,"local");n.repeat=o;var s=pt.moveByDisplayLines(e,t,n,r);if(!s)return null;var a=e.charCoords(s,"local");return e.scrollTo(null,i.top+a.top-u.top),s},moveByWords:function(e,t,n){return sn(e,t,n.repeat,!!n.forward,!!n.wordEnd,!!n.bigWord)},moveTillCharacter:function(e,t,n){var r=n.repeat,i=on(e,r,n.forward,n.selectedCharacter),s=n.forward?-1:1;return Zt(s,n),i?(i.ch+=s,i):null},moveToCharacter:function(e,t,n){var r=n.repeat;return Zt(0,n),on(e,r,n.forward,n.selectedCharacter)||t},moveToSymbol:function(e,t,n){var r=n.repeat;return nn(e,r,n.forward,n.selectedCharacter)||t},moveToColumn:function(e,t,n,r){var i=n.repeat;return r.lastHPos=i-1,r.lastHSPos=e.charCoords(t,"div").left,un(e,i)},moveToEol:function(e,t,n,r){var i=t;r.lastHPos=Infinity;var s=E(i.line+n.repeat-1,Infinity),o=e.clipPos(s);return o.ch--,r.lastHSPos=e.charCoords(o,"div").left,s},moveToFirstNonWhiteSpaceCharacter:function(e,t){var n=t;return E(n.line,Qt(e.getLine(n.line)))},moveToMatchedSymbol:function(e,t){var n=t,r=n.line,i=n.ch,s=e.getLine(r),o;do{o=s.charAt(i++);if(o&&z(o)){var u=e.getTokenTypeAt(E(r,i));if(u!=="string"&&u!=="comment")break}}while(o);if(o){var a=e.findMatchingBracket(E(r,i));return a.to}return n},moveToStartOfLine:function(e,t){return E(t.line,0)},moveToLineOrEdgeOfDocument:function(e,t,n){var r=n.forward?e.lastLine():e.firstLine();return n.repeatIsExplicit&&(r=n.repeat-e.getOption("firstLineNumber")),E(r,Qt(e.getLine(r)))},textObjectManipulation:function(e,t,n,r){var i={"(":")",")":"(","{":"}","}":"{","[":"]","]":"["},s={"'":!0,'"':!0},o=n.selectedCharacter;o=="b"?o="(":o=="B"&&(o="{");var u=!n.textObjectInner,a;if(i[o])a=cn(e,t,o,u);else if(s[o])a=hn(e,t,o,u);else if(o==="W")a=Gt(e,u,!0,!0);else if(o==="w")a=Gt(e,u,!0,!1);else{if(o!=="p")return null;a=ln(e,t,n.repeat,0,u),n.linewise=!0;if(r.visualMode)r.visualLine||(r.visualLine=!0);else{var f=r.inputState.operatorArgs;f&&(f.linewise=!0),a.end.line--}}return e.state.vim.visualMode?zt(e,a.start,a.end):[a.start,a.end]},repeatLastCharacterSearch:function(e,t,n){var r=nt.lastCharacterSearch,i=n.repeat,s=n.forward===r.forward,o=(r.increment?1:0)*(s?-1:1);e.moveH(-o,"char"),n.inclusive=s?!0:!1;var u=on(e,i,s,r.selectedCharacter);return u?(u.ch+=o,u):(e.moveH(o,"char"),t)}},mt={change:function(e,t,n){var r,i,s=e.state.vim;nt.macroModeState.lastInsertModeChanges.inVisualBlock=s.visualBlock;if(!s.visualMode){var o=n[0].anchor,u=n[0].head;i=e.getRange(o,u);var a=s.lastEditInputState||{};if(a.motion=="moveByWords"&&!V(i)){var f=/\s+$/.exec(i);f&&a.motionArgs&&a.motionArgs.forward&&(u=St(u,0,-f[0].length),i=i.slice(0,-f[0].length))}var l=new E(o.line-1,Number.MAX_VALUE),c=e.firstLine()==e.lastLine();u.line>e.lastLine()&&t.linewise&&!c?e.replaceRange("",l,u):e.replaceRange("",o,u),t.linewise&&(c||(e.setCursor(l),v.commands.newlineAndIndent(e)),o.ch=Number.MAX_VALUE),r=o}else{i=e.getSelection();var h=vt("",n.length);e.replaceSelections(h),r=Mt(n[0].head,n[0].anchor)}nt.registerController.pushText(t.registerName,"change",i,t.linewise,n.length>1),yt.enterInsertMode(e,{head:r},e.state.vim)},"delete":function(e,t,n){var r,i,s=e.state.vim;if(!s.visualBlock){var o=n[0].anchor,u=n[0].head;t.linewise&&u.line!=e.firstLine()&&o.line==e.lastLine()&&o.line==u.line-1&&(o.line==e.firstLine()?o.ch=0:o=E(o.line-1,Pt(e,o.line-1))),i=e.getRange(o,u),e.replaceRange("",o,u),r=o,t.linewise&&(r=pt.moveToFirstNonWhiteSpaceCharacter(e,o))}else{i=e.getSelection();var a=vt("",n.length);e.replaceSelections(a),r=n[0].anchor}nt.registerController.pushText(t.registerName,"delete",i,t.linewise,s.visualBlock);var f=s.insertMode;return wt(e,r,f)},indent:function(e,t,n){var r=e.state.vim,i=n[0].anchor.line,s=r.visualBlock?n[n.length-1].anchor.line:n[0].head.line,o=r.visualMode?t.repeat:1;t.linewise&&s--;for(var u=i;u<=s;u++)for(var a=0;af.top?(a.line+=(u-f.top)/i,a.line=Math.ceil(a.line),e.setCursor(a),f=e.charCoords(a,"local"),e.scrollTo(null,f.top)):e.scrollTo(null,u);else{var l=u+e.getScrollInfo().clientHeight;l=i.anchor.line?s=St(i.head,0,1):s=E(i.anchor.line,0);else if(r=="inplace"&&n.visualMode)return;e.setOption("disableInput",!1),t&&t.replace?(e.toggleOverwrite(!0),e.setOption("keyMap","vim-replace"),v.signal(e,"vim-mode-change",{mode:"replace"})):(e.toggleOverwrite(!1),e.setOption("keyMap","vim-insert"),v.signal(e,"vim-mode-change",{mode:"insert"})),nt.macroModeState.isPlaying||(e.on("change",Qn),v.on(e.getInputField(),"keydown",tr)),n.visualMode&&$t(e),It(e,s,o)},toggleVisualMode:function(e,t,n){var r=t.repeat,i=e.getCursor(),s;n.visualMode?n.visualLine^t.linewise||n.visualBlock^t.blockwise?(n.visualLine=!!t.linewise,n.visualBlock=!!t.blockwise,v.signal(e,"vim-mode-change",{mode:"visual",subMode:n.visualLine?"linewise":n.visualBlock?"blockwise":""}),Wt(e)):$t(e):(n.visualMode=!0,n.visualLine=!!t.linewise,n.visualBlock=!!t.blockwise,s=wt(e,E(i.line,i.ch+r-1),!0),n.sel={anchor:i,head:s},v.signal(e,"vim-mode-change",{mode:"visual",subMode:n.visualLine?"linewise":n.visualBlock?"blockwise":""}),Wt(e),an(e,n,"<",Mt(i,s)),an(e,n,">",_t(i,s)))},reselectLastSelection:function(e,t,n){var r=n.lastSelection;n.visualMode&&Ut(e,n);if(r){var i=r.anchorMark.find(),s=r.headMark.find();if(!i||!s)return;n.sel={anchor:i,head:s},n.visualMode=!0,n.visualLine=r.visualLine,n.visualBlock=r.visualBlock,Wt(e),an(e,n,"<",Mt(i,s)),an(e,n,">",_t(i,s)),v.signal(e,"vim-mode-change",{mode:"visual",subMode:n.visualLine?"linewise":n.visualBlock?"blockwise":""})}},joinLines:function(e,t,n){var r,i;if(n.visualMode){r=e.getCursor("anchor"),i=e.getCursor("head");if(Ot(i,r)){var s=i;i=r,r=s}i.ch=Pt(e,i.line)-1}else{var o=Math.max(t.repeat,2);r=e.getCursor(),i=wt(e,E(r.line+o-1,Infinity))}var u=0;for(var a=r.line;a1)var s=Array(t.repeat+1).join(s);var p=i.linewise,d=i.blockwise;if(p&&!d)n.visualMode?s=n.visualLine?s.slice(0,-1):"\n"+s.slice(0,s.length-1)+"\n":t.after?(s="\n"+s.slice(0,s.length-1),r.ch=Pt(e,r.line)):r.ch=0;else{if(d){s=s.split("\n");for(var v=0;ve.lastLine()&&e.replaceRange("\n",E(C,0));var k=Pt(e,C);ka.length&&(s=a.length),o=E(i.line,s)}if(r=="\n")n.visualMode||e.replaceRange("",i,o),(v.commands.newlineAndIndentContinueComment||v.commands.newlineAndIndent)(e);else{var f=e.getRange(i,o);f=f.replace(/[^\n]/g,r);if(n.visualBlock){var l=(new Array(e.getOption("tabSize")+1)).join(" ");f=e.getSelection(),f=f.replace(/\t/g,l).replace(/[^\n]/g,r).split("\n"),e.replaceSelections(f)}else e.replaceRange(f,i,o);n.visualMode?(i=Ot(u[0].anchor,u[0].head)?u[0].anchor:u[0].head,e.setCursor(i),$t(e,!1)):e.setCursor(St(o,0,-1))}},incrementNumberToken:function(e,t){var n=e.getCursor(),r=e.getLine(n.line),i=/(-?)(?:(0x)([\da-f]+)|(0b|0|)(\d+))/gi,s,o,u,a;while((s=i.exec(r))!==null){o=s.index,u=o+s[0].length;if(n.ch=1)return!0}else e.nextCh===e.reverseSymb&&e.depth--;return!1}},section:{init:function(e){e.curMoveThrough=!0,e.symb=(e.forward?"]":"[")===e.symb?"{":"}"},isComplete:function(e){return e.index===0&&e.nextCh===e.symb}},comment:{isComplete:function(e){var t=e.lastCh==="*"&&e.nextCh==="/";return e.lastCh=e.nextCh,t}},method:{init:function(e){e.symb=e.symb==="m"?"{":"}",e.reverseSymb=e.symb==="{"?"}":"{"},isComplete:function(e){return e.nextCh===e.symb?!0:!1}},preprocess:{init:function(e){e.index=0},isComplete:function(e){if(e.nextCh==="#"){var t=e.lineText.match(/#(\w+)/)[1];if(t==="endif"){if(e.forward&&e.depth===0)return!0;e.depth++}else if(t==="if"){if(!e.forward&&e.depth===0)return!0;e.depth--}if(t==="else"&&e.depth===0)return!0}return!1}}};K("pcre",!0,"boolean"),pn.prototype={getQuery:function(){return nt.query},setQuery:function(e){nt.query=e},getOverlay:function(){return this.searchOverlay},setOverlay:function(e){this.searchOverlay=e},isReversed:function(){return nt.isReversed},setReversed:function(e){nt.isReversed=e},getScrollbarAnnotate:function(){return this.annotate},setScrollbarAnnotate:function(e){this.annotate=e}};var En={"\\n":"\n","\\r":"\r","\\t":" "},xn={"\\/":"/","\\\\":"\\","\\n":"\n","\\r":"\r","\\t":" "},Ln="(Javascript regexp)",In=function(){this.buildCommandMap_()};In.prototype={processCommand:function(e,t,n){var r=this;e.operation(function(){e.curOp.isVimOp=!0,r._processCommand(e,t,n)})},_processCommand:function(e,t,n){var r=e.state.vim,i=nt.registerController.getRegister(":"),s=i.toString();r.visualMode&&$t(e);var o=new v.StringStream(t);i.setText(t);var u=n||{};u.input=t;try{this.parseInput_(e,o,u)}catch(a){throw Cn(e,a),a}var f,l;if(!u.commandName)u.line!==undefined&&(l="move");else{f=this.matchCommand_(u.commandName);if(f){l=f.name,f.excludeFromCommandHistory&&i.setText(s),this.parseCommandArgs_(o,u,f);if(f.type=="exToKey"){for(var c=0;c0;t--){var n=e.substring(0,t);if(this.commandMap_[n]){var r=this.commandMap_[n];if(r.name.indexOf(e)===0)return r}}return null},buildCommandMap_:function(){this.commandMap_={};for(var e=0;e
";if(!n)for(var s in r){var o=r[s].toString();o.length&&(i+='"'+s+" "+o+"
")}else{var s;n=n.join("");for(var u=0;u"}}Cn(e,i)},sort:function(e,t){function u(){if(t.argString){var e=new v.StringStream(t.argString);e.eat("!")&&(n=!0);if(e.eol())return;if(!e.eatSpace())return"Invalid arguments";var u=e.match(/([dinuox]+)?\s*(\/.+\/)?\s*/);if(!u&&!e.eol())return"Invalid arguments";if(u[1]){r=u[1].indexOf("i")!=-1,i=u[1].indexOf("u")!=-1;var a=u[1].indexOf("d")!=-1||u[1].indexOf("n")!=-1&&1,f=u[1].indexOf("x")!=-1&&1,l=u[1].indexOf("o")!=-1&&1;if(a+f+l>1)return"Invalid arguments";s=a&&"decimal"||f&&"hex"||l&&"octal"}u[2]&&(o=new RegExp(u[2].substr(1,u[2].length-2),r?"i":""))}}function S(e,t){if(n){var i;i=e,e=t,t=i}r&&(e=e.toLowerCase(),t=t.toLowerCase());var o=s&&d.exec(e),u=s&&d.exec(t);return o?(o=parseInt((o[1]+o[2]).toLowerCase(),m),u=parseInt((u[1]+u[2]).toLowerCase(),m),o-u):e")}if(!u){Cn(e,c);return}var d=0,v=function(){if(d=f){Cn(e,"Invalid argument: "+t.argString.substring(i));return}for(var l=0;l<=f-a;l++){var c=String.fromCharCode(a+l);delete n.marks[c]}}else delete n.marks[s]}}},Rn=new In;v.keyMap.vim={attach:C,detach:N,call:k},K("insertModeEscKeysTimeout",200,"number"),v.keyMap["vim-insert"]={"Ctrl-N":"autocomplete","Ctrl-P":"autocomplete",Enter:function(e){var t=v.commands.newlineAndIndentContinueComment||v.commands.newlineAndIndent;t(e)},fallthrough:["default"],attach:C,detach:N,call:k},v.keyMap["vim-replace"]={Backspace:"goCharLeft",fallthrough:["vim-insert"],attach:C,detach:N,call:k},rt(),v.Vim=S(),S=v.Vim;var ir={"return":"CR",backspace:"BS","delete":"Del",esc:"Esc",left:"Left",right:"Right",up:"Up",down:"Down",space:"Space",home:"Home",end:"End",pageup:"PageUp",pagedown:"PageDown",enter:"CR"},or=S.handleKey.bind(S);S.handleKey=function(e,t,n){return e.operation(function(){return or(e,t,n)},!0)},t.CodeMirror=v;var fr=S.maybeInitVimState_;t.handler={$id:"ace/keyboard/vim",drawCursor:function(e,t,n,r,s){var u=this.state.vim||{},a=n.characterWidth,f=n.lineHeight,l=t.top,c=t.left;if(!u.insertMode){var h=r.cursor?i.comparePoints(r.cursor,r.start)<=0:s.selection.isBackwards()||s.selection.isEmpty();!h&&c>a&&(c-=a)}!u.insertMode&&u.status&&(f/=2,l+=f),o.translate(e,c,l),o.setStyle(e.style,"width",a+"px"),o.setStyle(e.style,"height",f+"px")},handleKeyboard:function(e,t,n,r,i){var s=e.editor,o=s.state.cm,u=fr(o);if(r==-1)return;u.insertMode||(t==-1?(n.charCodeAt(0)>255&&e.inputKey&&(n=e.inputKey,n&&e.inputHash==4&&(n=n.toUpperCase())),e.inputChar=n):t==4||t==0?e.inputKey==n&&e.inputHash==t&&e.inputChar?(n=e.inputChar,t=-1):(e.inputChar=null,e.inputKey=n,e.inputHash=t):e.inputChar=e.inputKey=null);if(n=="c"&&t==1&&!c.isMac&&s.getCopyText())return s.once("copy",function(){s.selection.clearSelection()}),{command:"null",passEvent:!0};if(n=="esc"&&!u.insertMode&&!u.visualMode&&!o.ace.inMultiSelectMode){var a=dn(o),f=a.getOverlay();f&&o.removeOverlay(f)}if(t==-1||t&1||t===0&&n.length>1){var l=u.insertMode,h=sr(t,n,i||{});u.status==null&&(u.status="");var p=ar(o,h,"user");u=fr(o),p&&u.status!=null?u.status+=h:u.status==null&&(u.status=""),o._signal("changeStatus");if(!p&&(t!=-1||l))return;return{command:"null",passEvent:!p}}},attach:function(e){function n(){var n=fr(t).insertMode;t.ace.renderer.setStyle("normal-mode",!n),e.textInput.setCommandMode(!n),e.renderer.$keepTextAreaAtCursor=n,e.renderer.$blockCursor=!n}e.state||(e.state={});var t=new v(e);e.state.cm=t,e.$vimModeHandler=this,v.keyMap.vim.attach(t),fr(t).status=null,t.on("vim-command-done",function(){if(t.virtualSelectionMode())return;fr(t).status=null,t.ace._signal("changeStatus"),t.ace.session.markUndoGroup()}),t.on("changeStatus",function(){t.ace.renderer.updateCursor(),t.ace._signal("changeStatus")}),t.on("vim-mode-change",function(){if(t.virtualSelectionMode())return;n(),t._signal("changeStatus")}),n(),e.renderer.$cursorLayer.drawCursor=this.drawCursor.bind(t)},detach:function(e){var t=e.state.cm;v.keyMap.vim.detach(t),t.destroy(),e.state.cm=null,e.$vimModeHandler=null,e.renderer.$cursorLayer.drawCursor=null,e.renderer.setStyle("normal-mode",!1),e.textInput.setCommandMode(!1),e.renderer.$keepTextAreaAtCursor=!0},getStatusText:function(e){var t=e.state.cm,n=fr(t);if(n.insertMode)return"INSERT";var r="";return n.visualMode&&(r+="VISUAL",n.visualLine&&(r+=" LINE"),n.visualBlock&&(r+=" BLOCK")),n.status&&(r+=(r?" ":"")+n.status),r}},S.defineOption({name:"wrap",set:function(e,t){t&&t.ace.setOption("wrap",e)},type:"boolean"},!1),S.defineEx("write","w",function(){console.log(":write is not implemented")}),b.push({keys:"zc",type:"action",action:"fold",actionArgs:{open:!1}},{keys:"zC",type:"action",action:"fold",actionArgs:{open:!1,all:!0}},{keys:"zo",type:"action",action:"fold",actionArgs:{open:!0}},{keys:"zO",type:"action",action:"fold",actionArgs:{open:!0,all:!0}},{keys:"za",type:"action",action:"fold",actionArgs:{toggle:!0}},{keys:"zA",type:"action",action:"fold",actionArgs:{toggle:!0,all:!0}},{keys:"zf",type:"action",action:"fold",actionArgs:{open:!0,all:!0}},{keys:"zd",type:"action",action:"fold",actionArgs:{open:!0,all:!0}},{keys:"",type:"action",action:"aceCommand",actionArgs:{name:"addCursorAbove"}},{keys:"",type:"action",action:"aceCommand",actionArgs:{name:"addCursorBelow"}},{keys:"",type:"action",action:"aceCommand",actionArgs:{name:"addCursorAboveSkipCurrent"}},{keys:"",type:"action",action:"aceCommand",actionArgs:{name:"addCursorBelowSkipCurrent"}},{keys:"",type:"action",action:"aceCommand",actionArgs:{name:"selectMoreBefore"}},{keys:"",type:"action",action:"aceCommand",actionArgs:{name:"selectMoreAfter"}},{keys:"",type:"action",action:"aceCommand",actionArgs:{name:"selectNextBefore"}},{keys:"",type:"action",action:"aceCommand",actionArgs:{name:"selectNextAfter"}}),yt.aceCommand=function(e,t,n){e.vimCmd=t,e.ace.inVirtualSelectionMode?e.ace.on("beforeEndOperation",lr):lr(null,e.ace)},yt.fold=function(e,t,n){e.ace.execCommand(["toggleFoldWidget","toggleFoldWidget","foldOther","unfoldall"][(t.all?2:0)+(t.open?1:0)])},t.handler.defaultKeymap=b,t.handler.actions=yt,t.Vim=S,S.map("Y","yy","normal")}); - (function() { - window.require(["ace/keyboard/vim"], function(m) { - if (typeof module == "object" && typeof exports == "object" && module) { - module.exports = m; +define("ace/keyboard/vim", [ + "require", + "exports", + "module", + "ace/range", + "ace/lib/event_emitter", + "ace/lib/dom", + "ace/lib/oop", + "ace/lib/keys", + "ace/lib/event", + "ace/search", + "ace/lib/useragent", + "ace/search_highlight", + "ace/commands/multi_select_commands", + "ace/mode/text", + "ace/multi_select", +], function (e, t, n) { + "use strict"; + function r() { + function t(e) { + return typeof e != "object" + ? e + "" + : "line" in e + ? e.line + ":" + e.ch + : "anchor" in e + ? t(e.anchor) + "->" + t(e.head) + : Array.isArray(e) + ? "[" + + e.map(function (e) { + return t(e); + }) + + "]" + : JSON.stringify(e); + } + var e = ""; + for (var n = 0; n < arguments.length; n++) { + var r = arguments[n], + i = t(r); + e += i + " "; + } + console.log(e); + } + function m(e) { + return { row: e.line, column: e.ch }; + } + function g(e) { + return new E(e.row, e.column); + } + function x(e) { + e.setOption("disableInput", !0), + e.setOption("showCursorWhenSelecting", !1), + v.signal(e, "vim-mode-change", { mode: "normal" }), + e.on("cursorActivity", Gn), + tt(e), + v.on(e.getInputField(), "paste", M(e)); + } + function T(e) { + e.setOption("disableInput", !1), + e.off("cursorActivity", Gn), + v.off(e.getInputField(), "paste", M(e)), + (e.state.vim = null); + } + function N(e, t) { + this == v.keyMap.vim && v.rmClass(e.getWrapperElement(), "cm-fat-cursor"), + (!t || t.attach != C) && T(e); + } + function C(e, t) { + this == v.keyMap.vim && v.addClass(e.getWrapperElement(), "cm-fat-cursor"), + (!t || t.attach != C) && x(e); + } + function k(e, t) { + if (!t) return undefined; + if (this[e]) return this[e]; + var n = O(e); + if (!n) return !1; + var r = v.Vim.findKey(t, n); + return typeof r == "function" && v.signal(t, "vim-keypress", n), r; + } + function O(e) { + if (e.charAt(0) == "'") return e.charAt(1); + var t = e.split(/-(?!$)/), + n = t[t.length - 1]; + if (t.length == 1 && t[0].length == 1) return !1; + if (t.length == 2 && t[0] == "Shift" && n.length == 1) return !1; + var r = !1; + for (var i = 0; i < t.length; i++) { + var s = t[i]; + s in L ? (t[i] = L[s]) : (r = !0), s in A && (t[i] = A[s]); + } + return r ? (X(n) && (t[t.length - 1] = n.toLowerCase()), "<" + t.join("-") + ">") : !1; + } + function M(e) { + var t = e.state.vim; + return ( + t.onPasteFn || + (t.onPasteFn = function () { + t.insertMode || + (e.setCursor(St(e.getCursor(), 0, 1)), yt.enterInsertMode(e, {}, t)); + }), + t.onPasteFn + ); + } + function H(e, t) { + var n = []; + for (var r = e; r < e + t; r++) n.push(String.fromCharCode(r)); + return n; + } + function R(e, t) { + return t >= e.firstLine() && t <= e.lastLine(); + } + function U(e) { + return /^[a-z]$/.test(e); + } + function z(e) { + return "()[]{}".indexOf(e) != -1; + } + function W(e) { + return _.test(e); + } + function X(e) { + return /^[A-Z]$/.test(e); + } + function V(e) { + return /^\s*$/.test(e); + } + function $(e, t) { + for (var n = 0; n < t.length; n++) if (t[n] == e) return !0; + return !1; + } + function K(e, t, n, r, i) { + if (t === undefined && !i) + throw Error("defaultValue is required unless callback is provided"); + n || (n = "string"), (J[e] = { type: n, defaultValue: t, callback: i }); + if (r) for (var s = 0; s < r.length; s++) J[r[s]] = J[e]; + t && Q(e, t); + } + function Q(e, t, n, r) { + var i = J[e]; + r = r || {}; + var s = r.scope; + if (!i) return new Error("Unknown option: " + e); + if (i.type == "boolean") { + if (t && t !== !0) return new Error("Invalid argument: " + e + "=" + t); + t !== !1 && (t = !0); + } + i.callback + ? (s !== "local" && i.callback(t, undefined), s !== "global" && n && i.callback(t, n)) + : (s !== "local" && (i.value = i.type == "boolean" ? !!t : t), + s !== "global" && n && (n.state.vim.options[e] = { value: t })); + } + function G(e, t, n) { + var r = J[e]; + n = n || {}; + var i = n.scope; + if (!r) return new Error("Unknown option: " + e); + if (r.callback) { + var s = t && r.callback(undefined, t); + if (i !== "global" && s !== undefined) return s; + if (i !== "local") return r.callback(); + return; + } + var s = i !== "global" && t && t.state.vim.options[e]; + return (s || (i !== "local" && r) || {}).value; + } + function et() { + (this.latestRegister = undefined), + (this.isPlaying = !1), + (this.isRecording = !1), + (this.replaySearchQueries = []), + (this.onRecordingDone = undefined), + (this.lastInsertModeChanges = Z()); + } + function tt(e) { + return ( + e.state.vim || + (e.state.vim = { + inputState: new ot(), + lastEditInputState: undefined, + lastEditActionCommand: undefined, + lastHPos: -1, + lastHSPos: -1, + lastMotion: null, + marks: {}, + fakeCursor: null, + insertMode: !1, + insertModeRepeat: undefined, + visualMode: !1, + visualLine: !1, + visualBlock: !1, + lastSelection: null, + lastPastedText: null, + sel: {}, + options: {}, + }), + e.state.vim + ); + } + function rt() { + nt = { + searchQuery: null, + searchIsReversed: !1, + lastSubstituteReplacePart: undefined, + jumpList: Y(), + macroModeState: new et(), + lastCharacterSearch: { increment: 0, forward: !0, selectedCharacter: "" }, + registerController: new lt({}), + searchHistoryController: new ct(), + exCommandHistoryController: new ct(), + }; + for (var e in J) { + var t = J[e]; + t.value = t.defaultValue; + } + } + function ot() { + (this.prefixRepeat = []), + (this.motionRepeat = []), + (this.operator = null), + (this.operatorArgs = null), + (this.motion = null), + (this.motionArgs = null), + (this.keyBuffer = []), + (this.registerName = null); + } + function ut(e, t) { + (e.state.vim.inputState = new ot()), v.signal(e, "vim-command-done", t); + } + function at(e, t, n) { + this.clear(), + (this.keyBuffer = [e || ""]), + (this.insertModeChanges = []), + (this.searchQueries = []), + (this.linewise = !!t), + (this.blockwise = !!n); + } + function ft(e, t) { + var n = nt.registerController.registers; + if (!e || e.length != 1) throw Error("Register name must be 1 character"); + (n[e] = t), q.push(e); + } + function lt(e) { + (this.registers = e), + (this.unnamedRegister = e['"'] = new at()), + (e["."] = new at()), + (e[":"] = new at()), + (e["/"] = new at()); + } + function ct() { + (this.historyBuffer = []), (this.iterator = 0), (this.initialPrefix = null); + } + function dt(e, t) { + pt[e] = t; + } + function vt(e, t) { + var n = []; + for (var r = 0; r < t; r++) n.push(e); + return n; + } + function gt(e, t) { + mt[e] = t; + } + function bt(e, t) { + yt[e] = t; + } + function wt(e, t, n) { + var r = Math.min(Math.max(e.firstLine(), t.line), e.lastLine()), + i = Pt(e, r) - 1; + i = n ? i + 1 : i; + var s = Math.min(Math.max(0, t.ch), i); + return E(r, s); + } + function Et(e) { + var t = {}; + for (var n in e) e.hasOwnProperty(n) && (t[n] = e[n]); + return t; + } + function St(e, t, n) { + return typeof t == "object" && ((n = t.ch), (t = t.line)), E(e.line + t, e.ch + n); + } + function xt(e, t) { + return { line: t.line - e.line, ch: t.line - e.line }; + } + function Tt(e, t, n, r) { + var i, + s = [], + o = []; + for (var u = 0; u < t.length; u++) { + var a = t[u]; + if ( + (n == "insert" && a.context != "insert") || + (a.context && a.context != n) || + (r.operator && a.type == "action") || + !(i = Nt(e, a.keys)) + ) + continue; + i == "partial" && s.push(a), i == "full" && o.push(a); + } + return { partial: s.length && s, full: o.length && o }; + } + function Nt(e, t) { + if (t.slice(-11) == "") { + var n = t.length - 11, + r = e.slice(0, n), + i = t.slice(0, n); + return r == i && e.length > n ? "full" : i.indexOf(r) == 0 ? "partial" : !1; + } + return e == t ? "full" : t.indexOf(e) == 0 ? "partial" : !1; + } + function Ct(e) { + var t = /^.*(<[^>]+>)$/.exec(e), + n = t ? t[1] : e.slice(-1); + if (n.length > 1) + switch (n) { + case "": + n = "\n"; + break; + case "": + n = " "; + break; + default: + n = ""; + } + return n; + } + function kt(e, t, n) { + return function () { + for (var r = 0; r < n; r++) t(e); + }; + } + function Lt(e) { + return E(e.line, e.ch); + } + function At(e, t) { + return e.ch == t.ch && e.line == t.line; + } + function Ot(e, t) { + return e.line < t.line ? !0 : e.line == t.line && e.ch < t.ch ? !0 : !1; + } + function Mt(e, t) { + return ( + arguments.length > 2 && + (t = Mt.apply(undefined, Array.prototype.slice.call(arguments, 1))), + Ot(e, t) ? e : t + ); + } + function _t(e, t) { + return ( + arguments.length > 2 && + (t = _t.apply(undefined, Array.prototype.slice.call(arguments, 1))), + Ot(e, t) ? t : e + ); + } + function Dt(e, t, n) { + var r = Ot(e, t), + i = Ot(t, n); + return r && i; + } + function Pt(e, t) { + return e.getLine(t).length; + } + function Ht(e) { + return e.trim ? e.trim() : e.replace(/^\s+|\s+$/g, ""); + } + function Bt(e) { + return e.replace(/([.?*+$\[\]\/\\(){}|\-])/g, "\\$1"); + } + function jt(e, t, n) { + var r = Pt(e, t), + i = new Array(n - r + 1).join(" "); + e.setCursor(E(t, r)), e.replaceRange(i, e.getCursor()); + } + function Ft(e, t) { + var n = [], + r = e.listSelections(), + i = Lt(e.clipPos(t)), + s = !At(t, i), + o = e.getCursor("head"), + u = qt(r, o), + a = At(r[u].head, r[u].anchor), + f = r.length - 1, + l = f - u > u ? f : 0, + c = r[l].anchor, + h = Math.min(c.line, i.line), + p = Math.max(c.line, i.line), + d = c.ch, + v = i.ch, + m = r[l].head.ch - d, + g = v - d; + m > 0 && g <= 0 + ? (d++, s || v--) + : m < 0 && g >= 0 + ? (d--, a || v++) + : m < 0 && g == -1 && (d--, v++); + for (var y = h; y <= p; y++) { + var b = { anchor: new E(y, d), head: new E(y, v) }; + n.push(b); + } + return e.setSelections(n), (t.ch = v), (c.ch = d), c; + } + function It(e, t, n) { + var r = []; + for (var i = 0; i < n; i++) { + var s = St(t, i, 0); + r.push({ anchor: s, head: s }); + } + e.setSelections(r, 0); + } + function qt(e, t, n) { + for (var r = 0; r < e.length; r++) { + var i = n != "head" && At(e[r].anchor, t), + s = n != "anchor" && At(e[r].head, t); + if (i || s) return r; + } + return -1; + } + function Rt(e, t) { + var n = t.lastSelection, + r = function () { + var t = e.listSelections(), + n = t[0], + r = t[t.length - 1], + i = Ot(n.anchor, n.head) ? n.anchor : n.head, + s = Ot(r.anchor, r.head) ? r.head : r.anchor; + return [i, s]; + }, + i = function () { + var t = e.getCursor(), + r = e.getCursor(), + i = n.visualBlock; + if (i) { + var s = i.width, + o = i.height; + r = E(t.line + o, t.ch + s); + var u = []; + for (var a = t.line; a < r.line; a++) { + var f = E(a, t.ch), + l = E(a, r.ch), + c = { anchor: f, head: l }; + u.push(c); + } + e.setSelections(u); + } else { + var h = n.anchorMark.find(), + p = n.headMark.find(), + d = p.line - h.line, + v = p.ch - h.ch; + (r = { line: r.line + d, ch: d ? r.ch : v + r.ch }), + n.visualLine && ((t = E(t.line, 0)), (r = E(r.line, Pt(e, r.line)))), + e.setSelection(t, r); + } + return [t, r]; + }; + return t.visualMode ? r() : i(); + } + function Ut(e, t) { + var n = t.sel.anchor, + r = t.sel.head; + t.lastPastedText && + ((r = e.posFromIndex(e.indexFromPos(n) + t.lastPastedText.length)), + (t.lastPastedText = null)), + (t.lastSelection = { + anchorMark: e.setBookmark(n), + headMark: e.setBookmark(r), + anchor: Lt(n), + head: Lt(r), + visualMode: t.visualMode, + visualLine: t.visualLine, + visualBlock: t.visualBlock, + }); + } + function zt(e, t, n) { + var r = e.state.vim.sel, + i = r.head, + s = r.anchor, + o; + return ( + Ot(n, t) && ((o = n), (n = t), (t = o)), + Ot(i, s) + ? ((i = Mt(t, i)), (s = _t(s, n))) + : ((s = Mt(t, s)), + (i = _t(i, n)), + (i = St(i, 0, -1)), + i.ch == -1 && i.line != e.firstLine() && (i = E(i.line - 1, Pt(e, i.line - 1)))), + [s, i] + ); + } + function Wt(e, t, n) { + var r = e.state.vim; + t = t || r.sel; + var n = n || r.visualLine ? "line" : r.visualBlock ? "block" : "char", + i = Xt(e, t, n); + e.setSelections(i.ranges, i.primary), Yn(e); + } + function Xt(e, t, n, r) { + var i = Lt(t.head), + s = Lt(t.anchor); + if (n == "char") { + var o = !r && !Ot(t.head, t.anchor) ? 1 : 0, + u = Ot(t.head, t.anchor) ? 1 : 0; + return ( + (i = St(t.head, 0, o)), + (s = St(t.anchor, 0, u)), + { ranges: [{ anchor: s, head: i }], primary: 0 } + ); + } + if (n == "line") { + if (!Ot(t.head, t.anchor)) { + s.ch = 0; + var a = e.lastLine(); + i.line > a && (i.line = a), (i.ch = Pt(e, i.line)); + } else (i.ch = 0), (s.ch = Pt(e, s.line)); + return { ranges: [{ anchor: s, head: i }], primary: 0 }; + } + if (n == "block") { + var f = Math.min(s.line, i.line), + l = Math.min(s.ch, i.ch), + c = Math.max(s.line, i.line), + h = Math.max(s.ch, i.ch) + 1, + p = c - f + 1, + d = i.line == f ? 0 : p - 1, + v = []; + for (var m = 0; m < p; m++) v.push({ anchor: E(f + m, l), head: E(f + m, h) }); + return { ranges: v, primary: d }; + } + } + function Vt(e) { + var t = e.getCursor("head"); + return e.getSelection().length == 1 && (t = Mt(t, e.getCursor("anchor"))), t; + } + function $t(e, t) { + var n = e.state.vim; + t !== !1 && e.setCursor(wt(e, n.sel.head)), + Ut(e, n), + (n.visualMode = !1), + (n.visualLine = !1), + (n.visualBlock = !1), + v.signal(e, "vim-mode-change", { mode: "normal" }), + n.fakeCursor && n.fakeCursor.clear(); + } + function Jt(e, t, n) { + var r = e.getRange(t, n); + if (/\n\s*$/.test(r)) { + var i = r.split("\n"); + i.pop(); + var s; + for (var s = i.pop(); i.length > 0 && s && V(s); s = i.pop()) n.line--, (n.ch = 0); + s ? (n.line--, (n.ch = Pt(e, n.line))) : (n.ch = 0); + } + } + function Kt(e, t, n) { + (t.ch = 0), (n.ch = 0), n.line++; + } + function Qt(e) { + if (!e) return 0; + var t = e.search(/\S/); + return t == -1 ? e.length : t; + } + function Gt(e, t, n, r, i) { + var s = Vt(e), + o = e.getLine(s.line), + u = s.ch, + a = i ? D[0] : P[0]; + while (!a(o.charAt(u))) { + u++; + if (u >= o.length) return null; + } + r ? (a = P[0]) : ((a = D[0]), a(o.charAt(u)) || (a = D[1])); + var f = u, + l = u; + while (a(o.charAt(f)) && f < o.length) f++; + while (a(o.charAt(l)) && l >= 0) l--; + l++; + if (t) { + var c = f; + while (/\s/.test(o.charAt(f)) && f < o.length) f++; + if (c == f) { + var h = l; + while (/\s/.test(o.charAt(l - 1)) && l > 0) l--; + l || (l = h); + } + } + return { start: E(s.line, l), end: E(s.line, f) }; + } + function Yt(e, t, n) { + At(t, n) || nt.jumpList.add(e, t, n); + } + function Zt(e, t) { + (nt.lastCharacterSearch.increment = e), + (nt.lastCharacterSearch.forward = t.forward), + (nt.lastCharacterSearch.selectedCharacter = t.selectedCharacter); + } + function nn(e, t, n, r) { + var i = Lt(e.getCursor()), + s = n ? 1 : -1, + o = n ? e.lineCount() : -1, + u = i.ch, + a = i.line, + f = e.getLine(a), + l = { + lineText: f, + nextCh: f.charAt(u), + lastCh: null, + index: u, + symb: r, + reverseSymb: (n ? { ")": "(", "}": "{" } : { "(": ")", "{": "}" })[r], + forward: n, + depth: 0, + curMoveThrough: !1, + }, + c = en[r]; + if (!c) return i; + var h = tn[c].init, + p = tn[c].isComplete; + h && h(l); + while (a !== o && t) { + (l.index += s), (l.nextCh = l.lineText.charAt(l.index)); + if (!l.nextCh) { + (a += s), (l.lineText = e.getLine(a) || ""); + if (s > 0) l.index = 0; + else { + var d = l.lineText.length; + l.index = d > 0 ? d - 1 : 0; + } + l.nextCh = l.lineText.charAt(l.index); + } + p(l) && ((i.line = a), (i.ch = l.index), t--); + } + return l.nextCh || l.curMoveThrough ? E(a, l.index) : i; + } + function rn(e, t, n, r, i) { + var s = t.line, + o = t.ch, + u = e.getLine(s), + a = n ? 1 : -1, + f = r ? P : D; + if (i && u == "") { + (s += a), (u = e.getLine(s)); + if (!R(e, s)) return null; + o = n ? 0 : u.length; + } + for (;;) { + if (i && u == "") return { from: 0, to: 0, line: s }; + var l = a > 0 ? u.length : -1, + c = l, + h = l; + while (o != l) { + var p = !1; + for (var d = 0; d < f.length && !p; ++d) + if (f[d](u.charAt(o))) { + c = o; + while (o != l && f[d](u.charAt(o))) o += a; + (h = o), (p = c != h); + if (c == t.ch && s == t.line && h == c + a) continue; + return { from: Math.min(c, h + 1), to: Math.max(c, h), line: s }; + } + p || (o += a); + } + s += a; + if (!R(e, s)) return null; + (u = e.getLine(s)), (o = a > 0 ? 0 : u.length); + } + } + function sn(e, t, n, r, i, s) { + var o = Lt(t), + u = []; + ((r && !i) || (!r && i)) && n++; + var a = !r || !i; + for (var f = 0; f < n; f++) { + var l = rn(e, t, r, s, a); + if (!l) { + var c = Pt(e, e.lastLine()); + u.push(r ? { line: e.lastLine(), from: c, to: c } : { line: 0, from: 0, to: 0 }); + break; + } + u.push(l), (t = E(l.line, r ? l.to - 1 : l.from)); + } + var h = u.length != n, + p = u[0], + d = u.pop(); + return r && !i + ? (!h && (p.from != o.ch || p.line != o.line) && (d = u.pop()), E(d.line, d.from)) + : r && i + ? E(d.line, d.to - 1) + : !r && i + ? (!h && (p.to != o.ch || p.line != o.line) && (d = u.pop()), E(d.line, d.to)) + : E(d.line, d.from); + } + function on(e, t, n, r) { + var i = e.getCursor(), + s = i.ch, + o; + for (var u = 0; u < t; u++) { + var a = e.getLine(i.line); + o = fn(s, a, r, n, !0); + if (o == -1) return null; + s = o; + } + return E(e.getCursor().line, o); + } + function un(e, t) { + var n = e.getCursor().line; + return wt(e, E(n, t - 1)); + } + function an(e, t, n, r) { + if (!$(n, I)) return; + t.marks[n] && t.marks[n].clear(), (t.marks[n] = e.setBookmark(r)); + } + function fn(e, t, n, r, i) { + var s; + return ( + r + ? ((s = t.indexOf(n, e + 1)), s != -1 && !i && (s -= 1)) + : ((s = t.lastIndexOf(n, e - 1)), s != -1 && !i && (s += 1)), + s + ); + } + function ln(e, t, n, r, i) { + function c(t) { + return !/\S/.test(e.getLine(t)); + } + function h(e, t, n) { + return n ? c(e) != c(e + t) : !c(e) && c(e + t); + } + function p(t) { + r = r > 0 ? 1 : -1; + var n = e.ace.session.getFoldLine(t); + n && + t + r > n.start.row && + t + r < n.end.row && + (r = (r > 0 ? n.end.row : n.start.row) - t); + } + var s = t.line, + o = e.firstLine(), + u = e.lastLine(), + a, + f, + l = s; + if (r) { + while (o <= l && l <= u && n > 0) p(l), h(l, r) && n--, (l += r); + return new E(l, 0); + } + var d = e.state.vim; + if (d.visualLine && h(s, 1, !0)) { + var v = d.sel.anchor; + h(v.line, -1, !0) && (!i || v.line != s) && (s += 1); + } + var m = c(s); + for (l = s; l <= u && n; l++) h(l, 1, !0) && (!i || c(l) != m) && n--; + (f = new E(l, 0)), l > u && !m ? (m = !0) : (i = !1); + for (l = s; l > o; l--) if (!i || c(l) == m || l == s) if (h(l, -1, !0)) break; + return (a = new E(l, 0)), { start: a, end: f }; + } + function cn(e, t, n, r) { + var i = t, + s, + o, + u = { "(": /[()]/, ")": /[()]/, "[": /[[\]]/, "]": /[[\]]/, "{": /[{}]/, "}": /[{}]/ }[ + n + ], + a = { "(": "(", ")": "(", "[": "[", "]": "[", "{": "{", "}": "{" }[n], + f = e.getLine(i.line).charAt(i.ch), + l = f === a ? 1 : 0; + (s = e.scanForBracket(E(i.line, i.ch + l), -1, null, { bracketRegex: u })), + (o = e.scanForBracket(E(i.line, i.ch + l), 1, null, { bracketRegex: u })); + if (!s || !o) return { start: i, end: i }; + (s = s.pos), (o = o.pos); + if ((s.line == o.line && s.ch > o.ch) || s.line > o.line) { + var c = s; + (s = o), (o = c); + } + return r ? (o.ch += 1) : (s.ch += 1), { start: s, end: o }; + } + function hn(e, t, n, r) { + var i = Lt(t), + s = e.getLine(i.line), + o = s.split(""), + u, + a, + f, + l, + c = o.indexOf(n); + i.ch < c ? (i.ch = c) : c < i.ch && o[i.ch] == n && ((a = i.ch), --i.ch); + if (o[i.ch] == n && !a) u = i.ch + 1; + else for (f = i.ch; f > -1 && !u; f--) o[f] == n && (u = f + 1); + if (u && !a) for (f = u, l = o.length; f < l && !a; f++) o[f] == n && (a = f); + return !u || !a + ? { start: i, end: i } + : (r && (--u, ++a), { start: E(i.line, u), end: E(i.line, a) }); + } + function pn() {} + function dn(e) { + var t = e.state.vim; + return t.searchState_ || (t.searchState_ = new pn()); + } + function vn(e, t, n, r, i) { + e.openDialog + ? e.openDialog(t, r, { + bottom: !0, + value: i.value, + onKeyDown: i.onKeyDown, + onKeyUp: i.onKeyUp, + selectValueOnOpen: !1, + onClose: function () { + e.state.vim && + ((e.state.vim.status = ""), + e.ace.renderer.$loop.schedule(e.ace.renderer.CHANGE_CURSOR)); + }, + }) + : r(prompt(n, "")); + } + function mn(e) { + return yn(e, "/"); + } + function gn(e) { + return bn(e, "/"); + } + function yn(e, t) { + var n = bn(e, t) || []; + if (!n.length) return []; + var r = []; + if (n[0] !== 0) return; + for (var i = 0; i < n.length; i++) + typeof n[i] == "number" && r.push(e.substring(n[i] + 1, n[i + 1])); + return r; + } + function bn(e, t) { + t || (t = "/"); + var n = !1, + r = []; + for (var i = 0; i < e.length; i++) { + var s = e.charAt(i); + !n && s == t && r.push(i), (n = !n && s == "\\"); + } + return r; + } + function wn(e) { + var t = "|(){", + n = "}", + r = !1, + i = []; + for (var s = -1; s < e.length; s++) { + var o = e.charAt(s) || "", + u = e.charAt(s + 1) || "", + a = u && t.indexOf(u) != -1; + r + ? ((o !== "\\" || !a) && i.push(o), (r = !1)) + : o === "\\" + ? ((r = !0), u && n.indexOf(u) != -1 && (a = !0), (!a || u === "\\") && i.push(o)) + : (i.push(o), a && u !== "\\" && i.push("\\")); + } + return i.join(""); + } + function Sn(e) { + var t = !1, + n = []; + for (var r = -1; r < e.length; r++) { + var i = e.charAt(r) || "", + s = e.charAt(r + 1) || ""; + En[i + s] + ? (n.push(En[i + s]), r++) + : t + ? (n.push(i), (t = !1)) + : i === "\\" + ? ((t = !0), + W(s) || s === "$" ? n.push("$") : s !== "/" && s !== "\\" && n.push("\\")) + : (i === "$" && n.push("$"), n.push(i), s === "/" && n.push("\\")); + } + return n.join(""); + } + function Tn(e) { + var t = new v.StringStream(e), + n = []; + while (!t.eol()) { + while (t.peek() && t.peek() != "\\") n.push(t.next()); + var r = !1; + for (var i in xn) + if (t.match(i, !0)) { + (r = !0), n.push(xn[i]); + break; + } + r || n.push(t.next()); + } + return n.join(""); + } + function Nn(e, t, n) { + var r = nt.registerController.getRegister("/"); + r.setText(e); + if (e instanceof RegExp) return e; + var i = gn(e), + s, + o; + if (!i.length) s = e; + else { + s = e.substring(0, i[0]); + var u = e.substring(i[0]); + o = u.indexOf("i") != -1; + } + if (!s) return null; + G("pcre") || (s = wn(s)), n && (t = /^[^A-Z]*$/.test(s)); + var a = new RegExp(s, t || o ? "i" : undefined); + return a; + } + function Cn(e, t) { + e.openNotification + ? e.openNotification('' + t + "", { + bottom: !0, + duration: 5e3, + }) + : alert(t); + } + function kn(e, t) { + var n = + '' + + (e || "") + + ''; + return t && (n += ' ' + t + ""), n; + } + function An(e, t) { + var n = (t.prefix || "") + " " + (t.desc || ""), + r = kn(t.prefix, t.desc); + vn(e, r, n, t.onClose, t); + } + function On(e, t) { + if (e instanceof RegExp && t instanceof RegExp) { + var n = ["global", "multiline", "ignoreCase", "source"]; + for (var r = 0; r < n.length; r++) { + var i = n[r]; + if (e[i] !== t[i]) return !1; + } + return !0; + } + return !1; + } + function Mn(e, t, n, r) { + if (!t) return; + var i = dn(e), + s = Nn(t, !!n, !!r); + if (!s) return; + return Dn(e, s), On(s, i.getQuery()) ? s : (i.setQuery(s), s); + } + function _n(e) { + if (e.source.charAt(0) == "^") var t = !0; + return { + token: function (n) { + if (t && !n.sol()) { + n.skipToEnd(); + return; + } + var r = n.match(e, !1); + if (r) { + if (r[0].length == 0) return n.next(), "searching"; + if (!n.sol()) { + n.backUp(1); + if (!e.exec(n.next() + r[0])) return n.next(), null; + } + return n.match(e), "searching"; + } + while (!n.eol()) { + n.next(); + if (n.match(e, !1)) break; + } + }, + query: e, + }; + } + function Dn(e, t) { + var n = dn(e), + r = n.getOverlay(); + if (!r || t != r.query) + r && e.removeOverlay(r), + (r = _n(t)), + e.addOverlay(r), + e.showMatchesOnScrollbar && + (n.getScrollbarAnnotate() && n.getScrollbarAnnotate().clear(), + n.setScrollbarAnnotate(e.showMatchesOnScrollbar(t))), + n.setOverlay(r); + } + function Pn(e, t, n, r) { + return ( + r === undefined && (r = 1), + e.operation(function () { + var i = e.getCursor(), + s = e.getSearchCursor(n, i); + for (var o = 0; o < r; o++) { + var u = s.find(t); + o == 0 && u && At(s.from(), i) && (u = s.find(t)); + if (!u) { + s = e.getSearchCursor(n, t ? E(e.lastLine()) : E(e.firstLine(), 0)); + if (!s.find(t)) return; + } + } + return s.from(); + }) + ); + } + function Hn(e) { + var t = dn(e); + e.removeOverlay(dn(e).getOverlay()), + t.setOverlay(null), + t.getScrollbarAnnotate() && + (t.getScrollbarAnnotate().clear(), t.setScrollbarAnnotate(null)); + } + function Bn(e, t, n) { + return ( + typeof e != "number" && (e = e.line), + t instanceof Array ? $(e, t) : n ? e >= t && e <= n : e == t + ); + } + function jn(e) { + var t = e.ace.renderer; + return { top: t.getFirstFullyVisibleRow(), bottom: t.getLastFullyVisibleRow() }; + } + function Fn(e, t, n) { + var r = t.marks[n]; + return r && r.find(); + } + function Un(e, t, n, r, i, s, o, u, a) { + function c() { + e.operation(function () { + while (!f) h(), p(); + d(); + }); + } + function h() { + var t = e.getRange(s.from(), s.to()), + n = t.replace(o, u); + s.replace(n); + } + function p() { + while (s.findNext() && Bn(s.from(), r, i)) { + if (!n && l && s.from().line == l.line) continue; + e.scrollIntoView(s.from(), 30), + e.setSelection(s.from(), s.to()), + (l = s.from()), + (f = !1); + return; + } + f = !0; + } + function d(t) { + t && t(), e.focus(); + if (l) { + e.setCursor(l); + var n = e.state.vim; + (n.exMode = !1), (n.lastHPos = n.lastHSPos = l.ch); + } + a && a(); + } + function m(t, n, r) { + v.e_stop(t); + var i = v.keyName(t); + switch (i) { + case "Y": + h(), p(); + break; + case "N": + p(); + break; + case "A": + var s = a; + (a = undefined), e.operation(c), (a = s); + break; + case "L": + h(); + case "Q": + case "Esc": + case "Ctrl-C": + case "Ctrl-[": + d(r); + } + return f && d(r), !0; + } + e.state.vim.exMode = !0; + var f = !1, + l = s.from(); + p(); + if (f) { + Cn(e, "No matches for " + o.source); + return; + } + if (!t) { + c(), a && a(); + return; + } + An(e, { prefix: "replace with " + u + " (y/n/a/q/l)", onKeyDown: m }); + } + function zn(e) { + var t = e.state.vim, + n = nt.macroModeState, + r = nt.registerController.getRegister("."), + i = n.isPlaying, + s = n.lastInsertModeChanges, + o = []; + if (!i) { + var u = s.inVisualBlock && t.lastSelection ? t.lastSelection.visualBlock.height : 1, + a = s.changes, + o = [], + f = 0; + while (f < a.length) o.push(a[f]), a[f] instanceof er ? f++ : (f += u); + (s.changes = o), e.off("change", Qn), v.off(e.getInputField(), "keydown", tr); + } + !i && + t.insertModeRepeat > 1 && + (nr(e, t, t.insertModeRepeat - 1, !0), + (t.lastEditInputState.repeatOverride = t.insertModeRepeat)), + delete t.insertModeRepeat, + (t.insertMode = !1), + e.setCursor(e.getCursor().line, e.getCursor().ch - 1), + e.setOption("keyMap", "vim"), + e.setOption("disableInput", !0), + e.toggleOverwrite(!1), + r.setText(s.changes.join("")), + v.signal(e, "vim-mode-change", { mode: "normal" }), + n.isRecording && Jn(n); + } + function Wn(e) { + b.unshift(e); + } + function Xn(e, t, n, r, i) { + var s = { keys: e, type: t }; + (s[t] = n), (s[t + "Args"] = r); + for (var o in i) s[o] = i[o]; + Wn(s); + } + function Vn(e, t, n, r) { + var i = nt.registerController.getRegister(r); + if (r == ":") { + i.keyBuffer[0] && Rn.processCommand(e, i.keyBuffer[0]), (n.isPlaying = !1); + return; + } + var s = i.keyBuffer, + o = 0; + (n.isPlaying = !0), (n.replaySearchQueries = i.searchQueries.slice(0)); + for (var u = 0; u < s.length; u++) { + var a = s[u], + f, + l; + while (a) { + (f = /<\w+-.+?>|<\w+>|./.exec(a)), + (l = f[0]), + (a = a.substring(f.index + l.length)), + v.Vim.handleKey(e, l, "macro"); + if (t.insertMode) { + var c = i.insertModeChanges[o++].changes; + (nt.macroModeState.lastInsertModeChanges.changes = c), rr(e, c, 1), zn(e); + } + } + } + n.isPlaying = !1; + } + function $n(e, t) { + if (e.isPlaying) return; + var n = e.latestRegister, + r = nt.registerController.getRegister(n); + r && r.pushText(t); + } + function Jn(e) { + if (e.isPlaying) return; + var t = e.latestRegister, + n = nt.registerController.getRegister(t); + n && n.pushInsertModeChanges && n.pushInsertModeChanges(e.lastInsertModeChanges); + } + function Kn(e, t) { + if (e.isPlaying) return; + var n = e.latestRegister, + r = nt.registerController.getRegister(n); + r && r.pushSearchQuery && r.pushSearchQuery(t); + } + function Qn(e, t) { + var n = nt.macroModeState, + r = n.lastInsertModeChanges; + if (!n.isPlaying) + while (t) { + r.expectCursorActivityForChange = !0; + if (t.origin == "+input" || t.origin == "paste" || t.origin === undefined) { + var i = t.text.join("\n"); + r.maybeReset && ((r.changes = []), (r.maybeReset = !1)), + e.state.overwrite && !/\n/.test(i) + ? r.changes.push([i]) + : r.changes.push(i); + } + t = t.next; + } + } + function Gn(e) { + var t = e.state.vim; + if (t.insertMode) { + var n = nt.macroModeState; + if (n.isPlaying) return; + var r = n.lastInsertModeChanges; + r.expectCursorActivityForChange + ? (r.expectCursorActivityForChange = !1) + : (r.maybeReset = !0); + } else e.curOp.isVimOp || Zn(e, t); + t.visualMode && Yn(e); + } + function Yn(e) { + var t = e.state.vim, + n = wt(e, Lt(t.sel.head)), + r = St(n, 0, 1); + t.fakeCursor && t.fakeCursor.clear(), + (t.fakeCursor = e.markText(n, r, { className: "cm-animate-fat-cursor" })); + } + function Zn(e, t) { + var n = e.getCursor("anchor"), + r = e.getCursor("head"); + t.visualMode && !e.somethingSelected() + ? $t(e, !1) + : !t.visualMode && + !t.insertMode && + e.somethingSelected() && + ((t.visualMode = !0), + (t.visualLine = !1), + v.signal(e, "vim-mode-change", { mode: "visual" })); + if (t.visualMode) { + var i = Ot(r, n) ? 0 : -1, + s = Ot(r, n) ? -1 : 0; + (r = St(r, 0, i)), + (n = St(n, 0, s)), + (t.sel = { anchor: n, head: r }), + an(e, t, "<", Mt(r, n)), + an(e, t, ">", _t(r, n)); + } else t.insertMode || (t.lastHPos = e.getCursor().ch); + } + function er(e) { + this.keyName = e; + } + function tr(e) { + function i() { + return ( + n.maybeReset && ((n.changes = []), (n.maybeReset = !1)), + n.changes.push(new er(r)), + !0 + ); + } + var t = nt.macroModeState, + n = t.lastInsertModeChanges, + r = v.keyName(e); + if (!r) return; + (r.indexOf("Delete") != -1 || r.indexOf("Backspace") != -1) && + v.lookupKey(r, "vim-insert", i); + } + function nr(e, t, n, r) { + function u() { + s ? ht.processAction(e, t, t.lastEditActionCommand) : ht.evalInput(e, t); + } + function a(n) { + if (i.lastInsertModeChanges.changes.length > 0) { + n = t.lastEditActionCommand ? n : 1; + var r = i.lastInsertModeChanges; + rr(e, r.changes, n); + } + } + var i = nt.macroModeState; + i.isPlaying = !0; + var s = !!t.lastEditActionCommand, + o = t.inputState; + t.inputState = t.lastEditInputState; + if (s && t.lastEditActionCommand.interlaceInsertRepeat) + for (var f = 0; f < n; f++) u(), a(1); + else r || u(), a(n); + (t.inputState = o), t.insertMode && !r && zn(e), (i.isPlaying = !1); + } + function rr(e, t, n) { + function r(t) { + return typeof t == "string" ? v.commands[t](e) : t(e), !0; + } + var i = e.getCursor("head"), + s = nt.macroModeState.lastInsertModeChanges.inVisualBlock; + if (s) { + var o = e.state.vim, + u = o.lastSelection, + a = xt(u.anchor, u.head); + It(e, i, a.line + 1), (n = e.listSelections().length), e.setCursor(i); + } + for (var f = 0; f < n; f++) { + s && e.setCursor(St(i, f, 0)); + for (var l = 0; l < t.length; l++) { + var c = t[l]; + if (c instanceof er) v.lookupKey(c.keyName, "vim-insert", r); + else if (typeof c == "string") { + var h = e.getCursor(); + e.replaceRange(c, h, h); + } else { + var p = e.getCursor(), + d = St(p, 0, c[0].length); + e.replaceRange(c[0], p, d); + } + } + } + s && e.setCursor(St(i, 0, 1)); + } + function sr(e, t, n) { + t.length > 1 && t[0] == "n" && (t = t.replace("numpad", "")), (t = ir[t] || t); + var r = ""; + return ( + n.ctrlKey && (r += "C-"), + n.altKey && (r += "A-"), + (r || t.length > 1) && n.shiftKey && (r += "S-"), + (r += t), + r.length > 1 && (r = "<" + r + ">"), + r + ); + } + function ur(e) { + var t = new e.constructor(); + return ( + Object.keys(e).forEach(function (n) { + var r = e[n]; + Array.isArray(r) + ? (r = r.slice()) + : r && typeof r == "object" && r.constructor != Object && (r = ur(r)), + (t[n] = r); + }), + e.sel && + (t.sel = { + head: e.sel.head && Lt(e.sel.head), + anchor: e.sel.anchor && Lt(e.sel.anchor), + }), + t + ); + } + function ar(e, t, n) { + var r = !1, + i = S.maybeInitVimState_(e), + s = i.visualBlock || i.wasInVisualBlock; + i.wasInVisualBlock && !e.ace.inMultiSelectMode + ? (i.wasInVisualBlock = !1) + : e.ace.inMultiSelectMode && i.visualBlock && (i.wasInVisualBlock = !0); + if (t == "" && !i.insertMode && !i.visualMode && e.ace.inMultiSelectMode) + e.ace.exitMultiSelectMode(); + else if (s || !e.ace.inMultiSelectMode || e.ace.inVirtualSelectionMode) + r = S.handleKey(e, t, n); + else { + var o = ur(i); + e.operation(function () { + e.ace.forEachSelection(function () { + var i = e.ace.selection; + e.state.vim.lastHPos = + i.$desiredColumn == null ? i.lead.column : i.$desiredColumn; + var s = e.getCursor("head"), + u = e.getCursor("anchor"), + a = Ot(s, u) ? 0 : -1, + f = Ot(s, u) ? -1 : 0; + (s = St(s, 0, a)), + (u = St(u, 0, f)), + (e.state.vim.sel.head = s), + (e.state.vim.sel.anchor = u), + (r = or(e, t, n)), + (i.$desiredColumn = + e.state.vim.lastHPos == -1 ? null : e.state.vim.lastHPos), + e.virtualSelectionMode() && (e.state.vim = ur(o)); + }), + e.curOp.cursorActivity && !r && (e.curOp.cursorActivity = !1); + }, !0); + } + return r && Zn(e, i), r; + } + function lr(e, t) { + t.off("beforeEndOperation", lr); + var n = t.state.cm.vimCmd; + n && t.execCommand(n.exec ? n : n.name, n.args), (t.curOp = t.prevOp); + } + var i = e("../range").Range, + s = e("../lib/event_emitter").EventEmitter, + o = e("../lib/dom"), + u = e("../lib/oop"), + a = e("../lib/keys"), + f = e("../lib/event"), + l = e("../search").Search, + c = e("../lib/useragent"), + h = e("../search_highlight").SearchHighlight, + p = e("../commands/multi_select_commands"), + d = e("../mode/text").Mode.prototype.tokenRe; + e("../multi_select"); + var v = function (e) { + (this.ace = e), + (this.state = {}), + (this.marks = {}), + (this.$uid = 0), + (this.onChange = this.onChange.bind(this)), + (this.onSelectionChange = this.onSelectionChange.bind(this)), + (this.onBeforeEndOperation = this.onBeforeEndOperation.bind(this)), + this.ace.on("change", this.onChange), + this.ace.on("changeSelection", this.onSelectionChange), + this.ace.on("beforeEndOperation", this.onBeforeEndOperation); + }; + (v.Pos = function (e, t) { + if (!(this instanceof E)) return new E(e, t); + (this.line = e), (this.ch = t); + }), + (v.defineOption = function (e, t, n) {}), + (v.commands = { + redo: function (e) { + e.ace.redo(); + }, + undo: function (e) { + e.ace.undo(); + }, + newlineAndIndent: function (e) { + e.ace.insert("\n"); + }, + }), + (v.keyMap = {}), + (v.addClass = v.rmClass = function () {}), + (v.e_stop = v.e_preventDefault = f.stopEvent), + (v.keyName = function (e) { + var t = a[e.keyCode] || e.key || ""; + return ( + t.length == 1 && (t = t.toUpperCase()), + (t = + f.getModifierString(e).replace(/(^|-)\w/g, function (e) { + return e.toUpperCase(); + }) + t), + t + ); + }), + (v.keyMap["default"] = function (e) { + return function (t) { + var n = t.ace.commands.commandKeyBinding[e.toLowerCase()]; + return n && t.ace.execCommand(n) !== !1; + }; + }), + (v.lookupKey = function cr(e, t, n) { + typeof t == "string" && (t = v.keyMap[t]); + var r = typeof t == "function" ? t(e) : t[e]; + if (r === !1) return "nothing"; + if (r === "...") return "multi"; + if (r != null && n(r)) return "handled"; + if (t.fallthrough) { + if (!Array.isArray(t.fallthrough)) return cr(e, t.fallthrough, n); + for (var i = 0; i < t.fallthrough.length; i++) { + var s = cr(e, t.fallthrough[i], n); + if (s) return s; + } + } + }), + (v.signal = function (e, t, n) { + return e._signal(t, n); + }), + (v.on = f.addListener), + (v.off = f.removeListener), + (v.isWordChar = function (e) { + return e < "" ? /^\w$/.test(e) : ((d.lastIndex = 0), d.test(e)); + }), + function () { + u.implement(v.prototype, s), + (this.destroy = function () { + this.ace.off("change", this.onChange), + this.ace.off("changeSelection", this.onSelectionChange), + this.ace.off("beforeEndOperation", this.onBeforeEndOperation), + this.removeOverlay(); + }), + (this.virtualSelectionMode = function () { + return this.ace.inVirtualSelectionMode && this.ace.selection.index; + }), + (this.onChange = function (e) { + var t = { text: e.action[0] == "i" ? e.lines : [] }, + n = (this.curOp = this.curOp || {}); + n.changeHandlers || + (n.changeHandlers = + this._eventRegistry.change && this._eventRegistry.change.slice()); + if (this.virtualSelectionMode()) return; + n.lastChange + ? (n.lastChange.next = n.lastChange = t) + : (n.lastChange = n.change = t), + this.$updateMarkers(e); + }), + (this.onSelectionChange = function () { + var e = (this.curOp = this.curOp || {}); + e.cursorActivityHandlers || + (e.cursorActivityHandlers = + this._eventRegistry.cursorActivity && + this._eventRegistry.cursorActivity.slice()), + (this.curOp.cursorActivity = !0), + this.ace.inMultiSelectMode && + this.ace.keyBinding.removeKeyboardHandler(p.keyboardHandler); + }), + (this.operation = function (e, t) { + if ((!t && this.curOp) || (t && this.curOp && this.curOp.force)) return e(); + (t || !this.ace.curOp) && this.curOp && this.onBeforeEndOperation(); + if (!this.ace.curOp) { + var n = this.ace.prevOp; + this.ace.startOperation({ + command: { name: "vim", scrollIntoView: "cursor" }, + }); + } + var r = (this.curOp = this.curOp || {}); + this.curOp.force = t; + var i = e(); + return ( + this.ace.curOp && + this.ace.curOp.command.name == "vim" && + (this.state.dialog && (this.ace.curOp.command.scrollIntoView = !1), + this.ace.endOperation(), + !r.cursorActivity && !r.lastChange && n && (this.ace.prevOp = n)), + (t || !this.ace.curOp) && this.curOp && this.onBeforeEndOperation(), + i + ); + }), + (this.onBeforeEndOperation = function () { + var e = this.curOp; + e && + (e.change && this.signal("change", e.change, e), + e && e.cursorActivity && this.signal("cursorActivity", null, e), + (this.curOp = null)); + }), + (this.signal = function (e, t, n) { + var r = n ? n[e + "Handlers"] : (this._eventRegistry || {})[e]; + if (!r) return; + r = r.slice(); + for (var i = 0; i < r.length; i++) r[i](this, t); + }), + (this.firstLine = function () { + return 0; + }), + (this.lastLine = function () { + return this.ace.session.getLength() - 1; + }), + (this.lineCount = function () { + return this.ace.session.getLength(); + }), + (this.setCursor = function (e, t) { + typeof e == "object" && ((t = e.ch), (e = e.line)), + this.ace.inVirtualSelectionMode || this.ace.exitMultiSelectMode(), + this.ace.session.unfold({ row: e, column: t }), + this.ace.selection.moveTo(e, t); + }), + (this.getCursor = function (e) { + var t = this.ace.selection, + n = + e == "anchor" + ? t.isEmpty() + ? t.lead + : t.anchor + : e == "head" || !e + ? t.lead + : t.getRange()[e]; + return g(n); + }), + (this.listSelections = function (e) { + var t = this.ace.multiSelect.rangeList.ranges; + return !t.length || this.ace.inVirtualSelectionMode + ? [{ anchor: this.getCursor("anchor"), head: this.getCursor("head") }] + : t.map(function (e) { + return { + anchor: this.clipPos(g(e.cursor == e.end ? e.start : e.end)), + head: this.clipPos(g(e.cursor)), + }; + }, this); + }), + (this.setSelections = function (e, t) { + var n = this.ace.multiSelect, + r = e.map(function (e) { + var t = m(e.anchor), + n = m(e.head), + r = + i.comparePoints(t, n) < 0 + ? new i.fromPoints(t, n) + : new i.fromPoints(n, t); + return (r.cursor = i.comparePoints(r.start, n) ? r.end : r.start), r; + }); + if (this.ace.inVirtualSelectionMode) { + this.ace.selection.fromOrientedRange(r[0]); + return; + } + t ? r[t] && r.push(r.splice(t, 1)[0]) : (r = r.reverse()), + n.toSingleRange(r[0].clone()); + var s = this.ace.session; + for (var o = 0; o < r.length; o++) { + var u = s.$clipRangeToDocument(r[o]); + n.addRange(u); + } + }), + (this.setSelection = function (e, t, n) { + var r = this.ace.selection; + r.moveTo(e.line, e.ch), + r.selectTo(t.line, t.ch), + n && n.origin == "*mouse" && this.onBeforeEndOperation(); + }), + (this.somethingSelected = function (e) { + return !this.ace.selection.isEmpty(); + }), + (this.clipPos = function (e) { + var t = this.ace.session.$clipPositionToDocument(e.line, e.ch); + return g(t); + }), + (this.markText = function (e) { + return { clear: function () {}, find: function () {} }; + }), + (this.$updateMarkers = function (e) { + var t = e.action == "insert", + n = e.start, + r = e.end, + s = (r.row - n.row) * (t ? 1 : -1), + o = (r.column - n.column) * (t ? 1 : -1); + t && (r = n); + for (var u in this.marks) { + var a = this.marks[u], + f = i.comparePoints(a, n); + if (f < 0) continue; + if (f === 0 && t) { + if (a.bias != 1) { + a.bias = -1; + continue; + } + f = 1; } + var l = t ? f : i.comparePoints(a, r); + if (l > 0) { + (a.row += s), (a.column += a.row == r.row ? o : 0); + continue; + } + !t && + l <= 0 && + ((a.row = n.row), (a.column = n.column), l === 0 && (a.bias = 1)); + } + }); + var e = function (e, t, n, r) { + (this.cm = e), + (this.id = t), + (this.row = n), + (this.column = r), + (e.marks[this.id] = this); + }; + (e.prototype.clear = function () { + delete this.cm.marks[this.id]; + }), + (e.prototype.find = function () { + return g(this); + }), + (this.setBookmark = function (t, n) { + var r = new e(this, this.$uid++, t.line, t.ch); + if (!n || !n.insertLeft) r.$insertRight = !0; + return (this.marks[r.id] = r), r; + }), + (this.moveH = function (e, t) { + if (t == "char") { + var n = this.ace.selection; + n.clearSelection(), n.moveCursorBy(0, e); + } + }), + (this.findPosV = function (e, t, n, r) { + if (n == "page") { + var i = this.ace.renderer, + s = i.layerConfig; + (t *= Math.floor(s.height / s.lineHeight)), (n = "line"); + } + if (n == "line") { + var o = this.ace.session.documentToScreenPosition(e.line, e.ch); + r != null && (o.column = r), + (o.row += t), + (o.row = Math.min( + Math.max(0, o.row), + this.ace.session.getScreenLength() - 1, + )); + var u = this.ace.session.screenToDocumentPosition(o.row, o.column); + return g(u); + } + debugger; + }), + (this.charCoords = function (e, t) { + if (t == "div" || !t) { + var n = this.ace.session.documentToScreenPosition(e.line, e.ch); + return { left: n.column, top: n.row }; + } + if (t == "local") { + var r = this.ace.renderer, + n = this.ace.session.documentToScreenPosition(e.line, e.ch), + i = r.layerConfig.lineHeight, + s = r.layerConfig.characterWidth, + o = i * n.row; + return { left: n.column * s, top: o, bottom: o + i }; + } + }), + (this.coordsChar = function (e, t) { + var n = this.ace.renderer; + if (t == "local") { + var r = Math.max(0, Math.floor(e.top / n.lineHeight)), + i = Math.max(0, Math.floor(e.left / n.characterWidth)), + s = n.session.screenToDocumentPosition(r, i); + return g(s); + } + if (t == "div") throw "not implemented"; + }), + (this.getSearchCursor = function (e, t, n) { + var r = !1, + i = !1; + e instanceof RegExp && + !e.global && + ((r = !e.ignoreCase), (e = e.source), (i = !0)); + var s = new l(); + t.ch == undefined && (t.ch = Number.MAX_VALUE); + var o = { row: t.line, column: t.ch }, + u = this, + a = null; + return { + findNext: function () { + return this.find(!1); + }, + findPrevious: function () { + return this.find(!0); + }, + find: function (t) { + s.setOptions({ + needle: e, + caseSensitive: r, + wrap: !1, + backwards: t, + regExp: i, + start: a || o, + }); + var n = s.find(u.ace.session); + return ( + n && + n.isEmpty() && + u.getLine(n.start.row).length == n.start.column && + ((s.$options.start = n), (n = s.find(u.ace.session))), + (a = n), + a + ); + }, + from: function () { + return a && g(a.start); + }, + to: function () { + return a && g(a.end); + }, + replace: function (e) { + a && (a.end = u.ace.session.doc.replace(a, e)); + }, + }; + }), + (this.scrollTo = function (e, t) { + var n = this.ace.renderer, + r = n.layerConfig, + i = r.maxHeight; + (i -= (n.$size.scrollerHeight - n.lineHeight) * n.$scrollPastEnd), + t != null && this.ace.session.setScrollTop(Math.max(0, Math.min(t, i))), + e != null && + this.ace.session.setScrollLeft(Math.max(0, Math.min(e, r.width))); + }), + (this.scrollInfo = function () { + return 0; + }), + (this.scrollIntoView = function (e, t) { + if (e) { + var n = this.ace.renderer, + r = { top: 0, bottom: t }; + n.scrollCursorIntoView( + m(e), + (n.lineHeight * 2) / n.$size.scrollerHeight, + r, + ); + } + }), + (this.getLine = function (e) { + return this.ace.session.getLine(e); + }), + (this.getRange = function (e, t) { + return this.ace.session.getTextRange(new i(e.line, e.ch, t.line, t.ch)); + }), + (this.replaceRange = function (e, t, n) { + return ( + n || (n = t), this.ace.session.replace(new i(t.line, t.ch, n.line, n.ch), e) + ); + }), + (this.replaceSelections = function (e) { + var t = this.ace.selection; + if (this.ace.inVirtualSelectionMode) { + this.ace.session.replace(t.getRange(), e[0] || ""); + return; + } + t.inVirtualSelectionMode = !0; + var n = t.rangeList.ranges; + n.length || (n = [this.ace.multiSelect.getRange()]); + for (var r = n.length; r--; ) this.ace.session.replace(n[r], e[r] || ""); + t.inVirtualSelectionMode = !1; + }), + (this.getSelection = function () { + return this.ace.getSelectedText(); + }), + (this.getSelections = function () { + return this.listSelections().map(function (e) { + return this.getRange(e.anchor, e.head); + }, this); + }), + (this.getInputField = function () { + return this.ace.textInput.getElement(); + }), + (this.getWrapperElement = function () { + return this.ace.containter; + }); + var t = { + indentWithTabs: "useSoftTabs", + indentUnit: "tabSize", + tabSize: "tabSize", + firstLineNumber: "firstLineNumber", + readOnly: "readOnly", + }; + (this.setOption = function (e, n) { + this.state[e] = n; + switch (e) { + case "indentWithTabs": + (e = t[e]), (n = !n); + break; + default: + e = t[e]; + } + e && this.ace.setOption(e, n); + }), + (this.getOption = function (e, n) { + var r = t[e]; + r && (n = this.ace.getOption(r)); + switch (e) { + case "indentWithTabs": + return (e = t[e]), !n; + } + return r ? n : this.state[e]; + }), + (this.toggleOverwrite = function (e) { + return (this.state.overwrite = e), this.ace.setOverwrite(e); + }), + (this.addOverlay = function (e) { + if (!this.$searchHighlight || !this.$searchHighlight.session) { + var t = new h(null, "ace_highlight-marker", "text"), + n = this.ace.session.addDynamicMarker(t); + (t.id = n.id), + (t.session = this.ace.session), + (t.destroy = function (e) { + t.session.off("change", t.updateOnChange), + t.session.off("changeEditor", t.destroy), + t.session.removeMarker(t.id), + (t.session = null); + }), + (t.updateOnChange = function (e) { + var n = e.start.row; + n == e.end.row + ? (t.cache[n] = undefined) + : t.cache.splice(n, t.cache.length); + }), + t.session.on("changeEditor", t.destroy), + t.session.on("change", t.updateOnChange); + } + var r = new RegExp(e.query.source, "gmi"); + (this.$searchHighlight = e.highlight = t), + this.$searchHighlight.setRegexp(r), + this.ace.renderer.updateBackMarkers(); + }), + (this.removeOverlay = function (e) { + this.$searchHighlight && + this.$searchHighlight.session && + this.$searchHighlight.destroy(); + }), + (this.getScrollInfo = function () { + var e = this.ace.renderer, + t = e.layerConfig; + return { + left: e.scrollLeft, + top: e.scrollTop, + height: t.maxHeight, + width: t.width, + clientHeight: t.height, + clientWidth: t.width, + }; + }), + (this.getValue = function () { + return this.ace.getValue(); + }), + (this.setValue = function (e) { + return this.ace.setValue(e); + }), + (this.getTokenTypeAt = function (e) { + var t = this.ace.session.getTokenAt(e.line, e.ch); + return t && /comment|string/.test(t.type) ? "string" : ""; + }), + (this.findMatchingBracket = function (e) { + var t = this.ace.session.findMatchingBracket(m(e)); + return { to: t && g(t) }; + }), + (this.indentLine = function (e, t) { + t === !0 + ? this.ace.session.indentRows(e, e, " ") + : t === !1 && this.ace.session.outdentRows(new i(e, 0, e, 0)); + }), + (this.indexFromPos = function (e) { + return this.ace.session.doc.positionToIndex(m(e)); + }), + (this.posFromIndex = function (e) { + return g(this.ace.session.doc.indexToPosition(e)); + }), + (this.focus = function (e) { + return this.ace.textInput.focus(); + }), + (this.blur = function (e) { + return this.ace.blur(); + }), + (this.defaultTextHeight = function (e) { + return this.ace.renderer.layerConfig.lineHeight; + }), + (this.scanForBracket = function (e, t, n, r) { + var i = r.bracketRegex.source; + if (t == 1) + var s = this.ace.session.$findClosingBracket( + i.slice(1, 2), + m(e), + /paren|text/, + ); + else + var s = this.ace.session.$findOpeningBracket( + i.slice(-2, -1), + { row: e.line, column: e.ch + 1 }, + /paren|text/, + ); + return s && { pos: g(s) }; + }), + (this.refresh = function () { + return this.ace.resize(!0); + }), + (this.getMode = function () { + return { name: this.getOption("mode") }; + }); + }.call(v.prototype); + var y = (v.StringStream = function (e, t) { + (this.pos = this.start = 0), + (this.string = e), + (this.tabSize = t || 8), + (this.lastColumnPos = this.lastColumnValue = 0), + (this.lineStart = 0); + }); + (y.prototype = { + eol: function () { + return this.pos >= this.string.length; + }, + sol: function () { + return this.pos == this.lineStart; + }, + peek: function () { + return this.string.charAt(this.pos) || undefined; + }, + next: function () { + if (this.pos < this.string.length) return this.string.charAt(this.pos++); + }, + eat: function (e) { + var t = this.string.charAt(this.pos); + if (typeof e == "string") var n = t == e; + else var n = t && (e.test ? e.test(t) : e(t)); + if (n) return ++this.pos, t; + }, + eatWhile: function (e) { + var t = this.pos; + while (this.eat(e)); + return this.pos > t; + }, + eatSpace: function () { + var e = this.pos; + while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos; + return this.pos > e; + }, + skipToEnd: function () { + this.pos = this.string.length; + }, + skipTo: function (e) { + var t = this.string.indexOf(e, this.pos); + if (t > -1) return (this.pos = t), !0; + }, + backUp: function (e) { + this.pos -= e; + }, + column: function () { + throw "not implemented"; + }, + indentation: function () { + throw "not implemented"; + }, + match: function (e, t, n) { + if (typeof e != "string") { + var s = this.string.slice(this.pos).match(e); + return s && s.index > 0 ? null : (s && t !== !1 && (this.pos += s[0].length), s); + } + var r = function (e) { + return n ? e.toLowerCase() : e; + }, + i = this.string.substr(this.pos, e.length); + if (r(i) == r(e)) return t !== !1 && (this.pos += e.length), !0; + }, + current: function () { + return this.string.slice(this.start, this.pos); + }, + hideFirstChars: function (e, t) { + this.lineStart += e; + try { + return t(); + } finally { + this.lineStart -= e; + } + }, + }), + (v.defineExtension = function (e, t) { + v.prototype[e] = t; + }), + o.importCssString( + ".normal-mode .ace_cursor{ border: 1px solid red; background-color: red; opacity: 0.5;}.normal-mode .ace_hidden-cursors .ace_cursor{ background-color: transparent;}.ace_dialog { position: absolute; left: 0; right: 0; background: inherit; z-index: 15; padding: .1em .8em; overflow: hidden; color: inherit;}.ace_dialog-top { border-bottom: 1px solid #444; top: 0;}.ace_dialog-bottom { border-top: 1px solid #444; bottom: 0;}.ace_dialog input { border: none; outline: none; background: transparent; width: 20em; color: inherit; font-family: monospace;}", + "vimMode", + ), + (function () { + function e(e, t, n) { + var r = e.ace.container, + i; + return ( + (i = r.appendChild(document.createElement("div"))), + n + ? (i.className = "ace_dialog ace_dialog-bottom") + : (i.className = "ace_dialog ace_dialog-top"), + typeof t == "string" ? (i.innerHTML = t) : i.appendChild(t), + i + ); + } + function t(e, t) { + e.state.currentNotificationClose && e.state.currentNotificationClose(), + (e.state.currentNotificationClose = t); + } + v.defineExtension("openDialog", function (n, r, i) { + function a(e) { + if (typeof e == "string") f.value = e; + else { + if (o) return; + if (e && e.type == "blur" && document.activeElement === f) return; + (u.state.dialog = null), + (o = !0), + s.parentNode.removeChild(s), + u.focus(), + i.onClose && i.onClose(s); + } + } + if (this.virtualSelectionMode()) return; + i || (i = {}), t(this, null); + var s = e(this, n, i.bottom), + o = !1, + u = this; + this.state.dialog = s; + var f = s.getElementsByTagName("input")[0], + l; + if (f) + i.value && ((f.value = i.value), i.selectValueOnOpen !== !1 && f.select()), + i.onInput && + v.on(f, "input", function (e) { + i.onInput(e, f.value, a); + }), + i.onKeyUp && + v.on(f, "keyup", function (e) { + i.onKeyUp(e, f.value, a); + }), + v.on(f, "keydown", function (e) { + if (i && i.onKeyDown && i.onKeyDown(e, f.value, a)) return; + if (e.keyCode == 27 || (i.closeOnEnter !== !1 && e.keyCode == 13)) + f.blur(), v.e_stop(e), a(); + e.keyCode == 13 && r(f.value); + }), + i.closeOnBlur !== !1 && v.on(f, "blur", a), + f.focus(); + else if ((l = s.getElementsByTagName("button")[0])) + v.on(l, "click", function () { + a(), u.focus(); + }), + i.closeOnBlur !== !1 && v.on(l, "blur", a), + l.focus(); + return a; + }), + v.defineExtension("openNotification", function (n, r) { + function a() { + if (s) return; + (s = !0), clearTimeout(o), i.parentNode.removeChild(i); + } + if (this.virtualSelectionMode()) return; + t(this, a); + var i = e(this, n, r && r.bottom), + s = !1, + o, + u = r && typeof r.duration != "undefined" ? r.duration : 5e3; + return ( + v.on(i, "click", function (e) { + v.e_preventDefault(e), a(); + }), + u && (o = setTimeout(a, u)), + a + ); + }); + })(); + var b = [ + { keys: "", type: "keyToKey", toKeys: "h" }, + { keys: "", type: "keyToKey", toKeys: "l" }, + { keys: "", type: "keyToKey", toKeys: "k" }, + { keys: "", type: "keyToKey", toKeys: "j" }, + { keys: "", type: "keyToKey", toKeys: "l" }, + { keys: "", type: "keyToKey", toKeys: "h", context: "normal" }, + { keys: "", type: "keyToKey", toKeys: "W" }, + { keys: "", type: "keyToKey", toKeys: "B", context: "normal" }, + { keys: "", type: "keyToKey", toKeys: "w" }, + { keys: "", type: "keyToKey", toKeys: "b", context: "normal" }, + { keys: "", type: "keyToKey", toKeys: "j" }, + { keys: "", type: "keyToKey", toKeys: "k" }, + { keys: "", type: "keyToKey", toKeys: "" }, + { keys: "", type: "keyToKey", toKeys: "" }, + { keys: "", type: "keyToKey", toKeys: "", context: "insert" }, + { keys: "", type: "keyToKey", toKeys: "", context: "insert" }, + { keys: "s", type: "keyToKey", toKeys: "cl", context: "normal" }, + { keys: "s", type: "keyToKey", toKeys: "c", context: "visual" }, + { keys: "S", type: "keyToKey", toKeys: "cc", context: "normal" }, + { keys: "S", type: "keyToKey", toKeys: "VdO", context: "visual" }, + { keys: "", type: "keyToKey", toKeys: "0" }, + { keys: "", type: "keyToKey", toKeys: "$" }, + { keys: "", type: "keyToKey", toKeys: "" }, + { keys: "", type: "keyToKey", toKeys: "" }, + { keys: "", type: "keyToKey", toKeys: "j^", context: "normal" }, + { keys: "", type: "action", action: "toggleOverwrite", context: "insert" }, + { + keys: "H", + type: "motion", + motion: "moveToTopLine", + motionArgs: { linewise: !0, toJumplist: !0 }, + }, + { + keys: "M", + type: "motion", + motion: "moveToMiddleLine", + motionArgs: { linewise: !0, toJumplist: !0 }, + }, + { + keys: "L", + type: "motion", + motion: "moveToBottomLine", + motionArgs: { linewise: !0, toJumplist: !0 }, + }, + { keys: "h", type: "motion", motion: "moveByCharacters", motionArgs: { forward: !1 } }, + { keys: "l", type: "motion", motion: "moveByCharacters", motionArgs: { forward: !0 } }, + { + keys: "j", + type: "motion", + motion: "moveByLines", + motionArgs: { forward: !0, linewise: !0 }, + }, + { + keys: "k", + type: "motion", + motion: "moveByLines", + motionArgs: { forward: !1, linewise: !0 }, + }, + { + keys: "gj", + type: "motion", + motion: "moveByDisplayLines", + motionArgs: { forward: !0 }, + }, + { + keys: "gk", + type: "motion", + motion: "moveByDisplayLines", + motionArgs: { forward: !1 }, + }, + { + keys: "w", + type: "motion", + motion: "moveByWords", + motionArgs: { forward: !0, wordEnd: !1 }, + }, + { + keys: "W", + type: "motion", + motion: "moveByWords", + motionArgs: { forward: !0, wordEnd: !1, bigWord: !0 }, + }, + { + keys: "e", + type: "motion", + motion: "moveByWords", + motionArgs: { forward: !0, wordEnd: !0, inclusive: !0 }, + }, + { + keys: "E", + type: "motion", + motion: "moveByWords", + motionArgs: { forward: !0, wordEnd: !0, bigWord: !0, inclusive: !0 }, + }, + { + keys: "b", + type: "motion", + motion: "moveByWords", + motionArgs: { forward: !1, wordEnd: !1 }, + }, + { + keys: "B", + type: "motion", + motion: "moveByWords", + motionArgs: { forward: !1, wordEnd: !1, bigWord: !0 }, + }, + { + keys: "ge", + type: "motion", + motion: "moveByWords", + motionArgs: { forward: !1, wordEnd: !0, inclusive: !0 }, + }, + { + keys: "gE", + type: "motion", + motion: "moveByWords", + motionArgs: { forward: !1, wordEnd: !0, bigWord: !0, inclusive: !0 }, + }, + { + keys: "{", + type: "motion", + motion: "moveByParagraph", + motionArgs: { forward: !1, toJumplist: !0 }, + }, + { + keys: "}", + type: "motion", + motion: "moveByParagraph", + motionArgs: { forward: !0, toJumplist: !0 }, + }, + { keys: "", type: "motion", motion: "moveByPage", motionArgs: { forward: !0 } }, + { keys: "", type: "motion", motion: "moveByPage", motionArgs: { forward: !1 } }, + { + keys: "", + type: "motion", + motion: "moveByScroll", + motionArgs: { forward: !0, explicitRepeat: !0 }, + }, + { + keys: "", + type: "motion", + motion: "moveByScroll", + motionArgs: { forward: !1, explicitRepeat: !0 }, + }, + { + keys: "gg", + type: "motion", + motion: "moveToLineOrEdgeOfDocument", + motionArgs: { forward: !1, explicitRepeat: !0, linewise: !0, toJumplist: !0 }, + }, + { + keys: "G", + type: "motion", + motion: "moveToLineOrEdgeOfDocument", + motionArgs: { forward: !0, explicitRepeat: !0, linewise: !0, toJumplist: !0 }, + }, + { keys: "0", type: "motion", motion: "moveToStartOfLine" }, + { keys: "^", type: "motion", motion: "moveToFirstNonWhiteSpaceCharacter" }, + { + keys: "+", + type: "motion", + motion: "moveByLines", + motionArgs: { forward: !0, toFirstChar: !0 }, + }, + { + keys: "-", + type: "motion", + motion: "moveByLines", + motionArgs: { forward: !1, toFirstChar: !0 }, + }, + { + keys: "_", + type: "motion", + motion: "moveByLines", + motionArgs: { forward: !0, toFirstChar: !0, repeatOffset: -1 }, + }, + { keys: "$", type: "motion", motion: "moveToEol", motionArgs: { inclusive: !0 } }, + { + keys: "%", + type: "motion", + motion: "moveToMatchedSymbol", + motionArgs: { inclusive: !0, toJumplist: !0 }, + }, + { + keys: "f", + type: "motion", + motion: "moveToCharacter", + motionArgs: { forward: !0, inclusive: !0 }, + }, + { + keys: "F", + type: "motion", + motion: "moveToCharacter", + motionArgs: { forward: !1 }, + }, + { + keys: "t", + type: "motion", + motion: "moveTillCharacter", + motionArgs: { forward: !0, inclusive: !0 }, + }, + { + keys: "T", + type: "motion", + motion: "moveTillCharacter", + motionArgs: { forward: !1 }, + }, + { + keys: ";", + type: "motion", + motion: "repeatLastCharacterSearch", + motionArgs: { forward: !0 }, + }, + { + keys: ",", + type: "motion", + motion: "repeatLastCharacterSearch", + motionArgs: { forward: !1 }, + }, + { + keys: "'", + type: "motion", + motion: "goToMark", + motionArgs: { toJumplist: !0, linewise: !0 }, + }, + { + keys: "`", + type: "motion", + motion: "goToMark", + motionArgs: { toJumplist: !0 }, + }, + { keys: "]`", type: "motion", motion: "jumpToMark", motionArgs: { forward: !0 } }, + { keys: "[`", type: "motion", motion: "jumpToMark", motionArgs: { forward: !1 } }, + { + keys: "]'", + type: "motion", + motion: "jumpToMark", + motionArgs: { forward: !0, linewise: !0 }, + }, + { + keys: "['", + type: "motion", + motion: "jumpToMark", + motionArgs: { forward: !1, linewise: !0 }, + }, + { + keys: "]p", + type: "action", + action: "paste", + isEdit: !0, + actionArgs: { after: !0, isEdit: !0, matchIndent: !0 }, + }, + { + keys: "[p", + type: "action", + action: "paste", + isEdit: !0, + actionArgs: { after: !1, isEdit: !0, matchIndent: !0 }, + }, + { + keys: "]", + type: "motion", + motion: "moveToSymbol", + motionArgs: { forward: !0, toJumplist: !0 }, + }, + { + keys: "[", + type: "motion", + motion: "moveToSymbol", + motionArgs: { forward: !1, toJumplist: !0 }, + }, + { keys: "|", type: "motion", motion: "moveToColumn" }, + { keys: "o", type: "motion", motion: "moveToOtherHighlightedEnd", context: "visual" }, + { + keys: "O", + type: "motion", + motion: "moveToOtherHighlightedEnd", + motionArgs: { sameLine: !0 }, + context: "visual", + }, + { keys: "d", type: "operator", operator: "delete" }, + { keys: "y", type: "operator", operator: "yank" }, + { keys: "c", type: "operator", operator: "change" }, + { keys: ">", type: "operator", operator: "indent", operatorArgs: { indentRight: !0 } }, + { keys: "<", type: "operator", operator: "indent", operatorArgs: { indentRight: !1 } }, + { keys: "g~", type: "operator", operator: "changeCase" }, + { + keys: "gu", + type: "operator", + operator: "changeCase", + operatorArgs: { toLower: !0 }, + isEdit: !0, + }, + { + keys: "gU", + type: "operator", + operator: "changeCase", + operatorArgs: { toLower: !1 }, + isEdit: !0, + }, + { + keys: "n", + type: "motion", + motion: "findNext", + motionArgs: { forward: !0, toJumplist: !0 }, + }, + { + keys: "N", + type: "motion", + motion: "findNext", + motionArgs: { forward: !1, toJumplist: !0 }, + }, + { + keys: "x", + type: "operatorMotion", + operator: "delete", + motion: "moveByCharacters", + motionArgs: { forward: !0 }, + operatorMotionArgs: { visualLine: !1 }, + }, + { + keys: "X", + type: "operatorMotion", + operator: "delete", + motion: "moveByCharacters", + motionArgs: { forward: !1 }, + operatorMotionArgs: { visualLine: !0 }, + }, + { + keys: "D", + type: "operatorMotion", + operator: "delete", + motion: "moveToEol", + motionArgs: { inclusive: !0 }, + context: "normal", + }, + { + keys: "D", + type: "operator", + operator: "delete", + operatorArgs: { linewise: !0 }, + context: "visual", + }, + { + keys: "Y", + type: "operatorMotion", + operator: "yank", + motion: "moveToEol", + motionArgs: { inclusive: !0 }, + context: "normal", + }, + { + keys: "Y", + type: "operator", + operator: "yank", + operatorArgs: { linewise: !0 }, + context: "visual", + }, + { + keys: "C", + type: "operatorMotion", + operator: "change", + motion: "moveToEol", + motionArgs: { inclusive: !0 }, + context: "normal", + }, + { + keys: "C", + type: "operator", + operator: "change", + operatorArgs: { linewise: !0 }, + context: "visual", + }, + { + keys: "~", + type: "operatorMotion", + operator: "changeCase", + motion: "moveByCharacters", + motionArgs: { forward: !0 }, + operatorArgs: { shouldMoveCursor: !0 }, + context: "normal", + }, + { keys: "~", type: "operator", operator: "changeCase", context: "visual" }, + { + keys: "", + type: "operatorMotion", + operator: "delete", + motion: "moveByWords", + motionArgs: { forward: !1, wordEnd: !1 }, + context: "insert", + }, + { keys: "", type: "action", action: "jumpListWalk", actionArgs: { forward: !0 } }, + { keys: "", type: "action", action: "jumpListWalk", actionArgs: { forward: !1 } }, + { + keys: "", + type: "action", + action: "scroll", + actionArgs: { forward: !0, linewise: !0 }, + }, + { + keys: "", + type: "action", + action: "scroll", + actionArgs: { forward: !1, linewise: !0 }, + }, + { + keys: "a", + type: "action", + action: "enterInsertMode", + isEdit: !0, + actionArgs: { insertAt: "charAfter" }, + context: "normal", + }, + { + keys: "A", + type: "action", + action: "enterInsertMode", + isEdit: !0, + actionArgs: { insertAt: "eol" }, + context: "normal", + }, + { + keys: "A", + type: "action", + action: "enterInsertMode", + isEdit: !0, + actionArgs: { insertAt: "endOfSelectedArea" }, + context: "visual", + }, + { + keys: "i", + type: "action", + action: "enterInsertMode", + isEdit: !0, + actionArgs: { insertAt: "inplace" }, + context: "normal", + }, + { + keys: "I", + type: "action", + action: "enterInsertMode", + isEdit: !0, + actionArgs: { insertAt: "firstNonBlank" }, + context: "normal", + }, + { + keys: "I", + type: "action", + action: "enterInsertMode", + isEdit: !0, + actionArgs: { insertAt: "startOfSelectedArea" }, + context: "visual", + }, + { + keys: "o", + type: "action", + action: "newLineAndEnterInsertMode", + isEdit: !0, + interlaceInsertRepeat: !0, + actionArgs: { after: !0 }, + context: "normal", + }, + { + keys: "O", + type: "action", + action: "newLineAndEnterInsertMode", + isEdit: !0, + interlaceInsertRepeat: !0, + actionArgs: { after: !1 }, + context: "normal", + }, + { keys: "v", type: "action", action: "toggleVisualMode" }, + { keys: "V", type: "action", action: "toggleVisualMode", actionArgs: { linewise: !0 } }, + { + keys: "", + type: "action", + action: "toggleVisualMode", + actionArgs: { blockwise: !0 }, + }, + { + keys: "", + type: "action", + action: "toggleVisualMode", + actionArgs: { blockwise: !0 }, + }, + { keys: "gv", type: "action", action: "reselectLastSelection" }, + { keys: "J", type: "action", action: "joinLines", isEdit: !0 }, + { + keys: "p", + type: "action", + action: "paste", + isEdit: !0, + actionArgs: { after: !0, isEdit: !0 }, + }, + { + keys: "P", + type: "action", + action: "paste", + isEdit: !0, + actionArgs: { after: !1, isEdit: !0 }, + }, + { keys: "r", type: "action", action: "replace", isEdit: !0 }, + { keys: "@", type: "action", action: "replayMacro" }, + { keys: "q", type: "action", action: "enterMacroRecordMode" }, + { + keys: "R", + type: "action", + action: "enterInsertMode", + isEdit: !0, + actionArgs: { replace: !0 }, + }, + { keys: "u", type: "action", action: "undo", context: "normal" }, + { + keys: "u", + type: "operator", + operator: "changeCase", + operatorArgs: { toLower: !0 }, + context: "visual", + isEdit: !0, + }, + { + keys: "U", + type: "operator", + operator: "changeCase", + operatorArgs: { toLower: !1 }, + context: "visual", + isEdit: !0, + }, + { keys: "", type: "action", action: "redo" }, + { keys: "m", type: "action", action: "setMark" }, + { keys: '"', type: "action", action: "setRegister" }, + { + keys: "zz", + type: "action", + action: "scrollToCursor", + actionArgs: { position: "center" }, + }, + { + keys: "z.", + type: "action", + action: "scrollToCursor", + actionArgs: { position: "center" }, + motion: "moveToFirstNonWhiteSpaceCharacter", + }, + { + keys: "zt", + type: "action", + action: "scrollToCursor", + actionArgs: { position: "top" }, + }, + { + keys: "z", + type: "action", + action: "scrollToCursor", + actionArgs: { position: "top" }, + motion: "moveToFirstNonWhiteSpaceCharacter", + }, + { + keys: "z-", + type: "action", + action: "scrollToCursor", + actionArgs: { position: "bottom" }, + }, + { + keys: "zb", + type: "action", + action: "scrollToCursor", + actionArgs: { position: "bottom" }, + motion: "moveToFirstNonWhiteSpaceCharacter", + }, + { keys: ".", type: "action", action: "repeatLastEdit" }, + { + keys: "", + type: "action", + action: "incrementNumberToken", + isEdit: !0, + actionArgs: { increase: !0, backtrack: !1 }, + }, + { + keys: "", + type: "action", + action: "incrementNumberToken", + isEdit: !0, + actionArgs: { increase: !1, backtrack: !1 }, + }, + { + keys: "", + type: "action", + action: "indent", + actionArgs: { indentRight: !0 }, + context: "insert", + }, + { + keys: "", + type: "action", + action: "indent", + actionArgs: { indentRight: !1 }, + context: "insert", + }, + { keys: "a", type: "motion", motion: "textObjectManipulation" }, + { + keys: "i", + type: "motion", + motion: "textObjectManipulation", + motionArgs: { textObjectInner: !0 }, + }, + { + keys: "/", + type: "search", + searchArgs: { forward: !0, querySrc: "prompt", toJumplist: !0 }, + }, + { + keys: "?", + type: "search", + searchArgs: { forward: !1, querySrc: "prompt", toJumplist: !0 }, + }, + { + keys: "*", + type: "search", + searchArgs: { + forward: !0, + querySrc: "wordUnderCursor", + wholeWordOnly: !0, + toJumplist: !0, + }, + }, + { + keys: "#", + type: "search", + searchArgs: { + forward: !1, + querySrc: "wordUnderCursor", + wholeWordOnly: !0, + toJumplist: !0, + }, + }, + { + keys: "g*", + type: "search", + searchArgs: { forward: !0, querySrc: "wordUnderCursor", toJumplist: !0 }, + }, + { + keys: "g#", + type: "search", + searchArgs: { forward: !1, querySrc: "wordUnderCursor", toJumplist: !0 }, + }, + { keys: ":", type: "ex" }, + ], + w = [ + { name: "colorscheme", shortName: "colo" }, + { name: "map" }, + { name: "imap", shortName: "im" }, + { name: "nmap", shortName: "nm" }, + { name: "vmap", shortName: "vm" }, + { name: "unmap" }, + { name: "write", shortName: "w" }, + { name: "undo", shortName: "u" }, + { name: "redo", shortName: "red" }, + { name: "set", shortName: "se" }, + { name: "set", shortName: "se" }, + { name: "setlocal", shortName: "setl" }, + { name: "setglobal", shortName: "setg" }, + { name: "sort", shortName: "sor" }, + { name: "substitute", shortName: "s", possiblyAsync: !0 }, + { name: "nohlsearch", shortName: "noh" }, + { name: "yank", shortName: "y" }, + { name: "delmarks", shortName: "delm" }, + { name: "registers", shortName: "reg", excludeFromCommandHistory: !0 }, + { name: "global", shortName: "g" }, + ], + E = v.Pos, + S = function () { + return st; + }; + v.defineOption("vimMode", !1, function (e, t, n) { + t && e.getOption("keyMap") != "vim" + ? e.setOption("keyMap", "vim") + : !t && + n != v.Init && + /^vim/.test(e.getOption("keyMap")) && + e.setOption("keyMap", "default"); + }); + var L = { Shift: "S", Ctrl: "C", Alt: "A", Cmd: "D", Mod: "A" }, + A = { Enter: "CR", Backspace: "BS", Delete: "Del", Insert: "Ins" }, + _ = /[\d]/, + D = [ + v.isWordChar, + function (e) { + return e && !v.isWordChar(e) && !/\s/.test(e); + }, + ], + P = [ + function (e) { + return /\S/.test(e); + }, + ], + B = H(65, 26), + j = H(97, 26), + F = H(48, 10), + I = [].concat(B, j, F, ["<", ">"]), + q = [].concat(B, j, F, ["-", '"', ".", ":", "/"]), + J = {}; + K("filetype", undefined, "string", ["ft"], function (e, t) { + if (t === undefined) return; + if (e === undefined) { + var n = t.getOption("mode"); + return n == "null" ? "" : n; + } + var n = e == "" ? "null" : e; + t.setOption("mode", n); + }); + var Y = function () { + function s(s, o, u) { + function l(n) { + var r = ++t % e, + o = i[r]; + o && o.clear(), (i[r] = s.setBookmark(n)); + } + var a = t % e, + f = i[a]; + if (f) { + var c = f.find(); + c && !At(c, o) && l(o); + } else l(o); + l(u), (n = t), (r = t - e + 1), r < 0 && (r = 0); + } + function o(s, o) { + (t += o), t > n ? (t = n) : t < r && (t = r); + var u = i[(e + t) % e]; + if (u && !u.find()) { + var a = o > 0 ? 1 : -1, + f, + l = s.getCursor(); + do { + (t += a), (u = i[(e + t) % e]); + if (u && (f = u.find()) && !At(l, f)) break; + } while (t < n && t > r); + } + return u; + } + var e = 100, + t = -1, + n = 0, + r = 0, + i = new Array(e); + return { cachedCursor: undefined, add: s, move: o }; + }, + Z = function (e) { + return e + ? { + changes: e.changes, + expectCursorActivityForChange: e.expectCursorActivityForChange, + } + : { changes: [], expectCursorActivityForChange: !1 }; + }; + et.prototype = { + exitMacroRecordMode: function () { + var e = nt.macroModeState; + e.onRecordingDone && e.onRecordingDone(), + (e.onRecordingDone = undefined), + (e.isRecording = !1); + }, + enterMacroRecordMode: function (e, t) { + var n = nt.registerController.getRegister(t); + n && + (n.clear(), + (this.latestRegister = t), + e.openDialog && + (this.onRecordingDone = e.openDialog("(recording)[" + t + "]", null, { + bottom: !0, + })), + (this.isRecording = !0)); + }, + }; + var nt, + it, + st = { + buildKeyMap: function () {}, + getRegisterController: function () { + return nt.registerController; + }, + resetVimGlobalState_: rt, + getVimGlobalState_: function () { + return nt; + }, + maybeInitVimState_: tt, + suppressErrorLogging: !1, + InsertModeKey: er, + map: function (e, t, n) { + Rn.map(e, t, n); + }, + unmap: function (e, t) { + Rn.unmap(e, t); + }, + setOption: Q, + getOption: G, + defineOption: K, + defineEx: function (e, t, n) { + if (!t) t = e; + else if (e.indexOf(t) !== 0) + throw new Error( + '(Vim.defineEx) "' + + t + + '" is not a prefix of "' + + e + + '", command not registered', + ); + (qn[e] = n), (Rn.commandMap_[t] = { name: e, shortName: t, type: "api" }); + }, + handleKey: function (e, t, n) { + var r = this.findKey(e, t, n); + if (typeof r == "function") return r(); + }, + findKey: function (e, t, n) { + function i() { + var r = nt.macroModeState; + if (r.isRecording) { + if (t == "q") return r.exitMacroRecordMode(), ut(e), !0; + n != "mapping" && $n(r, t); + } + } + function s() { + if (t == "") + return ut(e), r.visualMode ? $t(e) : r.insertMode && zn(e), !0; + } + function o(n) { + var r; + while (n) + (r = /<\w+-.+?>|<\w+>|./.exec(n)), + (t = r[0]), + (n = n.substring(r.index + t.length)), + v.Vim.handleKey(e, t, "mapping"); + } + function u() { + if (s()) return !0; + var n = (r.inputState.keyBuffer = r.inputState.keyBuffer + t), + i = t.length == 1, + o = ht.matchCommand(n, b, r.inputState, "insert"); + while (n.length > 1 && o.type != "full") { + var n = (r.inputState.keyBuffer = n.slice(1)), + u = ht.matchCommand(n, b, r.inputState, "insert"); + u.type != "none" && (o = u); + } + if (o.type == "none") return ut(e), !1; + if (o.type == "partial") + return ( + it && window.clearTimeout(it), + (it = window.setTimeout(function () { + r.insertMode && r.inputState.keyBuffer && ut(e); + }, G("insertModeEscKeysTimeout"))), + !i + ); + it && window.clearTimeout(it); + if (i) { + var a = e.listSelections(); + for (var f = 0; f < a.length; f++) { + var l = a[f].head; + e.replaceRange("", St(l, 0, -(n.length - 1)), l, "+input"); + } + nt.macroModeState.lastInsertModeChanges.changes.pop(); + } + return ut(e), o.command; + } + function a() { + if (i() || s()) return !0; + var n = (r.inputState.keyBuffer = r.inputState.keyBuffer + t); + if (/^[1-9]\d*$/.test(n)) return !0; + var o = /^(\d*)(.*)$/.exec(n); + if (!o) return ut(e), !1; + var u = r.visualMode ? "visual" : "normal", + a = ht.matchCommand(o[2] || o[1], b, r.inputState, u); + if (a.type == "none") return ut(e), !1; + if (a.type == "partial") return !0; + r.inputState.keyBuffer = ""; + var o = /^(\d*)(.*)$/.exec(n); + return o[1] && o[1] != "0" && r.inputState.pushRepeatDigit(o[1]), a.command; + } + var r = tt(e), + f; + return ( + r.insertMode ? (f = u()) : (f = a()), + f === !1 + ? undefined + : f === !0 + ? function () { + return !0; + } + : function () { + if ((f.operator || f.isEdit) && e.getOption("readOnly")) return; + return e.operation(function () { + e.curOp.isVimOp = !0; + try { + f.type == "keyToKey" + ? o(f.toKeys) + : ht.processCommand(e, r, f); + } catch (t) { + throw ( + ((e.state.vim = undefined), + tt(e), + v.Vim.suppressErrorLogging || console.log(t), + t) + ); + } + return !0; + }); + } + ); + }, + handleEx: function (e, t) { + Rn.processCommand(e, t); + }, + defineMotion: dt, + defineAction: bt, + defineOperator: gt, + mapCommand: Xn, + _mapCommand: Wn, + defineRegister: ft, + exitVisualMode: $t, + exitInsertMode: zn, + }; + (ot.prototype.pushRepeatDigit = function (e) { + this.operator + ? (this.motionRepeat = this.motionRepeat.concat(e)) + : (this.prefixRepeat = this.prefixRepeat.concat(e)); + }), + (ot.prototype.getRepeat = function () { + var e = 0; + if (this.prefixRepeat.length > 0 || this.motionRepeat.length > 0) + (e = 1), + this.prefixRepeat.length > 0 && (e *= parseInt(this.prefixRepeat.join(""), 10)), + this.motionRepeat.length > 0 && (e *= parseInt(this.motionRepeat.join(""), 10)); + return e; + }), + (at.prototype = { + setText: function (e, t, n) { + (this.keyBuffer = [e || ""]), (this.linewise = !!t), (this.blockwise = !!n); + }, + pushText: function (e, t) { + t && (this.linewise || this.keyBuffer.push("\n"), (this.linewise = !0)), + this.keyBuffer.push(e); + }, + pushInsertModeChanges: function (e) { + this.insertModeChanges.push(Z(e)); + }, + pushSearchQuery: function (e) { + this.searchQueries.push(e); + }, + clear: function () { + (this.keyBuffer = []), + (this.insertModeChanges = []), + (this.searchQueries = []), + (this.linewise = !1); + }, + toString: function () { + return this.keyBuffer.join(""); + }, + }), + (lt.prototype = { + pushText: function (e, t, n, r, i) { + r && n.charAt(n.length - 1) !== "\n" && (n += "\n"); + var s = this.isValidRegister(e) ? this.getRegister(e) : null; + if (!s) { + switch (t) { + case "yank": + this.registers[0] = new at(n, r, i); + break; + case "delete": + case "change": + n.indexOf("\n") == -1 + ? (this.registers["-"] = new at(n, r)) + : (this.shiftNumericRegisters_(), + (this.registers[1] = new at(n, r))); + } + this.unnamedRegister.setText(n, r, i); + return; + } + var o = X(e); + o ? s.pushText(n, r) : s.setText(n, r, i), + this.unnamedRegister.setText(s.toString(), r); + }, + getRegister: function (e) { + return this.isValidRegister(e) + ? ((e = e.toLowerCase()), + this.registers[e] || (this.registers[e] = new at()), + this.registers[e]) + : this.unnamedRegister; + }, + isValidRegister: function (e) { + return e && $(e, q); + }, + shiftNumericRegisters_: function () { + for (var e = 9; e >= 2; e--) this.registers[e] = this.getRegister("" + (e - 1)); + }, + }), + (ct.prototype = { + nextMatch: function (e, t) { + var n = this.historyBuffer, + r = t ? -1 : 1; + this.initialPrefix === null && (this.initialPrefix = e); + for (var i = this.iterator + r; t ? i >= 0 : i < n.length; i += r) { + var s = n[i]; + for (var o = 0; o <= s.length; o++) + if (this.initialPrefix == s.substring(0, o)) return (this.iterator = i), s; + } + if (i >= n.length) return (this.iterator = n.length), this.initialPrefix; + if (i < 0) return e; + }, + pushInput: function (e) { + var t = this.historyBuffer.indexOf(e); + t > -1 && this.historyBuffer.splice(t, 1), e.length && this.historyBuffer.push(e); + }, + reset: function () { + (this.initialPrefix = null), (this.iterator = this.historyBuffer.length); + }, + }); + var ht = { + matchCommand: function (e, t, n, r) { + var i = Tt(e, t, r, n); + if (!i.full && !i.partial) return { type: "none" }; + if (!i.full && i.partial) return { type: "partial" }; + var s; + for (var o = 0; o < i.full.length; o++) { + var u = i.full[o]; + s || (s = u); + } + if (s.keys.slice(-11) == "") { + var a = Ct(e); + if (//.test(a)) return { type: "none" }; + n.selectedCharacter = a; + } + return { type: "full", command: s }; + }, + processCommand: function (e, t, n) { + t.inputState.repeatOverride = n.repeatOverride; + switch (n.type) { + case "motion": + this.processMotion(e, t, n); + break; + case "operator": + this.processOperator(e, t, n); + break; + case "operatorMotion": + this.processOperatorMotion(e, t, n); + break; + case "action": + this.processAction(e, t, n); + break; + case "search": + this.processSearch(e, t, n); + break; + case "ex": + case "keyToEx": + this.processEx(e, t, n); + break; + default: + } + }, + processMotion: function (e, t, n) { + (t.inputState.motion = n.motion), + (t.inputState.motionArgs = Et(n.motionArgs)), + this.evalInput(e, t); + }, + processOperator: function (e, t, n) { + var r = t.inputState; + if (r.operator) { + if (r.operator == n.operator) { + (r.motion = "expandToLine"), + (r.motionArgs = { linewise: !0 }), + this.evalInput(e, t); + return; + } + ut(e); + } + (r.operator = n.operator), + (r.operatorArgs = Et(n.operatorArgs)), + t.visualMode && this.evalInput(e, t); + }, + processOperatorMotion: function (e, t, n) { + var r = t.visualMode, + i = Et(n.operatorMotionArgs); + i && r && i.visualLine && (t.visualLine = !0), + this.processOperator(e, t, n), + r || this.processMotion(e, t, n); + }, + processAction: function (e, t, n) { + var r = t.inputState, + i = r.getRepeat(), + s = !!i, + o = Et(n.actionArgs) || {}; + r.selectedCharacter && (o.selectedCharacter = r.selectedCharacter), + n.operator && this.processOperator(e, t, n), + n.motion && this.processMotion(e, t, n), + (n.motion || n.operator) && this.evalInput(e, t), + (o.repeat = i || 1), + (o.repeatIsExplicit = s), + (o.registerName = r.registerName), + ut(e), + (t.lastMotion = null), + n.isEdit && this.recordLastEdit(t, r, n), + yt[n.action](e, o, t); + }, + processSearch: function (e, t, n) { + function a(r, i, s) { + nt.searchHistoryController.pushInput(r), nt.searchHistoryController.reset(); + try { + Mn(e, r, i, s); + } catch (o) { + Cn(e, "Invalid regex: " + r), ut(e); + return; + } + ht.processMotion(e, t, { + type: "motion", + motion: "findNext", + motionArgs: { forward: !0, toJumplist: n.searchArgs.toJumplist }, }); - })(); - \ No newline at end of file + } + function f(t) { + e.scrollTo(u.left, u.top), a(t, !0, !0); + var n = nt.macroModeState; + n.isRecording && Kn(n, t); + } + function l(t, n, i) { + var s = v.keyName(t), + o, + a; + s == "Up" || s == "Down" + ? ((o = s == "Up" ? !0 : !1), + (a = t.target ? t.target.selectionEnd : 0), + (n = nt.searchHistoryController.nextMatch(n, o) || ""), + i(n), + a && + t.target && + (t.target.selectionEnd = t.target.selectionStart = + Math.min(a, t.target.value.length))) + : s != "Left" && + s != "Right" && + s != "Ctrl" && + s != "Alt" && + s != "Shift" && + nt.searchHistoryController.reset(); + var f; + try { + f = Mn(e, n, !0, !0); + } catch (t) {} + f ? e.scrollIntoView(Pn(e, !r, f), 30) : (Hn(e), e.scrollTo(u.left, u.top)); + } + function c(t, n, r) { + var i = v.keyName(t); + i == "Esc" || i == "Ctrl-C" || i == "Ctrl-[" || (i == "Backspace" && n == "") + ? (nt.searchHistoryController.pushInput(n), + nt.searchHistoryController.reset(), + Mn(e, o), + Hn(e), + e.scrollTo(u.left, u.top), + v.e_stop(t), + ut(e), + r(), + e.focus()) + : i == "Up" || i == "Down" + ? v.e_stop(t) + : i == "Ctrl-U" && (v.e_stop(t), r("")); + } + if (!e.getSearchCursor) return; + var r = n.searchArgs.forward, + i = n.searchArgs.wholeWordOnly; + dn(e).setReversed(!r); + var s = r ? "/" : "?", + o = dn(e).getQuery(), + u = e.getScrollInfo(); + switch (n.searchArgs.querySrc) { + case "prompt": + var h = nt.macroModeState; + if (h.isPlaying) { + var p = h.replaySearchQueries.shift(); + a(p, !0, !1); + } else An(e, { onClose: f, prefix: s, desc: Ln, onKeyUp: l, onKeyDown: c }); + break; + case "wordUnderCursor": + var d = Gt(e, !1, !0, !1, !0), + m = !0; + d || ((d = Gt(e, !1, !0, !1, !1)), (m = !1)); + if (!d) return; + var p = e.getLine(d.start.line).substring(d.start.ch, d.end.ch); + m && i ? (p = "\\b" + p + "\\b") : (p = Bt(p)), + (nt.jumpList.cachedCursor = e.getCursor()), + e.setCursor(d.start), + a(p, !0, !1); + } + }, + processEx: function (e, t, n) { + function r(t) { + nt.exCommandHistoryController.pushInput(t), + nt.exCommandHistoryController.reset(), + Rn.processCommand(e, t); + } + function i(t, n, r) { + var i = v.keyName(t), + s, + o; + if ( + i == "Esc" || + i == "Ctrl-C" || + i == "Ctrl-[" || + (i == "Backspace" && n == "") + ) + nt.exCommandHistoryController.pushInput(n), + nt.exCommandHistoryController.reset(), + v.e_stop(t), + ut(e), + r(), + e.focus(); + i == "Up" || i == "Down" + ? (v.e_stop(t), + (s = i == "Up" ? !0 : !1), + (o = t.target ? t.target.selectionEnd : 0), + (n = nt.exCommandHistoryController.nextMatch(n, s) || ""), + r(n), + o && + t.target && + (t.target.selectionEnd = t.target.selectionStart = + Math.min(o, t.target.value.length))) + : i == "Ctrl-U" + ? (v.e_stop(t), r("")) + : i != "Left" && + i != "Right" && + i != "Ctrl" && + i != "Alt" && + i != "Shift" && + nt.exCommandHistoryController.reset(); + } + n.type == "keyToEx" + ? Rn.processCommand(e, n.exArgs.input) + : t.visualMode + ? An(e, { + onClose: r, + prefix: ":", + value: "'<,'>", + onKeyDown: i, + selectValueOnOpen: !1, + }) + : An(e, { onClose: r, prefix: ":", onKeyDown: i }); + }, + evalInput: function (e, t) { + var n = t.inputState, + r = n.motion, + i = n.motionArgs || {}, + s = n.operator, + o = n.operatorArgs || {}, + u = n.registerName, + a = t.sel, + f = Lt(t.visualMode ? wt(e, a.head) : e.getCursor("head")), + l = Lt(t.visualMode ? wt(e, a.anchor) : e.getCursor("anchor")), + c = Lt(f), + h = Lt(l), + p, + d, + v; + s && this.recordLastEdit(t, n), + n.repeatOverride !== undefined ? (v = n.repeatOverride) : (v = n.getRepeat()); + if (v > 0 && i.explicitRepeat) i.repeatIsExplicit = !0; + else if (i.noRepeat || (!i.explicitRepeat && v === 0)) + (v = 1), (i.repeatIsExplicit = !1); + n.selectedCharacter && + (i.selectedCharacter = o.selectedCharacter = n.selectedCharacter), + (i.repeat = v), + ut(e); + if (r) { + var m = pt[r](e, f, i, t); + t.lastMotion = pt[r]; + if (!m) return; + if (i.toJumplist) { + !s && + e.ace.curOp != null && + (e.ace.curOp.command.scrollIntoView = "center-animate"); + var g = nt.jumpList, + y = g.cachedCursor; + y ? (Yt(e, y, m), delete g.cachedCursor) : Yt(e, f, m); + } + m instanceof Array ? ((d = m[0]), (p = m[1])) : (p = m), p || (p = Lt(f)); + if (t.visualMode) { + if (!t.visualBlock || p.ch !== Infinity) p = wt(e, p, t.visualBlock); + d && (d = wt(e, d, !0)), + (d = d || h), + (a.anchor = d), + (a.head = p), + Wt(e), + an(e, t, "<", Ot(d, p) ? d : p), + an(e, t, ">", Ot(d, p) ? p : d); + } else s || ((p = wt(e, p)), e.setCursor(p.line, p.ch)); + } + if (s) { + if (o.lastSel) { + d = h; + var b = o.lastSel, + w = Math.abs(b.head.line - b.anchor.line), + S = Math.abs(b.head.ch - b.anchor.ch); + b.visualLine + ? (p = E(h.line + w, h.ch)) + : b.visualBlock + ? (p = E(h.line + w, h.ch + S)) + : b.head.line == b.anchor.line + ? (p = E(h.line, h.ch + S)) + : (p = E(h.line + w, h.ch)), + (t.visualMode = !0), + (t.visualLine = b.visualLine), + (t.visualBlock = b.visualBlock), + (a = t.sel = { anchor: d, head: p }), + Wt(e); + } else + t.visualMode && + (o.lastSel = { + anchor: Lt(a.anchor), + head: Lt(a.head), + visualBlock: t.visualBlock, + visualLine: t.visualLine, + }); + var x, T, N, C, k; + if (t.visualMode) { + (x = Mt(a.head, a.anchor)), + (T = _t(a.head, a.anchor)), + (N = t.visualLine || o.linewise), + (C = t.visualBlock ? "block" : N ? "line" : "char"), + (k = Xt(e, { anchor: x, head: T }, C)); + if (N) { + var L = k.ranges; + if (C == "block") + for (var A = 0; A < L.length; A++) + L[A].head.ch = Pt(e, L[A].head.line); + else C == "line" && (L[0].head = E(L[0].head.line + 1, 0)); + } + } else { + (x = Lt(d || h)), (T = Lt(p || c)); + if (Ot(T, x)) { + var O = x; + (x = T), (T = O); + } + (N = i.linewise || o.linewise), + N ? Kt(e, x, T) : i.forward && Jt(e, x, T), + (C = "char"); + var M = !i.inclusive || N; + k = Xt(e, { anchor: x, head: T }, C, M); + } + e.setSelections(k.ranges, k.primary), + (t.lastMotion = null), + (o.repeat = v), + (o.registerName = u), + (o.linewise = N); + var _ = mt[s](e, o, k.ranges, h, p); + t.visualMode && $t(e, _ != null), _ && e.setCursor(_); + } + }, + recordLastEdit: function (e, t, n) { + var r = nt.macroModeState; + if (r.isPlaying) return; + (e.lastEditInputState = t), + (e.lastEditActionCommand = n), + (r.lastInsertModeChanges.changes = []), + (r.lastInsertModeChanges.expectCursorActivityForChange = !1); + }, + }, + pt = { + moveToTopLine: function (e, t, n) { + var r = jn(e).top + n.repeat - 1; + return E(r, Qt(e.getLine(r))); + }, + moveToMiddleLine: function (e) { + var t = jn(e), + n = Math.floor((t.top + t.bottom) * 0.5); + return E(n, Qt(e.getLine(n))); + }, + moveToBottomLine: function (e, t, n) { + var r = jn(e).bottom - n.repeat + 1; + return E(r, Qt(e.getLine(r))); + }, + expandToLine: function (e, t, n) { + var r = t; + return E(r.line + n.repeat - 1, Infinity); + }, + findNext: function (e, t, n) { + var r = dn(e), + i = r.getQuery(); + if (!i) return; + var s = !n.forward; + return (s = r.isReversed() ? !s : s), Dn(e, i), Pn(e, s, i, n.repeat); + }, + goToMark: function (e, t, n, r) { + var i = Fn(e, r, n.selectedCharacter); + return i ? (n.linewise ? { line: i.line, ch: Qt(e.getLine(i.line)) } : i) : null; + }, + moveToOtherHighlightedEnd: function (e, t, n, r) { + if (r.visualBlock && n.sameLine) { + var i = r.sel; + return [wt(e, E(i.anchor.line, i.head.ch)), wt(e, E(i.head.line, i.anchor.ch))]; + } + return [r.sel.head, r.sel.anchor]; + }, + jumpToMark: function (e, t, n, r) { + var i = t; + for (var s = 0; s < n.repeat; s++) { + var o = i; + for (var u in r.marks) { + if (!U(u)) continue; + var a = r.marks[u].find(), + f = n.forward ? Ot(a, o) : Ot(o, a); + if (f) continue; + if (n.linewise && a.line == o.line) continue; + var l = At(o, i), + c = n.forward ? Dt(o, a, i) : Dt(i, a, o); + if (l || c) i = a; + } + } + return n.linewise && (i = E(i.line, Qt(e.getLine(i.line)))), i; + }, + moveByCharacters: function (e, t, n) { + var r = t, + i = n.repeat, + s = n.forward ? r.ch + i : r.ch - i; + return E(r.line, s); + }, + moveByLines: function (e, t, n, r) { + var i = t, + s = i.ch; + switch (r.lastMotion) { + case this.moveByLines: + case this.moveByDisplayLines: + case this.moveByScroll: + case this.moveToColumn: + case this.moveToEol: + s = r.lastHPos; + break; + default: + r.lastHPos = s; + } + var o = n.repeat + (n.repeatOffset || 0), + u = n.forward ? i.line + o : i.line - o, + a = e.firstLine(), + f = e.lastLine(); + if (u < a && i.line == a) return this.moveToStartOfLine(e, t, n, r); + if (u > f && i.line == f) return this.moveToEol(e, t, n, r); + var l = e.ace.session.getFoldLine(u); + return ( + l && (n.forward ? u > l.start.row && (u = l.end.row + 1) : (u = l.start.row)), + n.toFirstChar && ((s = Qt(e.getLine(u))), (r.lastHPos = s)), + (r.lastHSPos = e.charCoords(E(u, s), "div").left), + E(u, s) + ); + }, + moveByDisplayLines: function (e, t, n, r) { + var i = t; + switch (r.lastMotion) { + case this.moveByDisplayLines: + case this.moveByScroll: + case this.moveByLines: + case this.moveToColumn: + case this.moveToEol: + break; + default: + r.lastHSPos = e.charCoords(i, "div").left; + } + var s = n.repeat, + o = e.findPosV(i, n.forward ? s : -s, "line", r.lastHSPos); + if (o.hitSide) + if (n.forward) + var u = e.charCoords(o, "div"), + a = { top: u.top + 8, left: r.lastHSPos }, + o = e.coordsChar(a, "div"); + else { + var f = e.charCoords(E(e.firstLine(), 0), "div"); + (f.left = r.lastHSPos), (o = e.coordsChar(f, "div")); + } + return (r.lastHPos = o.ch), o; + }, + moveByPage: function (e, t, n) { + var r = t, + i = n.repeat; + return e.findPosV(r, n.forward ? i : -i, "page"); + }, + moveByParagraph: function (e, t, n) { + var r = n.forward ? 1 : -1; + return ln(e, t, n.repeat, r); + }, + moveByScroll: function (e, t, n, r) { + var i = e.getScrollInfo(), + s = null, + o = n.repeat; + o || (o = i.clientHeight / (2 * e.defaultTextHeight())); + var u = e.charCoords(t, "local"); + n.repeat = o; + var s = pt.moveByDisplayLines(e, t, n, r); + if (!s) return null; + var a = e.charCoords(s, "local"); + return e.scrollTo(null, i.top + a.top - u.top), s; + }, + moveByWords: function (e, t, n) { + return sn(e, t, n.repeat, !!n.forward, !!n.wordEnd, !!n.bigWord); + }, + moveTillCharacter: function (e, t, n) { + var r = n.repeat, + i = on(e, r, n.forward, n.selectedCharacter), + s = n.forward ? -1 : 1; + return Zt(s, n), i ? ((i.ch += s), i) : null; + }, + moveToCharacter: function (e, t, n) { + var r = n.repeat; + return Zt(0, n), on(e, r, n.forward, n.selectedCharacter) || t; + }, + moveToSymbol: function (e, t, n) { + var r = n.repeat; + return nn(e, r, n.forward, n.selectedCharacter) || t; + }, + moveToColumn: function (e, t, n, r) { + var i = n.repeat; + return (r.lastHPos = i - 1), (r.lastHSPos = e.charCoords(t, "div").left), un(e, i); + }, + moveToEol: function (e, t, n, r) { + var i = t; + r.lastHPos = Infinity; + var s = E(i.line + n.repeat - 1, Infinity), + o = e.clipPos(s); + return o.ch--, (r.lastHSPos = e.charCoords(o, "div").left), s; + }, + moveToFirstNonWhiteSpaceCharacter: function (e, t) { + var n = t; + return E(n.line, Qt(e.getLine(n.line))); + }, + moveToMatchedSymbol: function (e, t) { + var n = t, + r = n.line, + i = n.ch, + s = e.getLine(r), + o; + do { + o = s.charAt(i++); + if (o && z(o)) { + var u = e.getTokenTypeAt(E(r, i)); + if (u !== "string" && u !== "comment") break; + } + } while (o); + if (o) { + var a = e.findMatchingBracket(E(r, i)); + return a.to; + } + return n; + }, + moveToStartOfLine: function (e, t) { + return E(t.line, 0); + }, + moveToLineOrEdgeOfDocument: function (e, t, n) { + var r = n.forward ? e.lastLine() : e.firstLine(); + return ( + n.repeatIsExplicit && (r = n.repeat - e.getOption("firstLineNumber")), + E(r, Qt(e.getLine(r))) + ); + }, + textObjectManipulation: function (e, t, n, r) { + var i = { "(": ")", ")": "(", "{": "}", "}": "{", "[": "]", "]": "[" }, + s = { "'": !0, '"': !0 }, + o = n.selectedCharacter; + o == "b" ? (o = "(") : o == "B" && (o = "{"); + var u = !n.textObjectInner, + a; + if (i[o]) a = cn(e, t, o, u); + else if (s[o]) a = hn(e, t, o, u); + else if (o === "W") a = Gt(e, u, !0, !0); + else if (o === "w") a = Gt(e, u, !0, !1); + else { + if (o !== "p") return null; + (a = ln(e, t, n.repeat, 0, u)), (n.linewise = !0); + if (r.visualMode) r.visualLine || (r.visualLine = !0); + else { + var f = r.inputState.operatorArgs; + f && (f.linewise = !0), a.end.line--; + } + } + return e.state.vim.visualMode ? zt(e, a.start, a.end) : [a.start, a.end]; + }, + repeatLastCharacterSearch: function (e, t, n) { + var r = nt.lastCharacterSearch, + i = n.repeat, + s = n.forward === r.forward, + o = (r.increment ? 1 : 0) * (s ? -1 : 1); + e.moveH(-o, "char"), (n.inclusive = s ? !0 : !1); + var u = on(e, i, s, r.selectedCharacter); + return u ? ((u.ch += o), u) : (e.moveH(o, "char"), t); + }, + }, + mt = { + change: function (e, t, n) { + var r, + i, + s = e.state.vim; + nt.macroModeState.lastInsertModeChanges.inVisualBlock = s.visualBlock; + if (!s.visualMode) { + var o = n[0].anchor, + u = n[0].head; + i = e.getRange(o, u); + var a = s.lastEditInputState || {}; + if (a.motion == "moveByWords" && !V(i)) { + var f = /\s+$/.exec(i); + f && + a.motionArgs && + a.motionArgs.forward && + ((u = St(u, 0, -f[0].length)), (i = i.slice(0, -f[0].length))); + } + var l = new E(o.line - 1, Number.MAX_VALUE), + c = e.firstLine() == e.lastLine(); + u.line > e.lastLine() && t.linewise && !c + ? e.replaceRange("", l, u) + : e.replaceRange("", o, u), + t.linewise && + (c || (e.setCursor(l), v.commands.newlineAndIndent(e)), + (o.ch = Number.MAX_VALUE)), + (r = o); + } else { + i = e.getSelection(); + var h = vt("", n.length); + e.replaceSelections(h), (r = Mt(n[0].head, n[0].anchor)); + } + nt.registerController.pushText( + t.registerName, + "change", + i, + t.linewise, + n.length > 1, + ), + yt.enterInsertMode(e, { head: r }, e.state.vim); + }, + delete: function (e, t, n) { + var r, + i, + s = e.state.vim; + if (!s.visualBlock) { + var o = n[0].anchor, + u = n[0].head; + t.linewise && + u.line != e.firstLine() && + o.line == e.lastLine() && + o.line == u.line - 1 && + (o.line == e.firstLine() + ? (o.ch = 0) + : (o = E(o.line - 1, Pt(e, o.line - 1)))), + (i = e.getRange(o, u)), + e.replaceRange("", o, u), + (r = o), + t.linewise && (r = pt.moveToFirstNonWhiteSpaceCharacter(e, o)); + } else { + i = e.getSelection(); + var a = vt("", n.length); + e.replaceSelections(a), (r = n[0].anchor); + } + nt.registerController.pushText( + t.registerName, + "delete", + i, + t.linewise, + s.visualBlock, + ); + var f = s.insertMode; + return wt(e, r, f); + }, + indent: function (e, t, n) { + var r = e.state.vim, + i = n[0].anchor.line, + s = r.visualBlock ? n[n.length - 1].anchor.line : n[0].head.line, + o = r.visualMode ? t.repeat : 1; + t.linewise && s--; + for (var u = i; u <= s; u++) + for (var a = 0; a < o; a++) e.indentLine(u, t.indentRight); + return pt.moveToFirstNonWhiteSpaceCharacter(e, n[0].anchor); + }, + changeCase: function (e, t, n, r, i) { + var s = e.getSelections(), + o = [], + u = t.toLower; + for (var a = 0; a < s.length; a++) { + var f = s[a], + l = ""; + if (u === !0) l = f.toLowerCase(); + else if (u === !1) l = f.toUpperCase(); + else + for (var c = 0; c < f.length; c++) { + var h = f.charAt(c); + l += X(h) ? h.toLowerCase() : h.toUpperCase(); + } + o.push(l); + } + return ( + e.replaceSelections(o), + t.shouldMoveCursor + ? i + : !e.state.vim.visualMode && + t.linewise && + n[0].anchor.line + 1 == n[0].head.line + ? pt.moveToFirstNonWhiteSpaceCharacter(e, r) + : t.linewise + ? r + : Mt(n[0].anchor, n[0].head) + ); + }, + yank: function (e, t, n, r) { + var i = e.state.vim, + s = e.getSelection(), + o = i.visualMode ? Mt(i.sel.anchor, i.sel.head, n[0].head, n[0].anchor) : r; + return ( + nt.registerController.pushText( + t.registerName, + "yank", + s, + t.linewise, + i.visualBlock, + ), + o + ); + }, + }, + yt = { + jumpListWalk: function (e, t, n) { + if (n.visualMode) return; + var r = t.repeat, + i = t.forward, + s = nt.jumpList, + o = s.move(e, i ? r : -r), + u = o ? o.find() : undefined; + (u = u ? u : e.getCursor()), + e.setCursor(u), + (e.ace.curOp.command.scrollIntoView = "center-animate"); + }, + scroll: function (e, t, n) { + if (n.visualMode) return; + var r = t.repeat || 1, + i = e.defaultTextHeight(), + s = e.getScrollInfo().top, + o = i * r, + u = t.forward ? s + o : s - o, + a = Lt(e.getCursor()), + f = e.charCoords(a, "local"); + if (t.forward) + u > f.top + ? ((a.line += (u - f.top) / i), + (a.line = Math.ceil(a.line)), + e.setCursor(a), + (f = e.charCoords(a, "local")), + e.scrollTo(null, f.top)) + : e.scrollTo(null, u); + else { + var l = u + e.getScrollInfo().clientHeight; + l < f.bottom + ? ((a.line -= (f.bottom - l) / i), + (a.line = Math.floor(a.line)), + e.setCursor(a), + (f = e.charCoords(a, "local")), + e.scrollTo(null, f.bottom - e.getScrollInfo().clientHeight)) + : e.scrollTo(null, u); + } + }, + scrollToCursor: function (e, t) { + var n = e.getCursor().line, + r = e.charCoords(E(n, 0), "local"), + i = e.getScrollInfo().clientHeight, + s = r.top, + o = r.bottom - s; + switch (t.position) { + case "center": + s = s - i / 2 + o; + break; + case "bottom": + s = s - i + o * 1.4; + break; + case "top": + s += o * 0.4; + } + e.scrollTo(null, s); + }, + replayMacro: function (e, t, n) { + var r = t.selectedCharacter, + i = t.repeat, + s = nt.macroModeState; + r == "@" && (r = s.latestRegister); + while (i--) Vn(e, n, s, r); + }, + enterMacroRecordMode: function (e, t) { + var n = nt.macroModeState, + r = t.selectedCharacter; + nt.registerController.isValidRegister(r) && n.enterMacroRecordMode(e, r); + }, + toggleOverwrite: function (e) { + e.state.overwrite + ? (e.toggleOverwrite(!1), + e.setOption("keyMap", "vim-insert"), + v.signal(e, "vim-mode-change", { mode: "insert" })) + : (e.toggleOverwrite(!0), + e.setOption("keyMap", "vim-replace"), + v.signal(e, "vim-mode-change", { mode: "replace" })); + }, + enterInsertMode: function (e, t, n) { + if (e.getOption("readOnly")) return; + (n.insertMode = !0), (n.insertModeRepeat = (t && t.repeat) || 1); + var r = t ? t.insertAt : null, + i = n.sel, + s = t.head || e.getCursor("head"), + o = e.listSelections().length; + if (r == "eol") s = E(s.line, Pt(e, s.line)); + else if (r == "charAfter") s = St(s, 0, 1); + else if (r == "firstNonBlank") s = pt.moveToFirstNonWhiteSpaceCharacter(e, s); + else if (r == "startOfSelectedArea") + n.visualBlock + ? ((s = E( + Math.min(i.head.line, i.anchor.line), + Math.min(i.head.ch, i.anchor.ch), + )), + (o = Math.abs(i.head.line - i.anchor.line) + 1)) + : i.head.line < i.anchor.line + ? (s = i.head) + : (s = E(i.anchor.line, 0)); + else if (r == "endOfSelectedArea") + n.visualBlock + ? ((s = E( + Math.min(i.head.line, i.anchor.line), + Math.max(i.head.ch + 1, i.anchor.ch), + )), + (o = Math.abs(i.head.line - i.anchor.line) + 1)) + : i.head.line >= i.anchor.line + ? (s = St(i.head, 0, 1)) + : (s = E(i.anchor.line, 0)); + else if (r == "inplace" && n.visualMode) return; + e.setOption("disableInput", !1), + t && t.replace + ? (e.toggleOverwrite(!0), + e.setOption("keyMap", "vim-replace"), + v.signal(e, "vim-mode-change", { mode: "replace" })) + : (e.toggleOverwrite(!1), + e.setOption("keyMap", "vim-insert"), + v.signal(e, "vim-mode-change", { mode: "insert" })), + nt.macroModeState.isPlaying || + (e.on("change", Qn), v.on(e.getInputField(), "keydown", tr)), + n.visualMode && $t(e), + It(e, s, o); + }, + toggleVisualMode: function (e, t, n) { + var r = t.repeat, + i = e.getCursor(), + s; + n.visualMode + ? n.visualLine ^ t.linewise || n.visualBlock ^ t.blockwise + ? ((n.visualLine = !!t.linewise), + (n.visualBlock = !!t.blockwise), + v.signal(e, "vim-mode-change", { + mode: "visual", + subMode: n.visualLine ? "linewise" : n.visualBlock ? "blockwise" : "", + }), + Wt(e)) + : $t(e) + : ((n.visualMode = !0), + (n.visualLine = !!t.linewise), + (n.visualBlock = !!t.blockwise), + (s = wt(e, E(i.line, i.ch + r - 1), !0)), + (n.sel = { anchor: i, head: s }), + v.signal(e, "vim-mode-change", { + mode: "visual", + subMode: n.visualLine ? "linewise" : n.visualBlock ? "blockwise" : "", + }), + Wt(e), + an(e, n, "<", Mt(i, s)), + an(e, n, ">", _t(i, s))); + }, + reselectLastSelection: function (e, t, n) { + var r = n.lastSelection; + n.visualMode && Ut(e, n); + if (r) { + var i = r.anchorMark.find(), + s = r.headMark.find(); + if (!i || !s) return; + (n.sel = { anchor: i, head: s }), + (n.visualMode = !0), + (n.visualLine = r.visualLine), + (n.visualBlock = r.visualBlock), + Wt(e), + an(e, n, "<", Mt(i, s)), + an(e, n, ">", _t(i, s)), + v.signal(e, "vim-mode-change", { + mode: "visual", + subMode: n.visualLine ? "linewise" : n.visualBlock ? "blockwise" : "", + }); + } + }, + joinLines: function (e, t, n) { + var r, i; + if (n.visualMode) { + (r = e.getCursor("anchor")), (i = e.getCursor("head")); + if (Ot(i, r)) { + var s = i; + (i = r), (r = s); + } + i.ch = Pt(e, i.line) - 1; + } else { + var o = Math.max(t.repeat, 2); + (r = e.getCursor()), (i = wt(e, E(r.line + o - 1, Infinity))); + } + var u = 0; + for (var a = r.line; a < i.line; a++) { + u = Pt(e, r.line); + var s = E(r.line + 1, Pt(e, r.line + 1)), + f = e.getRange(r, s); + (f = f.replace(/\n\s*/g, " ")), e.replaceRange(f, r, s); + } + var l = E(r.line, u); + n.visualMode && $t(e, !1), e.setCursor(l); + }, + newLineAndEnterInsertMode: function (e, t, n) { + n.insertMode = !0; + var r = Lt(e.getCursor()); + if (r.line === e.firstLine() && !t.after) + e.replaceRange("\n", E(e.firstLine(), 0)), e.setCursor(e.firstLine(), 0); + else { + (r.line = t.after ? r.line : r.line - 1), + (r.ch = Pt(e, r.line)), + e.setCursor(r); + var i = + v.commands.newlineAndIndentContinueComment || v.commands.newlineAndIndent; + i(e); + } + this.enterInsertMode(e, { repeat: t.repeat }, n); + }, + paste: function (e, t, n) { + var r = Lt(e.getCursor()), + i = nt.registerController.getRegister(t.registerName), + s = i.toString(); + if (!s) return; + if (t.matchIndent) { + var o = e.getOption("tabSize"), + u = function (e) { + var t = e.split(" ").length - 1, + n = e.split(" ").length - 1; + return t * o + n * 1; + }, + a = e.getLine(e.getCursor().line), + f = u(a.match(/^\s*/)[0]), + l = s.replace(/\n$/, ""), + c = s !== l, + h = u(s.match(/^\s*/)[0]), + s = l.replace(/^\s*/gm, function (t) { + var n = f + (u(t) - h); + if (n < 0) return ""; + if (e.getOption("indentWithTabs")) { + var r = Math.floor(n / o); + return Array(r + 1).join(" "); + } + return Array(n + 1).join(" "); + }); + s += c ? "\n" : ""; + } + if (t.repeat > 1) var s = Array(t.repeat + 1).join(s); + var p = i.linewise, + d = i.blockwise; + if (p && !d) + n.visualMode + ? (s = n.visualLine + ? s.slice(0, -1) + : "\n" + s.slice(0, s.length - 1) + "\n") + : t.after + ? ((s = "\n" + s.slice(0, s.length - 1)), (r.ch = Pt(e, r.line))) + : (r.ch = 0); + else { + if (d) { + s = s.split("\n"); + for (var v = 0; v < s.length; v++) s[v] = s[v] == "" ? " " : s[v]; + } + r.ch += t.after ? 1 : 0; + } + var m, g; + if (n.visualMode) { + n.lastPastedText = s; + var y, + b = Rt(e, n), + w = b[0], + S = b[1], + x = e.getSelection(), + T = e.listSelections(), + N = new Array(T.length).join("1").split("1"); + n.lastSelection && (y = n.lastSelection.headMark.find()), + nt.registerController.unnamedRegister.setText(x), + d + ? (e.replaceSelections(N), + (S = E(w.line + s.length - 1, w.ch)), + e.setCursor(w), + Ft(e, S), + e.replaceSelections(s), + (m = w)) + : n.visualBlock + ? (e.replaceSelections(N), + e.setCursor(w), + e.replaceRange(s, w, w), + (m = w)) + : (e.replaceRange(s, w, S), + (m = e.posFromIndex(e.indexFromPos(w) + s.length - 1))), + y && (n.lastSelection.headMark = e.setBookmark(y)), + p && (m.ch = 0); + } else if (d) { + e.setCursor(r); + for (var v = 0; v < s.length; v++) { + var C = r.line + v; + C > e.lastLine() && e.replaceRange("\n", E(C, 0)); + var k = Pt(e, C); + k < r.ch && jt(e, C, r.ch); + } + e.setCursor(r), + Ft(e, E(r.line + s.length - 1, r.ch)), + e.replaceSelections(s), + (m = r); + } else + e.replaceRange(s, r), + p && t.after + ? (m = E(r.line + 1, Qt(e.getLine(r.line + 1)))) + : p && !t.after + ? (m = E(r.line, Qt(e.getLine(r.line)))) + : !p && t.after + ? ((g = e.indexFromPos(r)), (m = e.posFromIndex(g + s.length - 1))) + : ((g = e.indexFromPos(r)), (m = e.posFromIndex(g + s.length))); + n.visualMode && $t(e, !1), e.setCursor(m); + }, + undo: function (e, t) { + e.operation(function () { + kt(e, v.commands.undo, t.repeat)(), e.setCursor(e.getCursor("anchor")); + }); + }, + redo: function (e, t) { + kt(e, v.commands.redo, t.repeat)(); + }, + setRegister: function (e, t, n) { + n.inputState.registerName = t.selectedCharacter; + }, + setMark: function (e, t, n) { + var r = t.selectedCharacter; + an(e, n, r, e.getCursor()); + }, + replace: function (e, t, n) { + var r = t.selectedCharacter, + i = e.getCursor(), + s, + o, + u = e.listSelections(); + if (n.visualMode) (i = e.getCursor("start")), (o = e.getCursor("end")); + else { + var a = e.getLine(i.line); + (s = i.ch + t.repeat), s > a.length && (s = a.length), (o = E(i.line, s)); + } + if (r == "\n") + n.visualMode || e.replaceRange("", i, o), + (v.commands.newlineAndIndentContinueComment || v.commands.newlineAndIndent)( + e, + ); + else { + var f = e.getRange(i, o); + f = f.replace(/[^\n]/g, r); + if (n.visualBlock) { + var l = new Array(e.getOption("tabSize") + 1).join(" "); + (f = e.getSelection()), + (f = f.replace(/\t/g, l).replace(/[^\n]/g, r).split("\n")), + e.replaceSelections(f); + } else e.replaceRange(f, i, o); + n.visualMode + ? ((i = Ot(u[0].anchor, u[0].head) ? u[0].anchor : u[0].head), + e.setCursor(i), + $t(e, !1)) + : e.setCursor(St(o, 0, -1)); + } + }, + incrementNumberToken: function (e, t) { + var n = e.getCursor(), + r = e.getLine(n.line), + i = /(-?)(?:(0x)([\da-f]+)|(0b|0|)(\d+))/gi, + s, + o, + u, + a; + while ((s = i.exec(r)) !== null) { + (o = s.index), (u = o + s[0].length); + if (n.ch < u) break; + } + if (!t.backtrack && u <= n.ch) return; + if (!s) return; + var f = s[2] || s[4], + l = s[3] || s[5], + c = t.increase ? 1 : -1, + h = { "0b": 2, 0: 8, "": 10, "0x": 16 }[f.toLowerCase()], + p = parseInt(s[1] + l, h) + c * t.repeat; + a = p.toString(h); + var d = f ? new Array(l.length - a.length + 1 + s[1].length).join("0") : ""; + a.charAt(0) === "-" ? (a = "-" + f + d + a.substr(1)) : (a = f + d + a); + var v = E(n.line, o), + m = E(n.line, u); + e.replaceRange(a, v, m), e.setCursor(E(n.line, o + a.length - 1)); + }, + repeatLastEdit: function (e, t, n) { + var r = n.lastEditInputState; + if (!r) return; + var i = t.repeat; + i && t.repeatIsExplicit + ? (n.lastEditInputState.repeatOverride = i) + : (i = n.lastEditInputState.repeatOverride || i), + nr(e, n, i, !1); + }, + indent: function (e, t) { + e.indentLine(e.getCursor().line, t.indentRight); + }, + exitInsertMode: zn, + }, + en = { + "(": "bracket", + ")": "bracket", + "{": "bracket", + "}": "bracket", + "[": "section", + "]": "section", + "*": "comment", + "/": "comment", + m: "method", + M: "method", + "#": "preprocess", + }, + tn = { + bracket: { + isComplete: function (e) { + if (e.nextCh === e.symb) { + e.depth++; + if (e.depth >= 1) return !0; + } else e.nextCh === e.reverseSymb && e.depth--; + return !1; + }, + }, + section: { + init: function (e) { + (e.curMoveThrough = !0), + (e.symb = (e.forward ? "]" : "[") === e.symb ? "{" : "}"); + }, + isComplete: function (e) { + return e.index === 0 && e.nextCh === e.symb; + }, + }, + comment: { + isComplete: function (e) { + var t = e.lastCh === "*" && e.nextCh === "/"; + return (e.lastCh = e.nextCh), t; + }, + }, + method: { + init: function (e) { + (e.symb = e.symb === "m" ? "{" : "}"), + (e.reverseSymb = e.symb === "{" ? "}" : "{"); + }, + isComplete: function (e) { + return e.nextCh === e.symb ? !0 : !1; + }, + }, + preprocess: { + init: function (e) { + e.index = 0; + }, + isComplete: function (e) { + if (e.nextCh === "#") { + var t = e.lineText.match(/#(\w+)/)[1]; + if (t === "endif") { + if (e.forward && e.depth === 0) return !0; + e.depth++; + } else if (t === "if") { + if (!e.forward && e.depth === 0) return !0; + e.depth--; + } + if (t === "else" && e.depth === 0) return !0; + } + return !1; + }, + }, + }; + K("pcre", !0, "boolean"), + (pn.prototype = { + getQuery: function () { + return nt.query; + }, + setQuery: function (e) { + nt.query = e; + }, + getOverlay: function () { + return this.searchOverlay; + }, + setOverlay: function (e) { + this.searchOverlay = e; + }, + isReversed: function () { + return nt.isReversed; + }, + setReversed: function (e) { + nt.isReversed = e; + }, + getScrollbarAnnotate: function () { + return this.annotate; + }, + setScrollbarAnnotate: function (e) { + this.annotate = e; + }, + }); + var En = { "\\n": "\n", "\\r": "\r", "\\t": " " }, + xn = { "\\/": "/", "\\\\": "\\", "\\n": "\n", "\\r": "\r", "\\t": " " }, + Ln = "(Javascript regexp)", + In = function () { + this.buildCommandMap_(); + }; + In.prototype = { + processCommand: function (e, t, n) { + var r = this; + e.operation(function () { + (e.curOp.isVimOp = !0), r._processCommand(e, t, n); + }); + }, + _processCommand: function (e, t, n) { + var r = e.state.vim, + i = nt.registerController.getRegister(":"), + s = i.toString(); + r.visualMode && $t(e); + var o = new v.StringStream(t); + i.setText(t); + var u = n || {}; + u.input = t; + try { + this.parseInput_(e, o, u); + } catch (a) { + throw (Cn(e, a), a); + } + var f, l; + if (!u.commandName) u.line !== undefined && (l = "move"); + else { + f = this.matchCommand_(u.commandName); + if (f) { + (l = f.name), + f.excludeFromCommandHistory && i.setText(s), + this.parseCommandArgs_(o, u, f); + if (f.type == "exToKey") { + for (var c = 0; c < f.toKeys.length; c++) + v.Vim.handleKey(e, f.toKeys[c], "mapping"); + return; + } + if (f.type == "exToEx") { + this.processCommand(e, f.toInput); + return; + } + } + } + if (!l) { + Cn(e, 'Not an editor command ":' + t + '"'); + return; + } + try { + qn[l](e, u), (!f || !f.possiblyAsync) && u.callback && u.callback(); + } catch (a) { + throw (Cn(e, a), a); + } + }, + parseInput_: function (e, t, n) { + t.eatWhile(":"), + t.eat("%") + ? ((n.line = e.firstLine()), (n.lineEnd = e.lastLine())) + : ((n.line = this.parseLineSpec_(e, t)), + n.line !== undefined && + t.eat(",") && + (n.lineEnd = this.parseLineSpec_(e, t))); + var r = t.match(/^(\w+)/); + return r ? (n.commandName = r[1]) : (n.commandName = t.match(/.*/)[0]), n; + }, + parseLineSpec_: function (e, t) { + var n = t.match(/^(\d+)/); + if (n) return parseInt(n[1], 10) - 1; + switch (t.next()) { + case ".": + return this.parseLineSpecOffset_(t, e.getCursor().line); + case "$": + return this.parseLineSpecOffset_(t, e.lastLine()); + case "'": + var r = t.next(), + i = Fn(e, e.state.vim, r); + if (!i) throw new Error("Mark not set"); + return this.parseLineSpecOffset_(t, i.line); + case "-": + case "+": + return t.backUp(1), this.parseLineSpecOffset_(t, e.getCursor().line); + default: + return t.backUp(1), undefined; + } + }, + parseLineSpecOffset_: function (e, t) { + var n = e.match(/^([+-])?(\d+)/); + if (n) { + var r = parseInt(n[2], 10); + n[1] == "-" ? (t -= r) : (t += r); + } + return t; + }, + parseCommandArgs_: function (e, t, n) { + if (e.eol()) return; + t.argString = e.match(/.*/)[0]; + var r = n.argDelimiter || /\s+/, + i = Ht(t.argString).split(r); + i.length && i[0] && (t.args = i); + }, + matchCommand_: function (e) { + for (var t = e.length; t > 0; t--) { + var n = e.substring(0, t); + if (this.commandMap_[n]) { + var r = this.commandMap_[n]; + if (r.name.indexOf(e) === 0) return r; + } + } + return null; + }, + buildCommandMap_: function () { + this.commandMap_ = {}; + for (var e = 0; e < w.length; e++) { + var t = w[e], + n = t.shortName || t.name; + this.commandMap_[n] = t; + } + }, + map: function (e, t, n) { + if (e != ":" && e.charAt(0) == ":") { + if (n) throw Error("Mode not supported for ex mappings"); + var r = e.substring(1); + t != ":" && t.charAt(0) == ":" + ? (this.commandMap_[r] = { + name: r, + type: "exToEx", + toInput: t.substring(1), + user: !0, + }) + : (this.commandMap_[r] = { name: r, type: "exToKey", toKeys: t, user: !0 }); + } else if (t != ":" && t.charAt(0) == ":") { + var i = { keys: e, type: "keyToEx", exArgs: { input: t.substring(1) } }; + n && (i.context = n), b.unshift(i); + } else { + var i = { keys: e, type: "keyToKey", toKeys: t }; + n && (i.context = n), b.unshift(i); + } + }, + unmap: function (e, t) { + if (e != ":" && e.charAt(0) == ":") { + if (t) throw Error("Mode not supported for ex mappings"); + var n = e.substring(1); + if (this.commandMap_[n] && this.commandMap_[n].user) { + delete this.commandMap_[n]; + return; + } + } else { + var r = e; + for (var i = 0; i < b.length; i++) + if (r == b[i].keys && b[i].context === t) { + b.splice(i, 1); + return; + } + } + }, + }; + var qn = { + colorscheme: function (e, t) { + if (!t.args || t.args.length < 1) { + Cn(e, e.getOption("theme")); + return; + } + e.setOption("theme", t.args[0]); + }, + map: function (e, t, n) { + var r = t.args; + if (!r || r.length < 2) { + e && Cn(e, "Invalid mapping: " + t.input); + return; + } + Rn.map(r[0], r[1], n); + }, + imap: function (e, t) { + this.map(e, t, "insert"); + }, + nmap: function (e, t) { + this.map(e, t, "normal"); + }, + vmap: function (e, t) { + this.map(e, t, "visual"); + }, + unmap: function (e, t, n) { + var r = t.args; + if (!r || r.length < 1) { + e && Cn(e, "No such mapping: " + t.input); + return; + } + Rn.unmap(r[0], n); + }, + move: function (e, t) { + ht.processCommand(e, e.state.vim, { + type: "motion", + motion: "moveToLineOrEdgeOfDocument", + motionArgs: { forward: !1, explicitRepeat: !0, linewise: !0 }, + repeatOverride: t.line + 1, + }); + }, + set: function (e, t) { + var n = t.args, + r = t.setCfg || {}; + if (!n || n.length < 1) { + e && Cn(e, "Invalid mapping: " + t.input); + return; + } + var i = n[0].split("="), + s = i[0], + o = i[1], + u = !1; + if (s.charAt(s.length - 1) == "?") { + if (o) throw Error("Trailing characters: " + t.argString); + (s = s.substring(0, s.length - 1)), (u = !0); + } + o === undefined && s.substring(0, 2) == "no" && ((s = s.substring(2)), (o = !1)); + var a = J[s] && J[s].type == "boolean"; + a && o == undefined && (o = !0); + if ((!a && o === undefined) || u) { + var f = G(s, e, r); + f instanceof Error + ? Cn(e, f.message) + : f === !0 || f === !1 + ? Cn(e, " " + (f ? "" : "no") + s) + : Cn(e, " " + s + "=" + f); + } else { + var l = Q(s, o, e, r); + l instanceof Error && Cn(e, l.message); + } + }, + setlocal: function (e, t) { + (t.setCfg = { scope: "local" }), this.set(e, t); + }, + setglobal: function (e, t) { + (t.setCfg = { scope: "global" }), this.set(e, t); + }, + registers: function (e, t) { + var n = t.args, + r = nt.registerController.registers, + i = "----------Registers----------

"; + if (!n) + for (var s in r) { + var o = r[s].toString(); + o.length && (i += '"' + s + " " + o + "
"); + } + else { + var s; + n = n.join(""); + for (var u = 0; u < n.length; u++) { + s = n.charAt(u); + if (!nt.registerController.isValidRegister(s)) continue; + var a = r[s] || new at(); + i += '"' + s + " " + a.toString() + "
"; + } + } + Cn(e, i); + }, + sort: function (e, t) { + function u() { + if (t.argString) { + var e = new v.StringStream(t.argString); + e.eat("!") && (n = !0); + if (e.eol()) return; + if (!e.eatSpace()) return "Invalid arguments"; + var u = e.match(/([dinuox]+)?\s*(\/.+\/)?\s*/); + if (!u && !e.eol()) return "Invalid arguments"; + if (u[1]) { + (r = u[1].indexOf("i") != -1), (i = u[1].indexOf("u") != -1); + var a = u[1].indexOf("d") != -1 || (u[1].indexOf("n") != -1 && 1), + f = u[1].indexOf("x") != -1 && 1, + l = u[1].indexOf("o") != -1 && 1; + if (a + f + l > 1) return "Invalid arguments"; + s = (a && "decimal") || (f && "hex") || (l && "octal"); + } + u[2] && (o = new RegExp(u[2].substr(1, u[2].length - 2), r ? "i" : "")); + } + } + function S(e, t) { + if (n) { + var i; + (i = e), (e = t), (t = i); + } + r && ((e = e.toLowerCase()), (t = t.toLowerCase())); + var o = s && d.exec(e), + u = s && d.exec(t); + return o + ? ((o = parseInt((o[1] + o[2]).toLowerCase(), m)), + (u = parseInt((u[1] + u[2]).toLowerCase(), m)), + o - u) + : e < t + ? -1 + : 1; + } + function x(e, t) { + if (n) { + var i; + (i = e), (e = t), (t = i); + } + return ( + r && ((e[0] = e[0].toLowerCase()), (t[0] = t[0].toLowerCase())), + e[0] < t[0] ? -1 : 1 + ); + } + var n, + r, + i, + s, + o, + a = u(); + if (a) { + Cn(e, a + ": " + t.argString); + return; + } + var f = t.line || e.firstLine(), + l = t.lineEnd || t.line || e.lastLine(); + if (f == l) return; + var c = E(f, 0), + h = E(l, Pt(e, l)), + p = e.getRange(c, h).split("\n"), + d = o + ? o + : s == "decimal" + ? /(-?)([\d]+)/ + : s == "hex" + ? /(-?)(?:0x)?([0-9a-f]+)/i + : s == "octal" + ? /([0-7]+)/ + : null, + m = s == "decimal" ? 10 : s == "hex" ? 16 : s == "octal" ? 8 : null, + g = [], + y = []; + if (s || o) + for (var b = 0; b < p.length; b++) { + var w = o ? p[b].match(o) : null; + w && w[0] != "" + ? g.push(w) + : !o && d.exec(p[b]) + ? g.push(p[b]) + : y.push(p[b]); + } + else y = p; + g.sort(o ? x : S); + if (o) for (var b = 0; b < g.length; b++) g[b] = g[b].input; + else s || y.sort(S); + p = n ? g.concat(y) : y.concat(g); + if (i) { + var T = p, + N; + p = []; + for (var b = 0; b < T.length; b++) T[b] != N && p.push(T[b]), (N = T[b]); + } + e.replaceRange(p.join("\n"), c, h); + }, + global: function (e, t) { + var n = t.argString; + if (!n) { + Cn(e, "Regular Expression missing from global"); + return; + } + var r = t.line !== undefined ? t.line : e.firstLine(), + i = t.lineEnd || t.line || e.lastLine(), + s = mn(n), + o = n, + u; + s.length && ((o = s[0]), (u = s.slice(1, s.length).join("/"))); + if (o) + try { + Mn(e, o, !0, !0); + } catch (a) { + Cn(e, "Invalid regex: " + o); + return; + } + var f = dn(e).getQuery(), + l = [], + c = ""; + for (var h = r; h <= i; h++) { + var p = f.test(e.getLine(h)); + p && (l.push(h + 1), (c += e.getLine(h) + "
")); + } + if (!u) { + Cn(e, c); + return; + } + var d = 0, + v = function () { + if (d < l.length) { + var t = l[d] + u; + Rn.processCommand(e, t, { callback: v }); + } + d++; + }; + v(); + }, + substitute: function (e, t) { + if (!e.getSearchCursor) + throw new Error( + "Search feature not available. Requires searchcursor.js or any other getSearchCursor implementation.", + ); + var n = t.argString, + r = n ? yn(n, n[0]) : [], + i, + s = "", + o, + u, + a, + f = !1, + l = !1; + if (r.length) + (i = r[0]), + (s = r[1]), + i && + i[i.length - 1] === "$" && + ((i = i.slice(0, i.length - 1) + "\\n"), (s = s ? s + "\n" : "\n")), + s !== undefined && + (G("pcre") ? (s = Tn(s)) : (s = Sn(s)), + (nt.lastSubstituteReplacePart = s)), + (o = r[2] ? r[2].split(" ") : []); + else if (n && n.length) { + Cn(e, "Substitutions should be of the form :s/pattern/replace/"); + return; + } + o && + ((u = o[0]), + (a = parseInt(o[1])), + u && + (u.indexOf("c") != -1 && ((f = !0), u.replace("c", "")), + u.indexOf("g") != -1 && ((l = !0), u.replace("g", "")), + (i = i.replace(/\//g, "\\/") + "/" + u))); + if (i) + try { + Mn(e, i, !0, !0); + } catch (c) { + Cn(e, "Invalid regex: " + i); + return; + } + s = s || nt.lastSubstituteReplacePart; + if (s === undefined) { + Cn(e, "No previous substitute regular expression"); + return; + } + var h = dn(e), + p = h.getQuery(), + d = t.line !== undefined ? t.line : e.getCursor().line, + v = t.lineEnd || d; + d == e.firstLine() && v == e.lastLine() && (v = Infinity), + a && ((d = v), (v = d + a - 1)); + var m = wt(e, E(d, 0)), + g = e.getSearchCursor(p, m); + Un(e, f, l, d, v, g, p, s, t.callback); + }, + redo: v.commands.redo, + undo: v.commands.undo, + write: function (e) { + v.commands.save ? v.commands.save(e) : e.save && e.save(); + }, + nohlsearch: function (e) { + Hn(e); + }, + yank: function (e) { + var t = Lt(e.getCursor()), + n = t.line, + r = e.getLine(n); + nt.registerController.pushText("0", "yank", r, !0, !0); + }, + delmarks: function (e, t) { + if (!t.argString || !Ht(t.argString)) { + Cn(e, "Argument required"); + return; + } + var n = e.state.vim, + r = new v.StringStream(Ht(t.argString)); + while (!r.eol()) { + r.eatSpace(); + var i = r.pos; + if (!r.match(/[a-zA-Z]/, !1)) { + Cn(e, "Invalid argument: " + t.argString.substring(i)); + return; + } + var s = r.next(); + if (r.match("-", !0)) { + if (!r.match(/[a-zA-Z]/, !1)) { + Cn(e, "Invalid argument: " + t.argString.substring(i)); + return; + } + var o = s, + u = r.next(); + if (!((U(o) && U(u)) || (X(o) && X(u)))) { + Cn(e, "Invalid argument: " + o + "-"); + return; + } + var a = o.charCodeAt(0), + f = u.charCodeAt(0); + if (a >= f) { + Cn(e, "Invalid argument: " + t.argString.substring(i)); + return; + } + for (var l = 0; l <= f - a; l++) { + var c = String.fromCharCode(a + l); + delete n.marks[c]; + } + } else delete n.marks[s]; + } + }, + }, + Rn = new In(); + (v.keyMap.vim = { attach: C, detach: N, call: k }), + K("insertModeEscKeysTimeout", 200, "number"), + (v.keyMap["vim-insert"] = { + "Ctrl-N": "autocomplete", + "Ctrl-P": "autocomplete", + Enter: function (e) { + var t = v.commands.newlineAndIndentContinueComment || v.commands.newlineAndIndent; + t(e); + }, + fallthrough: ["default"], + attach: C, + detach: N, + call: k, + }), + (v.keyMap["vim-replace"] = { + Backspace: "goCharLeft", + fallthrough: ["vim-insert"], + attach: C, + detach: N, + call: k, + }), + rt(), + (v.Vim = S()), + (S = v.Vim); + var ir = { + return: "CR", + backspace: "BS", + delete: "Del", + esc: "Esc", + left: "Left", + right: "Right", + up: "Up", + down: "Down", + space: "Space", + home: "Home", + end: "End", + pageup: "PageUp", + pagedown: "PageDown", + enter: "CR", + }, + or = S.handleKey.bind(S); + (S.handleKey = function (e, t, n) { + return e.operation(function () { + return or(e, t, n); + }, !0); + }), + (t.CodeMirror = v); + var fr = S.maybeInitVimState_; + (t.handler = { + $id: "ace/keyboard/vim", + drawCursor: function (e, t, n, r, s) { + var u = this.state.vim || {}, + a = n.characterWidth, + f = n.lineHeight, + l = t.top, + c = t.left; + if (!u.insertMode) { + var h = r.cursor + ? i.comparePoints(r.cursor, r.start) <= 0 + : s.selection.isBackwards() || s.selection.isEmpty(); + !h && c > a && (c -= a); + } + !u.insertMode && u.status && ((f /= 2), (l += f)), + o.translate(e, c, l), + o.setStyle(e.style, "width", a + "px"), + o.setStyle(e.style, "height", f + "px"); + }, + handleKeyboard: function (e, t, n, r, i) { + var s = e.editor, + o = s.state.cm, + u = fr(o); + if (r == -1) return; + u.insertMode || + (t == -1 + ? (n.charCodeAt(0) > 255 && + e.inputKey && + ((n = e.inputKey), n && e.inputHash == 4 && (n = n.toUpperCase())), + (e.inputChar = n)) + : t == 4 || t == 0 + ? e.inputKey == n && e.inputHash == t && e.inputChar + ? ((n = e.inputChar), (t = -1)) + : ((e.inputChar = null), (e.inputKey = n), (e.inputHash = t)) + : (e.inputChar = e.inputKey = null)); + if (n == "c" && t == 1 && !c.isMac && s.getCopyText()) + return ( + s.once("copy", function () { + s.selection.clearSelection(); + }), + { command: "null", passEvent: !0 } + ); + if (n == "esc" && !u.insertMode && !u.visualMode && !o.ace.inMultiSelectMode) { + var a = dn(o), + f = a.getOverlay(); + f && o.removeOverlay(f); + } + if (t == -1 || t & 1 || (t === 0 && n.length > 1)) { + var l = u.insertMode, + h = sr(t, n, i || {}); + u.status == null && (u.status = ""); + var p = ar(o, h, "user"); + (u = fr(o)), + p && u.status != null ? (u.status += h) : u.status == null && (u.status = ""), + o._signal("changeStatus"); + if (!p && (t != -1 || l)) return; + return { command: "null", passEvent: !p }; + } + }, + attach: function (e) { + function n() { + var n = fr(t).insertMode; + t.ace.renderer.setStyle("normal-mode", !n), + e.textInput.setCommandMode(!n), + (e.renderer.$keepTextAreaAtCursor = n), + (e.renderer.$blockCursor = !n); + } + e.state || (e.state = {}); + var t = new v(e); + (e.state.cm = t), + (e.$vimModeHandler = this), + v.keyMap.vim.attach(t), + (fr(t).status = null), + t.on("vim-command-done", function () { + if (t.virtualSelectionMode()) return; + (fr(t).status = null), + t.ace._signal("changeStatus"), + t.ace.session.markUndoGroup(); + }), + t.on("changeStatus", function () { + t.ace.renderer.updateCursor(), t.ace._signal("changeStatus"); + }), + t.on("vim-mode-change", function () { + if (t.virtualSelectionMode()) return; + n(), t._signal("changeStatus"); + }), + n(), + (e.renderer.$cursorLayer.drawCursor = this.drawCursor.bind(t)); + }, + detach: function (e) { + var t = e.state.cm; + v.keyMap.vim.detach(t), + t.destroy(), + (e.state.cm = null), + (e.$vimModeHandler = null), + (e.renderer.$cursorLayer.drawCursor = null), + e.renderer.setStyle("normal-mode", !1), + e.textInput.setCommandMode(!1), + (e.renderer.$keepTextAreaAtCursor = !0); + }, + getStatusText: function (e) { + var t = e.state.cm, + n = fr(t); + if (n.insertMode) return "INSERT"; + var r = ""; + return ( + n.visualMode && + ((r += "VISUAL"), + n.visualLine && (r += " LINE"), + n.visualBlock && (r += " BLOCK")), + n.status && (r += (r ? " " : "") + n.status), + r + ); + }, + }), + S.defineOption( + { + name: "wrap", + set: function (e, t) { + t && t.ace.setOption("wrap", e); + }, + type: "boolean", + }, + !1, + ), + S.defineEx("write", "w", function () { + console.log(":write is not implemented"); + }), + b.push( + { keys: "zc", type: "action", action: "fold", actionArgs: { open: !1 } }, + { keys: "zC", type: "action", action: "fold", actionArgs: { open: !1, all: !0 } }, + { keys: "zo", type: "action", action: "fold", actionArgs: { open: !0 } }, + { keys: "zO", type: "action", action: "fold", actionArgs: { open: !0, all: !0 } }, + { keys: "za", type: "action", action: "fold", actionArgs: { toggle: !0 } }, + { keys: "zA", type: "action", action: "fold", actionArgs: { toggle: !0, all: !0 } }, + { keys: "zf", type: "action", action: "fold", actionArgs: { open: !0, all: !0 } }, + { keys: "zd", type: "action", action: "fold", actionArgs: { open: !0, all: !0 } }, + { + keys: "", + type: "action", + action: "aceCommand", + actionArgs: { name: "addCursorAbove" }, + }, + { + keys: "", + type: "action", + action: "aceCommand", + actionArgs: { name: "addCursorBelow" }, + }, + { + keys: "", + type: "action", + action: "aceCommand", + actionArgs: { name: "addCursorAboveSkipCurrent" }, + }, + { + keys: "", + type: "action", + action: "aceCommand", + actionArgs: { name: "addCursorBelowSkipCurrent" }, + }, + { + keys: "", + type: "action", + action: "aceCommand", + actionArgs: { name: "selectMoreBefore" }, + }, + { + keys: "", + type: "action", + action: "aceCommand", + actionArgs: { name: "selectMoreAfter" }, + }, + { + keys: "", + type: "action", + action: "aceCommand", + actionArgs: { name: "selectNextBefore" }, + }, + { + keys: "", + type: "action", + action: "aceCommand", + actionArgs: { name: "selectNextAfter" }, + }, + ), + (yt.aceCommand = function (e, t, n) { + (e.vimCmd = t), + e.ace.inVirtualSelectionMode ? e.ace.on("beforeEndOperation", lr) : lr(null, e.ace); + }), + (yt.fold = function (e, t, n) { + e.ace.execCommand( + ["toggleFoldWidget", "toggleFoldWidget", "foldOther", "unfoldall"][ + (t.all ? 2 : 0) + (t.open ? 1 : 0) + ], + ); + }), + (t.handler.defaultKeymap = b), + (t.handler.actions = yt), + (t.Vim = S), + S.map("Y", "yy", "normal"); +}); +(function () { + window.require(["ace/keyboard/vim"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/mode-json.js b/web/static/ace/mode-json.js index 340297a70..cff4390fa 100644 --- a/web/static/ace/mode-json.js +++ b/web/static/ace/mode-json.js @@ -1,9 +1,245 @@ -define("ace/mode/json_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"variable",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)'},{token:"string",regex:'"',next:"string"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"text",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"comment",regex:"\\/\\/.*$"},{token:"comment.start",regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],string:[{token:"constant.language.escape",regex:/\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/},{token:"string",regex:'"|$',next:"start"},{defaultToken:"string"}],comment:[{token:"comment.end",regex:"\\*\\/",next:"start"},{defaultToken:"comment"}]}};r.inherits(s,i),t.JsonHighlightRules=s}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(i.prototype),t.MatchingBraceOutdent=i}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(e){e&&(this.foldingStartMarker=new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/,"|"+e.start)),this.foldingStopMarker=new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/,"|"+e.end)))};r.inherits(o,s),function(){this.foldingStartMarker=/([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/,this.singleLineBlockCommentRe=/^\s*(\/\*).*\*\/\s*$/,this.tripleStarBlockCommentRe=/^\s*(\/\*\*\*).*\*\/\s*$/,this.startRegionRe=/^\s*(\/\*|\/\/)#?region\b/,this._getFoldWidgetBase=this.getFoldWidget,this.getFoldWidget=function(e,t,n){var r=e.getLine(n);if(this.singleLineBlockCommentRe.test(r)&&!this.startRegionRe.test(r)&&!this.tripleStarBlockCommentRe.test(r))return"";var i=this._getFoldWidgetBase(e,t,n);return!i&&this.startRegionRe.test(r)?"start":i},this.getFoldWidgetRange=function(e,t,n,r){var i=e.getLine(n);if(this.startRegionRe.test(i))return this.getCommentRegionBlock(e,i,n);var s=i.match(this.foldingStartMarker);if(s){var o=s.index;if(s[1])return this.openingBracketBlock(e,s[1],n,o);var u=e.getCommentFoldRange(n,o+s[0].length,1);return u&&!u.isMultiLine()&&(r?u=this.getSectionRange(e,n):t!="all"&&(u=null)),u}if(t==="markbegin")return;var s=i.match(this.foldingStopMarker);if(s){var o=s.index+s[0].length;return s[1]?this.closingBracketBlock(e,s[1],n,o):e.getCommentFoldRange(n,o,-1)}},this.getSectionRange=function(e,t){var n=e.getLine(t),r=n.search(/\S/),s=t,o=n.length;t+=1;var u=t,a=e.getLength();while(++tf)break;var l=this.getFoldWidgetRange(e,"all",t);if(l){if(l.start.row<=s)break;if(l.isMultiLine())t=l.end.row;else if(r==f)break}u=t}return new i(s,o,u,e.getLine(u).length)},this.getCommentRegionBlock=function(e,t,n){var r=t.search(/\s*$/),s=e.getLength(),o=n,u=/^\s*(?:\/\*|\/\/|--)#?(end)?region\b/,a=1;while(++no)return new i(o,r,l,t.length)}}.call(o.prototype)}),define("ace/mode/json",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/json_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/worker/worker_client"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./json_highlight_rules").JsonHighlightRules,o=e("./matching_brace_outdent").MatchingBraceOutdent,u=e("./behaviour/cstyle").CstyleBehaviour,a=e("./folding/cstyle").FoldMode,f=e("../worker/worker_client").WorkerClient,l=function(){this.HighlightRules=s,this.$outdent=new o,this.$behaviour=new u,this.foldingRules=new a};r.inherits(l,i),function(){this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t);if(e=="start"){var i=t.match(/^.*[\{\(\[]\s*$/);i&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new f(["ace"],"ace/mode/json_worker","JsonWorker");return t.attachToDocument(e.getDocument()),t.on("annotate",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t},this.$id="ace/mode/json"}.call(l.prototype),t.Mode=l}); - (function() { - window.require(["ace/mode/json"], function(m) { - if (typeof module == "object" && typeof exports == "object" && module) { - module.exports = m; - } +define( + "ace/mode/json_highlight_rules", + ["require", "exports", "module", "ace/lib/oop", "ace/mode/text_highlight_rules"], + function (e, t, n) { + "use strict"; + var r = e("../lib/oop"), + i = e("./text_highlight_rules").TextHighlightRules, + s = function () { + this.$rules = { + start: [ + { token: "variable", regex: '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)' }, + { token: "string", regex: '"', next: "string" }, + { token: "constant.numeric", regex: "0[xX][0-9a-fA-F]+\\b" }, + { + token: "constant.numeric", + regex: "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b", + }, + { token: "constant.language.boolean", regex: "(?:true|false)\\b" }, + { token: "text", regex: "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']" }, + { token: "comment", regex: "\\/\\/.*$" }, + { token: "comment.start", regex: "\\/\\*", next: "comment" }, + { token: "paren.lparen", regex: "[[({]" }, + { token: "paren.rparen", regex: "[\\])}]" }, + { token: "text", regex: "\\s+" }, + ], + string: [ + { + token: "constant.language.escape", + regex: /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/, + }, + { token: "string", regex: '"|$', next: "start" }, + { defaultToken: "string" }, + ], + comment: [ + { token: "comment.end", regex: "\\*\\/", next: "start" }, + { defaultToken: "comment" }, + ], + }; + }; + r.inherits(s, i), (t.JsonHighlightRules = s); + }, +), + define( + "ace/mode/matching_brace_outdent", + ["require", "exports", "module", "ace/range"], + function (e, t, n) { + "use strict"; + var r = e("../range").Range, + i = function () {}; + (function () { + (this.checkOutdent = function (e, t) { + return /^\s+$/.test(e) ? /^\s*\}/.test(t) : !1; + }), + (this.autoOutdent = function (e, t) { + var n = e.getLine(t), + i = n.match(/^(\s*\})/); + if (!i) return 0; + var s = i[1].length, + o = e.findMatchingBracket({ row: t, column: s }); + if (!o || o.row == t) return 0; + var u = this.$getIndent(e.getLine(o.row)); + e.replace(new r(t, 0, t, s - 1), u); + }), + (this.$getIndent = function (e) { + return e.match(/^\s*/)[0]; }); - })(); - \ No newline at end of file + }).call(i.prototype), + (t.MatchingBraceOutdent = i); + }, + ), + define( + "ace/mode/folding/cstyle", + ["require", "exports", "module", "ace/lib/oop", "ace/range", "ace/mode/folding/fold_mode"], + function (e, t, n) { + "use strict"; + var r = e("../../lib/oop"), + i = e("../../range").Range, + s = e("./fold_mode").FoldMode, + o = (t.FoldMode = function (e) { + e && + ((this.foldingStartMarker = new RegExp( + this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + e.start), + )), + (this.foldingStopMarker = new RegExp( + this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + e.end), + ))); + }); + r.inherits(o, s), + function () { + (this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/), + (this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/), + (this.singleLineBlockCommentRe = /^\s*(\/\*).*\*\/\s*$/), + (this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/), + (this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/), + (this._getFoldWidgetBase = this.getFoldWidget), + (this.getFoldWidget = function (e, t, n) { + var r = e.getLine(n); + if ( + this.singleLineBlockCommentRe.test(r) && + !this.startRegionRe.test(r) && + !this.tripleStarBlockCommentRe.test(r) + ) + return ""; + var i = this._getFoldWidgetBase(e, t, n); + return !i && this.startRegionRe.test(r) ? "start" : i; + }), + (this.getFoldWidgetRange = function (e, t, n, r) { + var i = e.getLine(n); + if (this.startRegionRe.test(i)) + return this.getCommentRegionBlock(e, i, n); + var s = i.match(this.foldingStartMarker); + if (s) { + var o = s.index; + if (s[1]) return this.openingBracketBlock(e, s[1], n, o); + var u = e.getCommentFoldRange(n, o + s[0].length, 1); + return ( + u && + !u.isMultiLine() && + (r + ? (u = this.getSectionRange(e, n)) + : t != "all" && (u = null)), + u + ); + } + if (t === "markbegin") return; + var s = i.match(this.foldingStopMarker); + if (s) { + var o = s.index + s[0].length; + return s[1] + ? this.closingBracketBlock(e, s[1], n, o) + : e.getCommentFoldRange(n, o, -1); + } + }), + (this.getSectionRange = function (e, t) { + var n = e.getLine(t), + r = n.search(/\S/), + s = t, + o = n.length; + t += 1; + var u = t, + a = e.getLength(); + while (++t < a) { + n = e.getLine(t); + var f = n.search(/\S/); + if (f === -1) continue; + if (r > f) break; + var l = this.getFoldWidgetRange(e, "all", t); + if (l) { + if (l.start.row <= s) break; + if (l.isMultiLine()) t = l.end.row; + else if (r == f) break; + } + u = t; + } + return new i(s, o, u, e.getLine(u).length); + }), + (this.getCommentRegionBlock = function (e, t, n) { + var r = t.search(/\s*$/), + s = e.getLength(), + o = n, + u = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/, + a = 1; + while (++n < s) { + t = e.getLine(n); + var f = u.exec(t); + if (!f) continue; + f[1] ? a-- : a++; + if (!a) break; + } + var l = n; + if (l > o) return new i(o, r, l, t.length); + }); + }.call(o.prototype); + }, + ), + define( + "ace/mode/json", + [ + "require", + "exports", + "module", + "ace/lib/oop", + "ace/mode/text", + "ace/mode/json_highlight_rules", + "ace/mode/matching_brace_outdent", + "ace/mode/behaviour/cstyle", + "ace/mode/folding/cstyle", + "ace/worker/worker_client", + ], + function (e, t, n) { + "use strict"; + var r = e("../lib/oop"), + i = e("./text").Mode, + s = e("./json_highlight_rules").JsonHighlightRules, + o = e("./matching_brace_outdent").MatchingBraceOutdent, + u = e("./behaviour/cstyle").CstyleBehaviour, + a = e("./folding/cstyle").FoldMode, + f = e("../worker/worker_client").WorkerClient, + l = function () { + (this.HighlightRules = s), + (this.$outdent = new o()), + (this.$behaviour = new u()), + (this.foldingRules = new a()); + }; + r.inherits(l, i), + function () { + (this.getNextLineIndent = function (e, t, n) { + var r = this.$getIndent(t); + if (e == "start") { + var i = t.match(/^.*[\{\(\[]\s*$/); + i && (r += n); + } + return r; + }), + (this.checkOutdent = function (e, t, n) { + return this.$outdent.checkOutdent(t, n); + }), + (this.autoOutdent = function (e, t, n) { + this.$outdent.autoOutdent(t, n); + }), + (this.createWorker = function (e) { + var t = new f(["ace"], "ace/mode/json_worker", "JsonWorker"); + return ( + t.attachToDocument(e.getDocument()), + t.on("annotate", function (t) { + e.setAnnotations(t.data); + }), + t.on("terminate", function () { + e.clearAnnotations(); + }), + t + ); + }), + (this.$id = "ace/mode/json"); + }.call(l.prototype), + (t.Mode = l); + }, + ); +(function () { + window.require(["ace/mode/json"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/theme-dark.js b/web/static/ace/theme-dark.js index 2c96943d9..f36b95101 100644 --- a/web/static/ace/theme-dark.js +++ b/web/static/ace/theme-dark.js @@ -1,9 +1,15 @@ -define("ace/theme/dark",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-chaos",t.cssText=".ace-chaos .ace_scroller { background: #000!important;} .ace-chaos .ace_gutter {background: #141414;color: #595959;border-right: 1px solid #282828;}.ace-chaos .ace_gutter-cell.ace_warning {background-image: none;background: #FC0;border-left: none;padding-left: 0;color: #000;}.ace-chaos .ace_gutter-cell.ace_error {background-position: -6px center;background-image: none;background: #F10;border-left: none;padding-left: 0;color: #000;}.ace-chaos .ace_print-margin {border-left: 1px solid #555;right: 0;background: #1D1D1D;}.ace-chaos {background-color: #161616;color: #FFF;}.ace-chaos .ace_cursor {border-left: 2px solid #FFFFFF;}.ace-chaos .ace_cursor.ace_overwrite {border-left: 0px;border-bottom: 1px solid #FFFFFF;}.ace-chaos .ace_marker-layer .ace_selection {background: #102510;}.ace-chaos .ace_marker-layer .ace_step {background: rgb(198, 219, 174);}.ace-chaos .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #FCE94F;}.ace-chaos .ace_marker-layer .ace_active-line {background: #333;}.ace-chaos .ace_gutter-active-line {background-color: #222;}.ace-chaos .ace_invisible {color: #404040;}.ace-chaos .ace_keyword {color:#00698F;}.ace-chaos .ace_keyword.ace_operator {color:#FF308F;}.ace-chaos .ace_constant {color:#1EDAFB;}.ace-chaos .ace_constant.ace_language {color:#EFA060;}.ace-chaos .ace_constant.ace_library {color:#8DFF0A;}.ace-chaos .ace_constant.ace_numeric {color:#FF6050;}.ace-chaos .ace_invalid {color:#FFFFFF;background-color:#990000;}.ace-chaos .ace_invalid.ace_deprecated {color:#FFFFFF;background-color:#990000;}.ace-chaos .ace_support {color: #999;}.ace-chaos .ace_support.ace_function {color:#00AEEF;}.ace-chaos .ace_function {color:#00AEEF;}.ace-chaos .ace_string {color:#60A060;}.ace-chaos .ace_comment {color:#555;font-style:italic;padding-bottom: 0px;}.ace-chaos .ace_variable {color:#a0a0a0;}.ace-chaos .ace_meta.ace_tag {color:#BE53E6;}.ace-chaos .ace_entity.ace_other.ace_attribute-name {color:#FFFF89;}.ace-chaos .ace_markup.ace_underline {text-decoration: underline;}.ace-chaos .ace_fold-widget {text-align: center;}.ace-chaos .ace_fold-widget:hover {color: #777;}.ace-chaos .ace_fold-widget.ace_start,.ace-chaos .ace_fold-widget.ace_end,.ace-chaos .ace_fold-widget.ace_closed{background: none;border: none;box-shadow: none;}.ace-chaos .ace_fold-widget.ace_start:after {content: '\u25be'}.ace-chaos .ace_fold-widget.ace_end:after {content: '\u25b4'}.ace-chaos .ace_fold-widget.ace_closed:after {content: '\u2023'}.ace-chaos .ace_indent-guide {border-right:1px dotted #333;margin-right:-1px;}.ace-chaos .ace_fold { background: #222; border-radius: 3px; color: #7AF; border: none; }.ace-chaos .ace_fold:hover {background: #CCC; color: #000;}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}); - (function() { - window.require(["ace/theme/dark"], function(m) { - if (typeof module == "object" && typeof exports == "object" && module) { - module.exports = m; - } - }); - })(); - \ No newline at end of file +define("ace/theme/dark", ["require", "exports", "module", "ace/lib/dom"], function (e, t, n) { + (t.isDark = !0), + (t.cssClass = "ace-chaos"), + (t.cssText = + ".ace-chaos .ace_scroller { background: #000!important;} .ace-chaos .ace_gutter {background: #141414;color: #595959;border-right: 1px solid #282828;}.ace-chaos .ace_gutter-cell.ace_warning {background-image: none;background: #FC0;border-left: none;padding-left: 0;color: #000;}.ace-chaos .ace_gutter-cell.ace_error {background-position: -6px center;background-image: none;background: #F10;border-left: none;padding-left: 0;color: #000;}.ace-chaos .ace_print-margin {border-left: 1px solid #555;right: 0;background: #1D1D1D;}.ace-chaos {background-color: #161616;color: #FFF;}.ace-chaos .ace_cursor {border-left: 2px solid #FFFFFF;}.ace-chaos .ace_cursor.ace_overwrite {border-left: 0px;border-bottom: 1px solid #FFFFFF;}.ace-chaos .ace_marker-layer .ace_selection {background: #102510;}.ace-chaos .ace_marker-layer .ace_step {background: rgb(198, 219, 174);}.ace-chaos .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #FCE94F;}.ace-chaos .ace_marker-layer .ace_active-line {background: #333;}.ace-chaos .ace_gutter-active-line {background-color: #222;}.ace-chaos .ace_invisible {color: #404040;}.ace-chaos .ace_keyword {color:#00698F;}.ace-chaos .ace_keyword.ace_operator {color:#FF308F;}.ace-chaos .ace_constant {color:#1EDAFB;}.ace-chaos .ace_constant.ace_language {color:#EFA060;}.ace-chaos .ace_constant.ace_library {color:#8DFF0A;}.ace-chaos .ace_constant.ace_numeric {color:#FF6050;}.ace-chaos .ace_invalid {color:#FFFFFF;background-color:#990000;}.ace-chaos .ace_invalid.ace_deprecated {color:#FFFFFF;background-color:#990000;}.ace-chaos .ace_support {color: #999;}.ace-chaos .ace_support.ace_function {color:#00AEEF;}.ace-chaos .ace_function {color:#00AEEF;}.ace-chaos .ace_string {color:#60A060;}.ace-chaos .ace_comment {color:#555;font-style:italic;padding-bottom: 0px;}.ace-chaos .ace_variable {color:#a0a0a0;}.ace-chaos .ace_meta.ace_tag {color:#BE53E6;}.ace-chaos .ace_entity.ace_other.ace_attribute-name {color:#FFFF89;}.ace-chaos .ace_markup.ace_underline {text-decoration: underline;}.ace-chaos .ace_fold-widget {text-align: center;}.ace-chaos .ace_fold-widget:hover {color: #777;}.ace-chaos .ace_fold-widget.ace_start,.ace-chaos .ace_fold-widget.ace_end,.ace-chaos .ace_fold-widget.ace_closed{background: none;border: none;box-shadow: none;}.ace-chaos .ace_fold-widget.ace_start:after {content: '\u25be'}.ace-chaos .ace_fold-widget.ace_end:after {content: '\u25b4'}.ace-chaos .ace_fold-widget.ace_closed:after {content: '\u2023'}.ace-chaos .ace_indent-guide {border-right:1px dotted #333;margin-right:-1px;}.ace-chaos .ace_fold { background: #222; border-radius: 3px; color: #7AF; border: none; }.ace-chaos .ace_fold:hover {background: #CCC; color: #000;}"); + var r = e("../lib/dom"); + r.importCssString(t.cssText, t.cssClass); +}); +(function () { + window.require(["ace/theme/dark"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/theme-light.js b/web/static/ace/theme-light.js index 3f778bcee..f41bded2e 100644 --- a/web/static/ace/theme-light.js +++ b/web/static/ace/theme-light.js @@ -1,9 +1,15 @@ -define("ace/theme/light",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-dawn",t.cssText=".ace-dawn .ace_scroller { background-color: #FFF!important;} .ace-dawn .ace_gutter {background: #ebebeb;color: #333}.ace-dawn .ace_print-margin {width: 1px;background: #e8e8e8}.ace-dawn {background-color: #F9F9F9;color: #080808}.ace-dawn .ace_cursor {color: #000000}.ace-dawn .ace_marker-layer .ace_selection {background: rgba(39, 95, 255, 0.30)}.ace-dawn.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #F9F9F9;}.ace-dawn .ace_marker-layer .ace_step {background: rgb(255, 255, 0)}.ace-dawn .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgba(75, 75, 126, 0.50)}.ace-dawn .ace_marker-layer .ace_active-line {background: rgba(36, 99, 180, 0.12)}.ace-dawn .ace_gutter-active-line {background-color : #dcdcdc}.ace-dawn .ace_marker-layer .ace_selected-word {border: 1px solid rgba(39, 95, 255, 0.30)}.ace-dawn .ace_invisible {color: rgba(75, 75, 126, 0.50)}.ace-dawn .ace_keyword,.ace-dawn .ace_meta {color: #794938}.ace-dawn .ace_constant,.ace-dawn .ace_constant.ace_character,.ace-dawn .ace_constant.ace_character.ace_escape,.ace-dawn .ace_constant.ace_other {color: #811F24}.ace-dawn .ace_invalid.ace_illegal {text-decoration: underline;font-style: italic;color: #F8F8F8;background-color: #B52A1D}.ace-dawn .ace_invalid.ace_deprecated {text-decoration: underline;font-style: italic;color: #B52A1D}.ace-dawn .ace_support {color: #691C97}.ace-dawn .ace_support.ace_constant {color: #B4371F}.ace-dawn .ace_fold {background-color: #794938;border-color: #080808}.ace-dawn .ace_list,.ace-dawn .ace_markup.ace_list,.ace-dawn .ace_support.ace_function {color: #693A17}.ace-dawn .ace_storage {font-style: italic;color: #A71D5D}.ace-dawn .ace_string {color: #0B6125}.ace-dawn .ace_string.ace_regexp {color: #CF5628}.ace-dawn .ace_comment {font-style: italic;color: #5A525F}.ace-dawn .ace_heading,.ace-dawn .ace_markup.ace_heading {color: #19356D}.ace-dawn .ace_variable {color: #234A97}.ace-dawn .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYLh/5+x/AAizA4hxNNsZAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}); - (function() { - window.require(["ace/theme/light"], function(m) { - if (typeof module == "object" && typeof exports == "object" && module) { - module.exports = m; - } - }); - })(); - \ No newline at end of file +define("ace/theme/light", ["require", "exports", "module", "ace/lib/dom"], function (e, t, n) { + (t.isDark = !1), + (t.cssClass = "ace-dawn"), + (t.cssText = + ".ace-dawn .ace_scroller { background-color: #FFF!important;} .ace-dawn .ace_gutter {background: #ebebeb;color: #333}.ace-dawn .ace_print-margin {width: 1px;background: #e8e8e8}.ace-dawn {background-color: #F9F9F9;color: #080808}.ace-dawn .ace_cursor {color: #000000}.ace-dawn .ace_marker-layer .ace_selection {background: rgba(39, 95, 255, 0.30)}.ace-dawn.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #F9F9F9;}.ace-dawn .ace_marker-layer .ace_step {background: rgb(255, 255, 0)}.ace-dawn .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgba(75, 75, 126, 0.50)}.ace-dawn .ace_marker-layer .ace_active-line {background: rgba(36, 99, 180, 0.12)}.ace-dawn .ace_gutter-active-line {background-color : #dcdcdc}.ace-dawn .ace_marker-layer .ace_selected-word {border: 1px solid rgba(39, 95, 255, 0.30)}.ace-dawn .ace_invisible {color: rgba(75, 75, 126, 0.50)}.ace-dawn .ace_keyword,.ace-dawn .ace_meta {color: #794938}.ace-dawn .ace_constant,.ace-dawn .ace_constant.ace_character,.ace-dawn .ace_constant.ace_character.ace_escape,.ace-dawn .ace_constant.ace_other {color: #811F24}.ace-dawn .ace_invalid.ace_illegal {text-decoration: underline;font-style: italic;color: #F8F8F8;background-color: #B52A1D}.ace-dawn .ace_invalid.ace_deprecated {text-decoration: underline;font-style: italic;color: #B52A1D}.ace-dawn .ace_support {color: #691C97}.ace-dawn .ace_support.ace_constant {color: #B4371F}.ace-dawn .ace_fold {background-color: #794938;border-color: #080808}.ace-dawn .ace_list,.ace-dawn .ace_markup.ace_list,.ace-dawn .ace_support.ace_function {color: #693A17}.ace-dawn .ace_storage {font-style: italic;color: #A71D5D}.ace-dawn .ace_string {color: #0B6125}.ace-dawn .ace_string.ace_regexp {color: #CF5628}.ace-dawn .ace_comment {font-style: italic;color: #5A525F}.ace-dawn .ace_heading,.ace-dawn .ace_markup.ace_heading {color: #19356D}.ace-dawn .ace_variable {color: #234A97}.ace-dawn .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYLh/5+x/AAizA4hxNNsZAAAAAElFTkSuQmCC) right repeat-y}"); + var r = e("../lib/dom"); + r.importCssString(t.cssText, t.cssClass); +}); +(function () { + window.require(["ace/theme/light"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/web/static/ace/worker-coffee.js b/web/static/ace/worker-coffee.js index a2244ef76..564efb5f4 100644 --- a/web/static/ace/worker-coffee.js +++ b/web/static/ace/worker-coffee.js @@ -1 +1,38636 @@ -"no use strict";!function(e){function t(e,t){var n=e,r="";while(n){var i=t[n];if(typeof i=="string")return i+r;if(i)return i.location.replace(/\/*$/,"/")+(r||i.main||i.name);if(i===!1)return"";var s=n.lastIndexOf("/");if(s===-1)break;r=n.substr(s)+r,n=n.slice(0,s)}return e}if(typeof e.window!="undefined"&&e.document)return;if(e.require&&e.define)return;e.console||(e.console=function(){var e=Array.prototype.slice.call(arguments,0);postMessage({type:"log",data:e})},e.console.error=e.console.warn=e.console.log=e.console.trace=e.console),e.window=e,e.ace=e,e.onerror=function(e,t,n,r,i){postMessage({type:"error",data:{message:e,data:i.data,file:t,line:n,col:r,stack:i.stack}})},e.normalizeModule=function(t,n){if(n.indexOf("!")!==-1){var r=n.split("!");return e.normalizeModule(t,r[0])+"!"+e.normalizeModule(t,r[1])}if(n.charAt(0)=="."){var i=t.split("/").slice(0,-1).join("/");n=(i?i+"/":"")+n;while(n.indexOf(".")!==-1&&s!=n){var s=n;n=n.replace(/^\.\//,"").replace(/\/\.\//,"/").replace(/[^\/]+\/\.\.\//,"")}}return n},e.require=function(r,i){i||(i=r,r=null);if(!i.charAt)throw new Error("worker.js require() accepts only (parentId, id) as arguments");i=e.normalizeModule(r,i);var s=e.require.modules[i];if(s)return s.initialized||(s.initialized=!0,s.exports=s.factory().exports),s.exports;if(!e.require.tlns)return console.log("unable to load "+i);var o=t(i,e.require.tlns);return o.slice(-3)!=".js"&&(o+=".js"),e.require.id=i,e.require.modules[i]={},importScripts(o),e.require(r,i)},e.require.modules={},e.require.tlns={},e.define=function(t,n,r){arguments.length==2?(r=n,typeof t!="string"&&(n=t,t=e.require.id)):arguments.length==1&&(r=t,n=[],t=e.require.id);if(typeof r!="function"){e.require.modules[t]={exports:r,initialized:!0};return}n.length||(n=["require","exports","module"]);var i=function(n){return e.require(t,n)};e.require.modules[t]={exports:{},factory:function(){var e=this,t=r.apply(this,n.slice(0,r.length).map(function(t){switch(t){case"require":return i;case"exports":return e.exports;case"module":return e;default:return i(t)}}));return t&&(e.exports=t),e}}},e.define.amd={},require.tlns={},e.initBaseUrls=function(t){for(var n in t)require.tlns[n]=t[n]},e.initSender=function(){var n=e.require("ace/lib/event_emitter").EventEmitter,r=e.require("ace/lib/oop"),i=function(){};return function(){r.implement(this,n),this.callback=function(e,t){postMessage({type:"call",id:t,data:e})},this.emit=function(e,t){postMessage({type:"event",name:e,data:t})}}.call(i.prototype),new i};var n=e.main=null,r=e.sender=null;e.onmessage=function(t){var i=t.data;if(i.event&&r)r._signal(i.event,i.data);else if(i.command)if(n[i.command])n[i.command].apply(n,i.args);else{if(!e[i.command])throw new Error("Unknown command:"+i.command);e[i.command].apply(e,i.args)}else if(i.init){e.initBaseUrls(i.tlns),require("ace/lib/es5-shim"),r=e.sender=e.initSender();var s=require(i.module)[i.classname];n=e.main=new s(r)}}}(this),define("ace/lib/oop",[],function(e,t,n){"use strict";t.inherits=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})},t.mixin=function(e,t){for(var n in t)e[n]=t[n];return e},t.implement=function(e,n){t.mixin(e,n)}}),define("ace/range",[],function(e,t,n){"use strict";var r=function(e,t){return e.row-t.row||e.column-t.column},i=function(e,t,n,r){this.start={row:e,column:t},this.end={row:n,column:r}};(function(){this.isEqual=function(e){return this.start.row===e.start.row&&this.end.row===e.end.row&&this.start.column===e.start.column&&this.end.column===e.end.column},this.toString=function(){return"Range: ["+this.start.row+"/"+this.start.column+"] -> ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e=="object"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e=="object"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?tthis.end.column?1:0:ethis.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};else if(this.end.rowt)var r={row:t+1,column:0};else if(this.start.row=0&&t.row=0&&t.column<=e[t.row].length}function s(e,t){t.action!="insert"&&t.action!="remove"&&r(t,"delta.action must be 'insert' or 'remove'"),t.lines instanceof Array||r(t,"delta.lines must be an Array"),(!t.start||!t.end)&&r(t,"delta.start/end must be an present");var n=t.start;i(e,t.start)||r(t,"delta.start must be contained in document");var s=t.end;t.action=="remove"&&!i(e,s)&&r(t,"delta.end must contained in document for 'remove' actions");var o=s.row-n.row,u=s.column-(o==0?n.column:0);(o!=t.lines.length-1||t.lines[o].length!=u)&&r(t,"delta.range must match delta lines")}t.applyDelta=function(e,t,n){var r=t.start.row,i=t.start.column,s=e[r]||"";switch(t.action){case"insert":var o=t.lines;if(o.length===1)e[r]=s.substring(0,i)+t.lines[0]+s.substring(i);else{var u=[r,1].concat(t.lines);e.splice.apply(e,u),e[r]=s.substring(0,i)+e[r],e[r+t.lines.length-1]+=s.substring(i)}break;case"remove":var a=t.end.column,f=t.end.row;r===f?e[r]=s.substring(0,i)+s.substring(a):e.splice(r,f-r+1,s.substring(0,i)+e[f].substring(a))}}}),define("ace/lib/event_emitter",[],function(e,t,n){"use strict";var r={},i=function(){this.propagationStopped=!0},s=function(){this.defaultPrevented=!0};r._emit=r._dispatchEvent=function(e,t){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var n=this._eventRegistry[e]||[],r=this._defaultHandlers[e];if(!n.length&&!r)return;if(typeof t!="object"||!t)t={};t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=i),t.preventDefault||(t.preventDefault=s),n=n.slice();for(var o=0;othis.row)return;var n=t(e,{row:this.row,column:this.column},this.$insertRight);this.setPosition(n.row,n.column,!0)},this.setPosition=function(e,t,n){var r;n?r={row:e,column:t}:r=this.$clipPositionToDocument(e,t);if(this.row==r.row&&this.column==r.column)return;var i={row:this.row,column:this.column};this.row=r.row,this.column=r.column,this._signal("change",{old:i,value:r})},this.detach=function(){this.document.removeEventListener("change",this.$onChange)},this.attach=function(e){this.document=e||this.document,this.document.on("change",this.$onChange)},this.$clipPositionToDocument=function(e,t){var n={};return e>=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),define("ace/document",[],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./apply_delta").applyDelta,s=e("./lib/event_emitter").EventEmitter,o=e("./range").Range,u=e("./anchor").Anchor,a=function(e){this.$lines=[""],e.length===0?this.$lines=[""]:Array.isArray(e)?this.insertMergedLines({row:0,column:0},e):this.insert({row:0,column:0},e)};(function(){r.implement(this,s),this.setValue=function(e){var t=this.getLength()-1;this.remove(new o(0,0,t,this.getLine(t).length)),this.insert({row:0,column:0},e)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(e,t){return new u(this,e,t)},"aaa".split(/a/).length===0?this.$split=function(e){return e.replace(/\r\n|\r/g,"\n").split("\n")}:this.$split=function(e){return e.split(/\r\n|\r|\n/)},this.$detectNewLine=function(e){var t=e.match(/^.*?(\r\n|\r|\n)/m);this.$autoNewLine=t?t[1]:"\n",this._signal("changeNewLineMode")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case"windows":return"\r\n";case"unix":return"\n";default:return this.$autoNewLine||"\n"}},this.$autoNewLine="",this.$newLineMode="auto",this.setNewLineMode=function(e){if(this.$newLineMode===e)return;this.$newLineMode=e,this._signal("changeNewLineMode")},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(e){return e=="\r\n"||e=="\r"||e=="\n"},this.getLine=function(e){return this.$lines[e]||""},this.getLines=function(e,t){return this.$lines.slice(e,t+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(e){return this.getLinesForRange(e).join(this.getNewLineCharacter())},this.getLinesForRange=function(e){var t;if(e.start.row===e.end.row)t=[this.getLine(e.start.row).substring(e.start.column,e.end.column)];else{t=this.getLines(e.start.row,e.end.row),t[0]=(t[0]||"").substring(e.start.column);var n=t.length-1;e.end.row-e.start.row==n&&(t[n]=t[n].substring(0,e.end.column))}return t},this.insertLines=function(e,t){return console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."),this.insertFullLines(e,t)},this.removeLines=function(e,t){return console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."),this.removeFullLines(e,t)},this.insertNewLine=function(e){return console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead."),this.insertMergedLines(e,["",""])},this.insert=function(e,t){return this.getLength()<=1&&this.$detectNewLine(t),this.insertMergedLines(e,this.$split(t))},this.insertInLine=function(e,t){var n=this.clippedPos(e.row,e.column),r=this.pos(e.row,e.column+t.length);return this.applyDelta({start:n,end:r,action:"insert",lines:[t]},!0),this.clonePos(r)},this.clippedPos=function(e,t){var n=this.getLength();e===undefined?e=n:e<0?e=0:e>=n&&(e=n-1,t=undefined);var r=this.getLine(e);return t==undefined&&(t=r.length),t=Math.min(Math.max(t,0),r.length),{row:e,column:t}},this.clonePos=function(e){return{row:e.row,column:e.column}},this.pos=function(e,t){return{row:e,column:t}},this.$clipPosition=function(e){var t=this.getLength();return e.row>=t?(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length):(e.row=Math.max(0,e.row),e.column=Math.min(Math.max(e.column,0),this.getLine(e.row).length)),e},this.insertFullLines=function(e,t){e=Math.min(Math.max(e,0),this.getLength());var n=0;e0,r=t=0&&this.applyDelta({start:this.pos(e,this.getLine(e).length),end:this.pos(e+1,0),action:"remove",lines:["",""]})},this.replace=function(e,t){e instanceof o||(e=o.fromPoints(e.start,e.end));if(t.length===0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);var n;return t?n=this.insert(e.start,t):n=e.start,n},this.applyDeltas=function(e){for(var t=0;t=0;t--)this.revertDelta(e[t])},this.applyDelta=function(e,t){var n=e.action=="insert";if(n?e.lines.length<=1&&!e.lines[0]:!o.comparePoints(e.start,e.end))return;n&&e.lines.length>2e4?this.$splitAndapplyLargeDelta(e,2e4):(i(this.$lines,e,t),this._signal("change",e))},this.$splitAndapplyLargeDelta=function(e,t){var n=e.lines,r=n.length-t+1,i=e.start.row,s=e.start.column;for(var o=0,u=0;o0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\s\s*/,i=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(r,"")},t.stringTrimRight=function(e){return e.replace(i,"")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n=6"},directories:{lib:"./lib/coffeescript"},main:"./lib/coffeescript/index",browser:"./lib/coffeescript/browser",bin:{coffee:"./bin/coffee",cake:"./bin/cake"},files:["bin","lib","register.js","repl.js"],scripts:{test:"node ./bin/cake test","test-harmony":"node --harmony ./bin/cake test"},homepage:"http://coffeescript.org",bugs:"https://github.com/jashkenas/coffeescript/issues",repository:{type:"git",url:"git://github.com/jashkenas/coffeescript.git"},devDependencies:{"babel-core":"~6.26.0","babel-preset-babili":"~0.1.4","babel-preset-env":"~1.6.1","babel-preset-minify":"^0.3.0",codemirror:"^5.32.0",docco:"~0.8.0","highlight.js":"~9.12.0",jison:">=0.4.18","markdown-it":"~8.4.0",underscore:"~1.8.3",webpack:"~3.10.0"},dependencies:{}}}(),require["./helpers"]=function(){var e={};return function(){var t,n,r,i,s,o,u,a;e.starts=function(e,t,n){return t===e.substr(n,t.length)},e.ends=function(e,t,n){var r;return r=t.length,t===e.substr(e.length-r-(n||0),r)},e.repeat=u=function(e,t){var n;for(n="";0>>=1,e+=e;return n},e.compact=function(e){var t,n,r,i;for(i=[],t=0,r=e.length;to)return s.returnOnNegativeLevel?void 0:i.call(this,c,n);n+=1}return n-1}},{key:"removeLeadingNewlines",value:function(){var t,n,r,i,s,o,u,a,f;for(u=this.tokens,t=n=0,s=u.length;n=s&&s>o;i=0<=o?++s:--s)if(null!=f[i]&&("string"==typeof f[i]&&(f[i]=[f[i]]),u=this.tag(n+i+r),0>t.call(f[i],u)))return-1;return n+i+r-1}},{key:"looksObjectish",value:function(n){var r,i;return-1!==this.indexOfTag(n,"@",null,":")||-1!==this.indexOfTag(n,null,":")||(i=this.indexOfTag(n,f),-1!==i&&(r=null,this.detectEnd(i+1,function(e){var n;return n=e[0],0<=t.call(a,n)},function(e,t){return r=t}),":"===this.tag(r+1)))}},{key:"findTagsBackwards",value:function(n,r){var i,s,o,u,l,c,h;for(i=[];0<=n&&(i.length||(u=this.tag(n),0>t.call(r,u))&&((l=this.tag(n),0>t.call(f,l))||this.tokens[n].generated)&&(c=this.tag(n),0>t.call(v,c)));)(s=this.tag(n),0<=t.call(a,s))&&i.push(this.tag(n)),(o=this.tag(n),0<=t.call(f,o))&&i.length&&i.pop(),n-=1;return h=this.tag(n),0<=t.call(r,h)}},{key:"addImplicitBracesAndParens",value:function(){var n,r;return n=[],r=null,this.scanTokens(function(e,o,u){var d=this,m=_slicedToArray(e,1),g,y,w,E,S,x,T,N,C,k,L,A,O,M,_,D,P,H,B,j,F,I,q,R,U,z,W,X,V,$,J,K,Q;Q=m[0];var G=B=0"!==H&&"->"!==H&&"["!==H&&"("!==H&&","!==H&&"{"!==H&&"ELSE"!==H&&"="!==H)for(;T()||C()&&":"!==H;)T()?g():y();return N()&&n.pop(),n.push([Q,o]),w(1)}if(0<=t.call(f,Q))return n.push([Q,o]),w(1);if(0<=t.call(a,Q)){for(;x();)T()?g():C()?y():n.pop();r=n.pop()}if(S=function(){var n,r,i,s;return(i=d.findTagsBackwards(o,["FOR"])&&d.findTagsBackwards(o,["FORIN","FOROF","FORFROM"]),n=i||d.findTagsBackwards(o,["WHILE","UNTIL","LOOP","LEADING_WHEN"]),!!n)&&(r=!1,s=e[2].first_line,d.detectEnd(o,function(e){var n;return n=e[0],0<=t.call(v,n)},function(e,t){var n=u[t-1]||[],i=_slicedToArray(n,3),o;return H=i[0],o=i[2].first_line,r=s===o&&("->"===H||"=>"===H)},{returnOnNegativeLevel:!0}),r)},(0<=t.call(h,Q)&&e.spaced||"?"===Q&&0t.call(a,e):return r[1];case"@"!==this.tag(o-2):return o-2;default:return o-1}}.call(this),K=0>=q||(F=this.tag(q-1),0<=t.call(v,F))||u[q-1].newLine,X()){var tt=X(),nt=_slicedToArray(tt,2);if(W=nt[0],U=nt[1],("{"===W||"INDENT"===W&&"{"===this.tag(U-1))&&(K||","===this.tag(q-1)||"{"===this.tag(q-1)))return w(1)}return J(q,!!K),w(2)}if(0<=t.call(v,Q))for(O=n.length-1;0<=O&&(z=n[O],!!k(z));O+=-1)A(z)&&(z[2].sameLine=!1);if(M="OUTDENT"===H||B.newLine,0<=t.call(c,Q)||0<=t.call(i,Q)&&M||(".."===Q||"..."===Q)&&this.findTagsBackwards(o,["INDEX_START"]))for(;x();){var rt=X(),it=_slicedToArray(rt,3);W=it[0],U=it[1];var st=it[2];if(R=st.sameLine,K=st.startsLine,T()&&","!==H||","===H&&"TERMINATOR"===Q&&null==_)g();else if(C()&&R&&"TERMINATOR"!==Q&&":"!==H&&("POST_IF"!==Q&&"FOR"!==Q&&"WHILE"!==Q&&"UNTIL"!==Q||!K||!E(o+1)))y();else{if(!C()||"TERMINATOR"!==Q||","===H||!!K&&!!this.looksObjectish(o+1))break;y()}}if(","===Q&&!this.looksObjectish(o+1)&&C()&&"FOROF"!==(I=this.tag(o+2))&&"FORIN"!==I&&("TERMINATOR"!==_||!this.looksObjectish(o+2)))for(P="OUTDENT"===_?1:0;C();)y(o+P);return w(1)})}},{key:"enforceValidCSXAttributes",value:function(){return this.scanTokens(function(e,t,n){var r,i;return e.csxColon&&(r=n[t+1],"STRING_START"!==(i=r[0])&&"STRING"!==i&&"("!==i&&N("expected wrapped or quoted JSX attribute",r[2])),1})}},{key:"rescueStowawayComments",value:function(){var n,r,i;return n=function(e,t,n,r){return"TERMINATOR"!==n[t][0]&&n[r](b("TERMINATOR","\n",n[t])),n[r](b("JS","",n[t],e))},i=function(e,r,i){var s,u,a,f,l,c,h;for(u=r;u!==i.length&&(l=i[u][0],0<=t.call(o,l));)u++;if(u===i.length||(c=i[u][0],0<=t.call(o,c)))return u=i.length-1,n(e,u,i,"push"),1;for(h=e.comments,a=0,f=h.length;at.call(i,r)))return this.tokens.splice(s,0,b("(","(",this.tokens[s])),this.tokens.splice(n+1,0,b(")",")",this.tokens[n]))},s=null,this.scanTokens(function(e,t){var i,o;return"do"===e[1]?(s=t,i=t+1,"PARAM_START"===this.tag(t+1)&&(i=null,this.detectEnd(t+1,function(e,t){return"PARAM_END"===this.tag(t-1)},function(e,t){return i=t})),null==i||"->"!==(o=this.tag(i))&&"=>"!==o||"INDENT"!==this.tag(i+1))?1:(this.detectEnd(i+1,r,n),2):1})}},{key:"normalizeLines",value:function(){var n=this,r,s,o,a,f,l,c,h,p;return p=f=h=null,c=null,l=null,a=[],o=function(e,n){var r,s,o,a;return";"!==e[1]&&(r=e[0],0<=t.call(g,r))&&!("TERMINATOR"===e[0]&&(s=this.tag(n+1),0<=t.call(u,s)))&&("ELSE"!==e[0]||"THEN"===p&&!l&&!c)&&("CATCH"!==(o=e[0])&&"FINALLY"!==o||"->"!==p&&"=>"!==p)||(a=e[0],0<=t.call(i,a))&&(this.tokens[n-1].newLine||"OUTDENT"===this.tokens[n-1][0])},r=function(e,t){return"ELSE"===e[0]&&"THEN"===p&&a.pop(),this.tokens.splice(","===this.tag(t-1)?t-1:t,0,h)},s=function(e,t){var r,i,s;if(s=a.length,0"===E||"=>"===E)&&this.findTagsBackwards(n,["IF","WHILE","FOR","UNTIL","SWITCH","WHEN","LEADING_WHEN","[","INDEX_START"])&&!this.findTagsBackwards(n,["THEN","..","..."]),"TERMINATOR"===E){if("ELSE"===this.tag(n+1)&&"OUTDENT"!==this.tag(n-1))return i.splice.apply(i,[n,1].concat(_toConsumableArray(this.indentation()))),1;if(b=this.tag(n+1),0<=t.call(u,b))return i.splice(n,1),0}if("CATCH"===E)for(m=g=1;2>=g;m=++g)if("OUTDENT"===(w=this.tag(n+m))||"TERMINATOR"===w||"FINALLY"===w)return i.splice.apply(i,[n+m,0].concat(_toConsumableArray(this.indentation()))),2+m;if("->"!==E&&"=>"!==E||!(","===this.tag(n+1)||"."===this.tag(n+1)&&e.newLine)){if(0<=t.call(y,E)&&"INDENT"!==this.tag(n+1)&&("ELSE"!==E||"IF"!==this.tag(n+1))&&!v){p=E;var T=this.indentation(i[n]),N=_slicedToArray(T,2);return f=N[0],h=N[1],"THEN"===p&&(f.fromThen=!0),"THEN"===E&&(c=this.findTagsBackwards(n,["LEADING_WHEN"])&&"IF"===this.tag(n+1),l=this.findTagsBackwards(n,["IF"])&&"IF"===this.tag(n+1)),"THEN"===E&&this.findTagsBackwards(n,["IF"])&&a.push(n),"ELSE"===E&&"OUTDENT"!==this.tag(n-1)&&(n=s(i,n)),i.splice(n+1,0,f),this.detectEnd(n+2,o,r),"THEN"===E&&i.splice(n,1),1}return 1}var S=this.indentation(i[n]),x=_slicedToArray(S,2);return f=x[0],h=x[1],i.splice(n+1,0,f,h),1})}},{key:"tagPostfixConditionals",value:function(){var n,r,i;return i=null,r=function(e,n){var r=_slicedToArray(e,1),i,s;s=r[0];var o=_slicedToArray(this.tokens[n-1],1);return i=o[0],"TERMINATOR"===s||"INDENT"===s&&0>t.call(y,i)},n=function(e){if("INDENT"!==e[0]||e.generated&&!e.fromThen)return i[0]="POST_"+i[0]},this.scanTokens(function(e,t){return"IF"===e[0]?(i=e,this.detectEnd(t+1,r,n),1):1})}},{key:"indentation",value:function(t){var n,r;return n=["INDENT",2],r=["OUTDENT",2],t?(n.generated=r.generated=!0,n.origin=r.origin=t):n.explicit=r.explicit=!0,[n,r]}},{key:"tag",value:function(t){var n;return null==(n=this.tokens[t])?void 0:n[0]}}]),e}();return e.prototype.generate=b,e}.call(this),r=[["(",")"],["[","]"],["{","}"],["INDENT","OUTDENT"],["CALL_START","CALL_END"],["PARAM_START","PARAM_END"],["INDEX_START","INDEX_END"],["STRING_START","STRING_END"],["REGEX_START","REGEX_END"]],e.INVERSES=d={},f=[],a=[],w=0,S=r.length;w","=>","[","(","{","--","++"],p=["+","-"],c=["POST_IF","FOR","WHILE","UNTIL","WHEN","BY","LOOP","TERMINATOR"],y=["ELSE","->","=>","TRY","FINALLY","THEN"],g=["TERMINATOR","CATCH","FINALLY","ELSE","OUTDENT","LEADING_WHEN"],v=["TERMINATOR","INDENT","OUTDENT"],i=[".","?.","::","?::"],s=["IF","TRY","FINALLY","CATCH","CLASS","SWITCH"],o=["(",")","[","]","{","}",".","..","...",",","=","++","--","?","AS","AWAIT","CALL_START","CALL_END","DEFAULT","ELSE","EXTENDS","EXPORT","FORIN","FOROF","FORFROM","IMPORT","INDENT","INDEX_SOAK","LEADING_WHEN","OUTDENT","PARAM_END","REGEX_START","REGEX_END","RETURN","STRING_END","THROW","UNARY","YIELD"].concat(p.concat(c.concat(i.concat(s))))}.call(this),{exports:e}.exports}(),require["./lexer"]=function(){var e={};return function(){var t=[].indexOf,n=[].slice,r=require("./rewriter"),i,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b,w,E,S,x,T,N,C,k,L,A,O,M,_,D,P,H,B,j,F,I,q,R,U,z,W,X,V,$,J,K,Q,G,Y,Z,et,tt,nt,rt,it,st,ot,ut,at,ft,lt,ct,ht,pt,dt,vt,mt,gt,yt,bt,wt,Et,St,xt;K=r.Rewriter,O=r.INVERSES;var Tt=require("./helpers");dt=Tt.count,St=Tt.starts,pt=Tt.compact,Et=Tt.repeat,vt=Tt.invertLiterate,wt=Tt.merge,ht=Tt.attachCommentsToNode,bt=Tt.locationDataToString,xt=Tt.throwSyntaxError,e.Lexer=B=function(){function e(){_classCallCheck(this,e)}return _createClass(e,[{key:"tokenize",value:function(t){var n=1this.indent){if(a)return this.indebt=l-this.indent,this.suppressNewlines(),i.length;if(!this.tokens.length)return this.baseIndent=this.indent=l,this.indentLiteral=u,i.length;r=l-this.indent+this.outdebt,this.token("INDENT",r,i.length-l,l),this.indents.push(r),this.ends.push({tag:"OUTDENT"}),this.outdebt=this.indebt=0,this.indent=l,this.indentLiteral=u}else lt.call(h,v))))return 0;var E=l,S=_slicedToArray(E,3);return f=S[0],a=S[1],i=S[2],c=this.token("CSX_TAG",a,1,a.length),this.token("CALL_START","("),this.token("[","["),this.ends.push({tag:"/>",origin:c,name:a}),this.csxDepth++,a.length+1}if(s=this.atCSXTag()){if("/>"===this.chunk.slice(0,2))return this.pair("/>"),this.token("]","]",0,2),this.token("CALL_END",")",0,2),this.csxDepth--,2;if("{"===u)return":"===d?(b=this.token("(","("),this.csxObjAttribute[this.csxDepth]=!1):(b=this.token("{","{"),this.csxObjAttribute[this.csxDepth]=!0),this.ends.push({tag:"}",origin:b}),1;if(">"===u){this.pair("/>"),c=this.token("]","]"),this.token(",",",");var x=this.matchWithInterpolations(A,">",""})}),l=g.exec(this.chunk.slice(o))||m.exec(this.chunk.slice(o)),l&&l[1]===s.name||this.error("expected corresponding CSX closing tag for "+s.name,s.origin[2]),r=o+s.name.length,">"!==this.chunk[r]&&this.error("missing closing > after tag name",{offset:r,length:1}),this.token("CALL_END",")",o,s.name.length+1),this.csxDepth--,r+1}return 0}return this.atCSXTag(1)?"}"===u?(this.pair(u),this.csxObjAttribute[this.csxDepth]?(this.token("}","}"),this.csxObjAttribute[this.csxDepth]=!1):this.token(")",")"),this.token(",",","),1):0:0}},{key:"atCSXTag",value:function(){var t=0"===(null==r?void 0:r.tag)&&r}},{key:"literalToken",value:function(){var n,r,i,s,a,f,l,c,h,v,m,g,y;if(n=R.exec(this.chunk)){var b=n,w=_slicedToArray(b,1);y=w[0],u.test(y)&&this.tagParameters()}else y=this.chunk.charAt(0);if(m=y,s=this.prev(),s&&0<=t.call(["="].concat(_toConsumableArray(d)),y)&&(v=!1,"="!==y||"||"!==(a=s[1])&&"&&"!==a||s.spaced||(s[0]="COMPOUND_ASSIGN",s[1]+="=",s=this.tokens[this.tokens.length-2],v=!0),s&&"PROPERTY"!==s[0]&&(i=null==(f=s.origin)?s:f,r=gt(s[1],i[1]),r&&this.error(r,i[2])),v))return y.length;if("{"===y&&this.seenImport?this.importSpecifierList=!0:this.importSpecifierList&&"}"===y?this.importSpecifierList=!1:"{"===y&&"EXPORT"===(null==s?void 0:s[0])?this.exportSpecifierList=!0:this.exportSpecifierList&&"}"===y&&(this.exportSpecifierList=!1),";"===y)(l=null==s?void 0:s[0],0<=t.call(["="].concat(_toConsumableArray(at)),l))&&this.error("unexpected ;"),this.seenFor=this.seenImport=this.seenExport=!1,m="TERMINATOR";else if("*"===y&&"EXPORT"===(null==s?void 0:s[0]))m="EXPORT_ALL";else if(0<=t.call(j,y))m="MATH";else if(0<=t.call(p,y))m="COMPARE";else if(0<=t.call(d,y))m="COMPOUND_ASSIGN";else if(0<=t.call(ot,y))m="UNARY";else if(0<=t.call(ut,y))m="UNARY_MATH";else if(0<=t.call(Q,y))m="SHIFT";else if("?"===y&&(null==s?void 0:s.spaced))m="BIN?";else if(s)if("("===y&&!s.spaced&&(c=s[0],0<=t.call(o,c)))"?"===s[0]&&(s[0]="FUNC_EXIST"),m="CALL_START";else if("["===y&&((h=s[0],0<=t.call(L,h))&&!s.spaced||"::"===s[0]))switch(m="INDEX_START",s[0]){case"?":s[0]="INDEX_SOAK"}return g=this.makeToken(m,y),"("===y||"{"===y||"["===y?this.ends.push({tag:O[y],origin:g}):")"===y||"}"===y||"]"===y?this.pair(y):void 0,this.tokens.push(this.makeToken(m,y)),y.length}},{key:"tagParameters",value:function(){var t,n,r,i,s;if(")"!==this.tag())return this;for(r=[],s=this.tokens,t=s.length,n=s[--t],n[0]="PARAM_END";i=s[--t];)switch(i[0]){case")":r.push(i);break;case"(":case"CALL_START":if(!r.length)return"("===i[0]?(i[0]="PARAM_START",this):(n[0]="CALL_END",this);r.pop()}return this}},{key:"closeIndentation",value:function(){return this.outdentToken(this.indent)}},{key:"matchWithInterpolations",value:function(r,i,s,o){var u,a,f,l,c,h,p,d,v,m,g,y,b,w,E,S,x,T,N,C,k,L;if(null==s&&(s=i),null==o&&(o=/^#\{/),L=[],S=i.length,this.chunk.slice(0,S)!==i)return null;for(C=this.chunk.slice(S);;){var A=r.exec(C),O=_slicedToArray(A,1);if(k=O[0],this.validateEscapes(k,{isRegex:"/"===i.charAt(0),offsetInChunk:S}),L.push(this.makeToken("NEOSTRING",k,S)),C=C.slice(k.length),S+=k.length,!(w=o.exec(C)))break;var M=w,_=_slicedToArray(M,1);g=_[0],m=g.length-1;var D=this.getLineAndColumnFromChunk(S+m),P=_slicedToArray(D,2);b=P[0],p=P[1],N=C.slice(m);var H=(new e).tokenize(N,{line:b,column:p,untilBalanced:!0});if(E=H.tokens,v=H.index,v+=m,c="}"===C[v-1],c){var B,j,F,I;B=E,j=_slicedToArray(B,1),x=j[0],B,F=n.call(E,-1),I=_slicedToArray(F,1),h=I[0],F,x[0]=x[1]="(",h[0]=h[1]=")",h.origin=["","end of interpolation",h[2]]}"TERMINATOR"===(null==(T=E[1])?void 0:T[0])&&E.splice(1,1),c||(x=this.makeToken("(","(",S,0),h=this.makeToken(")",")",S+v,0),E=[x].concat(_toConsumableArray(E),[h])),L.push(["TOKENS",E]),C=C.slice(v),S+=v}return C.slice(0,s.length)!==s&&this.error("missing "+s,{length:i.length}),u=L,a=_slicedToArray(u,1),d=a[0],u,f=n.call(L,-1),l=_slicedToArray(f,1),y=l[0],f,d[2].first_column-=i.length,"\n"===y[1].substr(-1)?(y[2].last_line+=1,y[2].last_column=s.length-1):y[2].last_column+=s.length,0===y[1].length&&(y[2].last_column-=1),{tokens:L,index:S+s.length}}},{key:"mergeInterpolationTokens",value:function(t,r,i){var s,o,u,a,f,l,c,h,p,d,v,m,g,y,b,w,E,S,x;for(1u&&(g=this.token("+","+"),g[2]={first_line:d[2].first_line,first_column:d[2].first_column,last_line:d[2].first_line,last_column:d[2].first_column}),(T=this.tokens).push.apply(T,_toConsumableArray(E))}if(v){var L=n.call(t,-1),A=_slicedToArray(L,1);return c=A[0],v.origin=["STRING",null,{first_line:v[2].first_line,first_column:v[2].first_column,last_line:c[2].last_line,last_column:c[2].last_column}],v[2]=v.origin[2],y=this.token("STRING_END",")"),y[2]={first_line:c[2].last_line,first_column:c[2].last_column,last_line:c[2].last_line,last_column:c[2].last_column}}}},{key:"pair",value:function(t){var r,i,s,o,u,a,f;if(u=this.ends,r=n.call(u,-1),i=_slicedToArray(r,1),o=i[0],r,t!==(f=null==o?void 0:o.tag)){var l,c;return"OUTDENT"!==f&&this.error("unmatched "+t),a=this.indents,l=n.call(a,-1),c=_slicedToArray(l,1),s=c[0],l,this.outdentToken(s,!0),this.pair(t)}return this.ends.pop()}},{key:"getLineAndColumnFromChunk",value:function(t){var r,i,s,o,u;if(0===t)return[this.chunkLine,this.chunkColumn];if(u=t>=this.chunk.length?this.chunk:this.chunk.slice(0,+(t-1)+1||9e9),s=dt(u,"\n"),r=this.chunkColumn,0t)?i(t):(n=_Mathfloor((t-65536)/1024)+55296,r=(t-65536)%1024+56320,""+i(n)+i(r))}},{key:"replaceUnicodeCodePointEscapes",value:function(n,r){var i=this,s;return s=null!=r.flags&&0>t.call(r.flags,"u"),n.replace(ft,function(e,t,n,o){var u;return t?t:(u=parseInt(n,16),1114111t.call([].concat(_toConsumableArray(_),_toConsumableArray(l)),e):return"keyword '"+n+"' can't be assigned";case 0>t.call(Y,e):return"'"+n+"' can't be assigned";case 0>t.call(J,e):return"reserved word '"+n+"' can't be assigned";default:return!1}},e.isUnassignable=gt,mt=function(e){var t;return"IDENTIFIER"===e[0]?("from"===e[1]&&(e[1][0]="IDENTIFIER",!0),!0):"FOR"!==e[0]&&"{"!==(t=e[1])&&"["!==t&&","!==t&&":"!==t},_=["true","false","null","this","new","delete","typeof","in","instanceof","return","throw","break","continue","debugger","yield","await","if","else","switch","for","while","do","try","catch","finally","class","extends","super","import","export","default"],l=["undefined","Infinity","NaN","then","unless","until","loop","of","by","when"],f={and:"&&",or:"||",is:"==",isnt:"!=",not:"!",yes:"true",no:"false",on:"true",off:"false"},a=function(){var e;for(yt in e=[],f)e.push(yt);return e}(),l=l.concat(a),J=["case","function","var","void","with","const","let","enum","native","implements","interface","package","private","protected","public","static"],Y=["arguments","eval"],e.JS_FORBIDDEN=_.concat(J).concat(Y),i=65279,C=/^(?!\d)((?:(?!\s)[$\w\x7f-\uffff])+)([^\n\S]*:(?!:))?/,g=/^(?![\d<])((?:(?!\s)[\.\-$\w\x7f-\uffff])+)/,m=/^()>/,v=/^(?!\d)((?:(?!\s)[\-$\w\x7f-\uffff])+)([^\S]*=(?!=))?/,q=/^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i,R=/^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>*\/%])\2=?|\?(\.|::)|\.{2,3})/,ct=/^[^\n\S]+/,c=/^\s*###([^#][\s\S]*?)(?:###[^\n\S]*|###$)|^(?:\s*#(?!##[^#]).*)+/,u=/^[-=]>/,F=/^(?:\n[^\n\S]*)+/,M=/^`(?!``)((?:[^`\\]|\\[\s\S])*)`/,N=/^```((?:[^`\\]|\\[\s\S]|`(?!``))*)```/,rt=/^(?:'''|"""|'|")/,nt=/^(?:[^\\']|\\[\s\S])*/,Z=/^(?:[^\\"#]|\\[\s\S]|\#(?!\{))*/,S=/^(?:[^\\']|\\[\s\S]|'(?!''))*/,w=/^(?:[^\\"#]|\\[\s\S]|"(?!"")|\#(?!\{))*/,A=/^(?:[^\{<])*/,y=/^(?:\{|<(?!\/))/,tt=/((?:\\\\)+)|\\[^\S\n]*\n\s*/g,G=/\s*\n\s*/g,E=/\n+([^\n\S]*)(?=\S)/g,z=/^\/(?!\/)((?:[^[\/\n\\]|\\[^\n]|\[(?:\\[^\n]|[^\]\n\\])*\])*)(\/)?/,W=/^\w*/,lt=/^(?!.*(.).*\1)[imguy]*$/,x=/^(?:[^\\\/#\s]|\\[\s\S]|\/(?!\/\/)|\#(?!\{)|\s+(?:#(?!\{).*)?)*/,T=/((?:\\\\)+)|\\(\s)|\s+(?:#.*)?/g,X=/^(\/|\/{3}\s*)(\*)/,U=/^\/=?\s/,b=/\*\//,H=/^\s*(?:,|\??\.(?![.\d])|::)/,et=/((?:^|[^\\])(?:\\\\)*)\\(?:(0[0-7]|[1-7])|(x(?![\da-fA-F]{2}).{0,2})|(u\{(?![\da-fA-F]{1,}\})[^}]*\}?)|(u(?!\{|[\da-fA-F]{4}).{0,4}))/,V=/((?:^|[^\\])(?:\\\\)*)\\(?:(0[0-7])|(x(?![\da-fA-F]{2}).{0,2})|(u\{(?![\da-fA-F]{1,}\})[^}]*\}?)|(u(?!\{|[\da-fA-F]{4}).{0,4}))/,ft=/(\\\\)|\\u\{([\da-fA-F]+)\}/g,D=/^[^\n\S]*\n/,it=/\n[^\n\S]*$/,st=/\s+$/,d=["-=","+=","/=","*=","%=","||=","&&=","?=","<<=",">>=",">>>=","&=","^=","|=","**=","//=","%%="],ot=["NEW","TYPEOF","DELETE","DO"],ut=["!","~"],Q=["<<",">>",">>>"],p=["==","!=","<",">","<=",">="],j=["*","/","%","//","%%"],$=["IN","OF","INSTANCEOF"],s=["TRUE","FALSE"],o=["IDENTIFIER","PROPERTY",")","]","?","@","THIS","SUPER"],L=o.concat(["NUMBER","INFINITY","NAN","STRING","STRING_END","REGEX","REGEX_END","BOOL","NULL","UNDEFINED","}","::"]),h=["IDENTIFIER",")","]","NUMBER"],I=L.concat(["++","--"]),P=["INDENT","OUTDENT","TERMINATOR"],k=[")","}","]"],at=["\\",".","?.","?::","UNARY","MATH","UNARY_MATH","+","-","**","SHIFT","RELATION","COMPARE","&","^","|","&&","||","BIN?","EXTENDS"]}.call(this),{exports:e}.exports}(),require["./parser"]=function(){var e={},t={exports:e},n=function(){function e(){this.yy={}}var t=function(e,t,n,r){for(n=n||{},r=e.length;r--;n[e[r]]=t);return n},n=[1,24],r=[1,56],i=[1,91],s=[1,92],o=[1,87],u=[1,93],a=[1,94],f=[1,89],l=[1,90],c=[1,64],h=[1,66],p=[1,67],d=[1,68],v=[1,69],m=[1,70],g=[1,72],y=[1,73],b=[1,58],w=[1,42],E=[1,36],S=[1,76],x=[1,77],T=[1,86],N=[1,54],C=[1,59],k=[1,60],L=[1,74],A=[1,75],O=[1,47],M=[1,55],_=[1,71],D=[1,81],P=[1,82],H=[1,83],B=[1,84],j=[1,53],F=[1,80],I=[1,38],q=[1,39],R=[1,40],U=[1,41],z=[1,43],W=[1,44],X=[1,95],V=[1,6,36,47,146],$=[1,6,35,36,47,69,70,93,127,135,146,149,157],J=[1,113],K=[1,114],Q=[1,115],G=[1,110],Y=[1,98],Z=[1,97],et=[1,96],tt=[1,99],nt=[1,100],rt=[1,101],it=[1,102],st=[1,103],ot=[1,104],ut=[1,105],at=[1,106],ft=[1,107],lt=[1,108],ct=[1,109],ht=[1,117],pt=[1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,157,174,178,179,182,183,184,185,186,187,188,189,190,191,192,193],dt=[2,196],vt=[1,123],mt=[1,128],gt=[1,124],yt=[1,125],bt=[1,126],wt=[1,129],Et=[1,122],St=[1,6,35,36,47,69,70,93,127,135,146,148,149,150,156,157,174],xt=[1,6,35,36,45,46,47,69,70,80,81,83,88,93,101,102,103,105,109,125,126,127,135,146,148,149,150,156,157,174,178,179,182,183,184,185,186,187,188,189,190,191,192,193],Tt=[2,122],Nt=[2,126],Ct=[6,35,88,93],kt=[2,99],Lt=[1,141],At=[1,135],Ot=[1,140],Mt=[1,144],_t=[1,149],Dt=[1,147],Pt=[1,151],Ht=[1,155],Bt=[1,153],jt=[1,6,35,36,45,46,47,61,69,70,80,81,83,88,93,101,102,103,105,109,125,126,127,135,146,148,149,150,156,157,174,178,179,182,183,184,185,186,187,188,189,190,191,192,193],Ft=[2,119],It=[1,6,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,157,174,178,179,182,183,184,185,186,187,188,189,190,191,192,193],qt=[2,31],Rt=[1,183],Ut=[2,86],zt=[1,187],Wt=[1,193],Xt=[1,208],Vt=[1,203],$t=[1,212],Jt=[1,209],Kt=[1,214],Qt=[1,215],Gt=[1,217],Yt=[14,32,35,38,39,43,45,46,49,50,54,55,56,57,58,59,68,77,84,85,86,90,91,107,110,112,120,129,130,140,144,145,148,150,153,156,167,173,176,177,178,179,180,181],Zt=[1,6,35,36,45,46,47,61,69,70,80,81,83,88,93,101,102,103,105,109,111,125,126,127,135,146,148,149,150,156,157,174,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194],en=[1,228],tn=[2,142],nn=[1,250],rn=[1,245],sn=[1,256],on=[1,6,35,36,45,46,47,65,69,70,80,81,83,88,93,101,102,103,105,109,125,126,127,135,146,148,149,150,156,157,174,178,179,182,183,184,185,186,187,188,189,190,191,192,193],un=[1,6,33,35,36,45,46,47,61,65,69,70,80,81,83,88,93,101,102,103,105,109,111,117,125,126,127,135,146,148,149,150,156,157,164,165,166,174,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194],an=[1,6,35,36,45,46,47,52,65,69,70,80,81,83,88,93,101,102,103,105,109,125,126,127,135,146,148,149,150,156,157,174,178,179,182,183,184,185,186,187,188,189,190,191,192,193],fn=[1,286],ln=[45,46,126],cn=[1,297],hn=[1,296],pn=[6,35],dn=[2,97],vn=[1,303],mn=[6,35,36,88,93],gn=[6,35,36,61,70,88,93],yn=[1,6,35,36,47,69,70,80,81,83,88,93,101,102,103,105,109,127,135,146,148,149,150,156,157,174,178,179,182,183,184,185,186,187,188,189,190,191,192,193],bn=[1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,157,174,178,179,183,184,185,186,187,188,189,190,191,192,193],wn=[2,347],En=[1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,157,174,178,179,183,185,186,187,188,189,190,191,192,193],Sn=[45,46,80,81,101,102,103,105,125,126],xn=[1,330],Tn=[1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,157,174],Nn=[2,84],Cn=[1,346],kn=[1,348],Ln=[1,353],An=[1,355],On=[6,35,69,93],Mn=[2,221],_n=[2,222],Dn=[1,6,35,36,45,46,47,61,69,70,80,81,83,88,93,101,102,103,105,109,125,126,127,135,146,148,149,150,156,157,164,165,166,174,178,179,182,183,184,185,186,187,188,189,190,191,192,193],Pn=[1,369],Hn=[6,14,32,35,36,38,39,43,45,46,49,50,54,55,56,57,58,59,68,69,70,77,84,85,86,90,91,93,107,110,112,120,129,130,140,144,145,148,150,153,156,167,173,176,177,178,179,180,181],Bn=[6,35,36,69,93],jn=[6,35,36,69,93,127],Fn=[1,6,35,36,45,46,47,61,65,69,70,80,81,83,88,93,101,102,103,105,109,111,125,126,127,135,146,148,149,150,156,157,164,165,166,174,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194],In=[1,6,35,36,47,69,70,83,88,93,109,127,135,146,157,174],qn=[1,6,35,36,47,69,70,83,88,93,109,127,135,146,149,157,174],Rn=[2,273],Un=[164,165,166],zn=[93,164,165,166],Wn=[6,35,109],Xn=[1,393],Vn=[6,35,36,93,109],$n=[6,35,36,65,93,109],Jn=[1,399],Kn=[1,400],Qn=[6,35,36,61,65,70,80,81,93,109,126],Gn=[6,35,36,70,80,81,93,109,126],Yn=[1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,157,174,178,179,185,186,187,188,189,190,191,192,193],Zn=[2,339],er=[2,338],tr=[1,6,35,36,45,46,47,52,69,70,80,81,83,88,93,101,102,103,105,109,125,126,127,135,146,148,149,150,156,157,174,178,179,182,183,184,185,186,187,188,189,190,191,192,193],nr=[1,422],rr=[14,32,38,39,43,45,46,49,50,54,55,56,57,58,59,68,77,83,84,85,86,90,91,107,110,112,120,129,130,140,144,145,148,150,153,156,167,173,176,177,178,179,180,181],ir=[2,207],sr=[6,35,36],or=[2,98],ur=[1,431],ar=[1,432],fr=[1,6,35,36,47,69,70,80,81,83,88,93,101,102,103,105,109,127,135,142,143,146,148,149,150,156,157,169,171,174,178,179,182,183,184,185,186,187,188,189,190,191,192,193],lr=[1,312],cr=[36,169,171],hr=[1,6,36,47,69,70,83,88,93,109,127,135,146,149,157,174],pr=[1,467],dr=[1,473],vr=[1,6,35,36,47,69,70,93,127,135,146,149,157,174],mr=[2,113],gr=[1,486],yr=[1,487],br=[6,35,36,69],wr=[1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,157,169,174,178,179,182,183,184,185,186,187,188,189,190,191,192,193],Er=[1,6,35,36,47,69,70,93,127,135,146,149,157,169],Sr=[2,286],xr=[2,287],Tr=[2,302],Nr=[1,510],Cr=[1,511],kr=[6,35,36,109],Lr=[1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,150,156,157,174],Ar=[1,532],Or=[6,35,36,93,127],Mr=[6,35,36,93],_r=[1,6,35,36,47,69,70,83,88,93,109,127,135,142,146,148,149,150,156,157,174,178,179,182,183,184,185,186,187,188,189,190,191,192,193],Dr=[35,93],Pr=[1,560],Hr=[1,561],Br=[1,567],jr=[1,568],Fr=[2,258],Ir=[2,261],qr=[2,274],Rr=[1,617],Ur=[1,618],zr=[2,288],Wr=[2,292],Xr=[2,289],Vr=[2,293],$r=[2,290],Jr=[2,291],Kr=[2,303],Qr=[2,304],Gr=[1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,174],Yr=[2,294],Zr=[2,296],ei=[2,298],ti=[2,300],ni=[2,295],ri=[2,297],ii=[2,299],si=[2,301],oi={trace:function(){},yy:{},symbols_:{error:2,Root:3,Body:4,Line:5,TERMINATOR:6,Expression:7,ExpressionLine:8,Statement:9,FuncDirective:10,YieldReturn:11,AwaitReturn:12,Return:13,STATEMENT:14,Import:15,Export:16,Value:17,Code:18,Operation:19,Assign:20,If:21,Try:22,While:23,For:24,Switch:25,Class:26,Throw:27,Yield:28,CodeLine:29,IfLine:30,OperationLine:31,YIELD:32,FROM:33,Block:34,INDENT:35,OUTDENT:36,Identifier:37,IDENTIFIER:38,CSX_TAG:39,Property:40,PROPERTY:41,AlphaNumeric:42,NUMBER:43,String:44,STRING:45,STRING_START:46,STRING_END:47,Regex:48,REGEX:49,REGEX_START:50,Invocation:51,REGEX_END:52,Literal:53,JS:54,UNDEFINED:55,NULL:56,BOOL:57,INFINITY:58,NAN:59,Assignable:60,"=":61,AssignObj:62,ObjAssignable:63,ObjRestValue:64,":":65,SimpleObjAssignable:66,ThisProperty:67,"[":68,"]":69,"...":70,ObjSpreadExpr:71,ObjSpreadIdentifier:72,Object:73,Parenthetical:74,Super:75,This:76,SUPER:77,Arguments:78,ObjSpreadAccessor:79,".":80,INDEX_START:81,IndexValue:82,INDEX_END:83,RETURN:84,AWAIT:85,PARAM_START:86,ParamList:87,PARAM_END:88,FuncGlyph:89,"->":90,"=>":91,OptComma:92,",":93,Param:94,ParamVar:95,Array:96,Splat:97,SimpleAssignable:98,Accessor:99,Range:100,"?.":101,"::":102,"?::":103,Index:104,INDEX_SOAK:105,Slice:106,"{":107,AssignList:108,"}":109,CLASS:110,EXTENDS:111,IMPORT:112,ImportDefaultSpecifier:113,ImportNamespaceSpecifier:114,ImportSpecifierList:115,ImportSpecifier:116,AS:117,DEFAULT:118,IMPORT_ALL:119,EXPORT:120,ExportSpecifierList:121,EXPORT_ALL:122,ExportSpecifier:123,OptFuncExist:124,FUNC_EXIST:125,CALL_START:126,CALL_END:127,ArgList:128,THIS:129,"@":130,Elisions:131,ArgElisionList:132,OptElisions:133,RangeDots:134,"..":135,Arg:136,ArgElision:137,Elision:138,SimpleArgs:139,TRY:140,Catch:141,FINALLY:142,CATCH:143,THROW:144,"(":145,")":146,WhileLineSource:147,WHILE:148,WHEN:149,UNTIL:150,WhileSource:151,Loop:152,LOOP:153,ForBody:154,ForLineBody:155,FOR:156,BY:157,ForStart:158,ForSource:159,ForLineSource:160,ForVariables:161,OWN:162,ForValue:163,FORIN:164,FOROF:165,FORFROM:166,SWITCH:167,Whens:168,ELSE:169,When:170,LEADING_WHEN:171,IfBlock:172,IF:173,POST_IF:174,IfBlockLine:175,UNARY:176,UNARY_MATH:177,"-":178,"+":179,"--":180,"++":181,"?":182,MATH:183,"**":184,SHIFT:185,COMPARE:186,"&":187,"^":188,"|":189,"&&":190,"||":191,"BIN?":192,RELATION:193,COMPOUND_ASSIGN:194,$accept:0,$end:1},terminals_:{2:"error",6:"TERMINATOR",14:"STATEMENT",32:"YIELD",33:"FROM",35:"INDENT",36:"OUTDENT",38:"IDENTIFIER",39:"CSX_TAG",41:"PROPERTY",43:"NUMBER",45:"STRING",46:"STRING_START",47:"STRING_END",49:"REGEX",50:"REGEX_START",52:"REGEX_END",54:"JS",55:"UNDEFINED",56:"NULL",57:"BOOL",58:"INFINITY",59:"NAN",61:"=",65:":",68:"[",69:"]",70:"...",77:"SUPER",80:".",81:"INDEX_START",83:"INDEX_END",84:"RETURN",85:"AWAIT",86:"PARAM_START",88:"PARAM_END",90:"->",91:"=>",93:",",101:"?.",102:"::",103:"?::",105:"INDEX_SOAK",107:"{",109:"}",110:"CLASS",111:"EXTENDS",112:"IMPORT",117:"AS",118:"DEFAULT",119:"IMPORT_ALL",120:"EXPORT",122:"EXPORT_ALL",125:"FUNC_EXIST",126:"CALL_START",127:"CALL_END",129:"THIS",130:"@",135:"..",140:"TRY",142:"FINALLY",143:"CATCH",144:"THROW",145:"(",146:")",148:"WHILE",149:"WHEN",150:"UNTIL",153:"LOOP",156:"FOR",157:"BY",162:"OWN",164:"FORIN",165:"FOROF",166:"FORFROM",167:"SWITCH",169:"ELSE",171:"LEADING_WHEN",173:"IF",174:"POST_IF",176:"UNARY",177:"UNARY_MATH",178:"-",179:"+",180:"--",181:"++",182:"?",183:"MATH",184:"**",185:"SHIFT",186:"COMPARE",187:"&",188:"^",189:"|",190:"&&",191:"||",192:"BIN?",193:"RELATION",194:"COMPOUND_ASSIGN"},productions_:[0,[3,0],[3,1],[4,1],[4,3],[4,2],[5,1],[5,1],[5,1],[5,1],[10,1],[10,1],[9,1],[9,1],[9,1],[9,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[8,1],[8,1],[8,1],[28,1],[28,2],[28,3],[34,2],[34,3],[37,1],[37,1],[40,1],[42,1],[42,1],[44,1],[44,3],[48,1],[48,3],[53,1],[53,1],[53,1],[53,1],[53,1],[53,1],[53,1],[53,1],[20,3],[20,4],[20,5],[62,1],[62,1],[62,3],[62,5],[62,3],[62,5],[66,1],[66,1],[66,1],[66,3],[63,1],[63,1],[64,2],[64,2],[64,2],[64,2],[71,1],[71,1],[71,1],[71,1],[71,1],[71,2],[71,2],[71,2],[72,2],[72,2],[79,2],[79,3],[13,2],[13,4],[13,1],[11,3],[11,2],[12,3],[12,2],[18,5],[18,2],[29,5],[29,2],[89,1],[89,1],[92,0],[92,1],[87,0],[87,1],[87,3],[87,4],[87,6],[94,1],[94,2],[94,2],[94,3],[94,1],[95,1],[95,1],[95,1],[95,1],[97,2],[97,2],[98,1],[98,2],[98,2],[98,1],[60,1],[60,1],[60,1],[17,1],[17,1],[17,1],[17,1],[17,1],[17,1],[17,1],[75,3],[75,4],[99,2],[99,2],[99,2],[99,2],[99,1],[99,1],[104,3],[104,2],[82,1],[82,1],[73,4],[108,0],[108,1],[108,3],[108,4],[108,6],[26,1],[26,2],[26,3],[26,4],[26,2],[26,3],[26,4],[26,5],[15,2],[15,4],[15,4],[15,5],[15,7],[15,6],[15,9],[115,1],[115,3],[115,4],[115,4],[115,6],[116,1],[116,3],[116,1],[116,3],[113,1],[114,3],[16,3],[16,5],[16,2],[16,4],[16,5],[16,6],[16,3],[16,5],[16,4],[16,7],[121,1],[121,3],[121,4],[121,4],[121,6],[123,1],[123,3],[123,3],[123,1],[123,3],[51,3],[51,3],[51,3],[124,0],[124,1],[78,2],[78,4],[76,1],[76,1],[67,2],[96,2],[96,3],[96,4],[134,1],[134,1],[100,5],[100,5],[106,3],[106,2],[106,3],[106,2],[106,2],[106,1],[128,1],[128,3],[128,4],[128,4],[128,6],[136,1],[136,1],[136,1],[136,1],[132,1],[132,3],[132,4],[132,4],[132,6],[137,1],[137,2],[133,1],[133,2],[131,1],[131,2],[138,1],[139,1],[139,1],[139,3],[139,3],[22,2],[22,3],[22,4],[22,5],[141,3],[141,3],[141,2],[27,2],[27,4],[74,3],[74,5],[147,2],[147,4],[147,2],[147,4],[151,2],[151,4],[151,4],[151,2],[151,4],[151,4],[23,2],[23,2],[23,2],[23,2],[23,1],[152,2],[152,2],[24,2],[24,2],[24,2],[24,2],[154,2],[154,4],[154,2],[155,4],[155,2],[158,2],[158,3],[163,1],[163,1],[163,1],[163,1],[161,1],[161,3],[159,2],[159,2],[159,4],[159,4],[159,4],[159,4],[159,4],[159,4],[159,6],[159,6],[159,6],[159,6],[159,6],[159,6],[159,6],[159,6],[159,2],[159,4],[159,4],[160,2],[160,2],[160,4],[160,4],[160,4],[160,4],[160,4],[160,4],[160,6],[160,6],[160,6],[160,6],[160,6],[160,6],[160,6],[160,6],[160,2],[160,4],[160,4],[25,5],[25,5],[25,7],[25,7],[25,4],[25,6],[168,1],[168,2],[170,3],[170,4],[172,3],[172,5],[21,1],[21,3],[21,3],[21,3],[175,3],[175,5],[30,1],[30,3],[30,3],[30,3],[31,2],[19,2],[19,2],[19,2],[19,2],[19,2],[19,2],[19,2],[19,2],[19,2],[19,2],[19,3],[19,3],[19,3],[19,3],[19,3],[19,3],[19,3],[19,3],[19,3],[19,3],[19,3],[19,3],[19,3],[19,3],[19,5],[19,4]],performAction:function(e,t,n,r,i,s,o){var u=s.length-1;switch(i){case 1:return this.$=r.addDataToNode(r,o[u],o[u])(new r.Block);case 2:return this.$=s[u];case 3:this.$=r.addDataToNode(r,o[u],o[u])(r.Block.wrap([s[u]]));break;case 4:this.$=r.addDataToNode(r,o[u-2],o[u])(s[u-2].push(s[u]));break;case 5:this.$=s[u-1];break;case 6:case 7:case 8:case 9:case 10:case 11:case 12:case 14:case 15:case 16:case 17:case 18:case 19:case 20:case 21:case 22:case 23:case 24:case 25:case 26:case 27:case 28:case 29:case 30:case 40:case 45:case 47:case 57:case 62:case 63:case 64:case 66:case 67:case 72:case 73:case 74:case 75:case 76:case 97:case 98:case 109:case 110:case 111:case 112:case 118:case 119:case 122:case 127:case 136:case 221:case 222:case 223:case 225:case 237:case 238:case 280:case 281:case 330:case 336:case 342:this.$=s[u];break;case 13:this.$=r.addDataToNode(r,o[u],o[u])(new r.StatementLiteral(s[u]));break;case 31:this.$=r.addDataToNode(r,o[u],o[u])(new r.Op(s[u],new r.Value(new r.Literal(""))));break;case 32:case 346:case 347:case 348:case 351:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Op(s[u-1],s[u]));break;case 33:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Op(s[u-2].concat(s[u-1]),s[u]));break;case 34:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Block);break;case 35:case 83:case 137:this.$=r.addDataToNode(r,o[u-2],o[u])(s[u-1]);break;case 36:this.$=r.addDataToNode(r,o[u],o[u])(new r.IdentifierLiteral(s[u]));break;case 37:this.$=r.addDataToNode(r,o[u],o[u])(new r.CSXTag(s[u]));break;case 38:this.$=r.addDataToNode(r,o[u],o[u])(new r.PropertyName(s[u]));break;case 39:this.$=r.addDataToNode(r,o[u],o[u])(new r.NumberLiteral(s[u]));break;case 41:this.$=r.addDataToNode(r,o[u],o[u])(new r.StringLiteral(s[u]));break;case 42:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.StringWithInterpolations(s[u-1]));break;case 43:this.$=r.addDataToNode(r,o[u],o[u])(new r.RegexLiteral(s[u]));break;case 44:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.RegexWithInterpolations(s[u-1].args));break;case 46:this.$=r.addDataToNode(r,o[u],o[u])(new r.PassthroughLiteral(s[u]));break;case 48:this.$=r.addDataToNode(r,o[u],o[u])(new r.UndefinedLiteral(s[u]));break;case 49:this.$=r.addDataToNode(r,o[u],o[u])(new r.NullLiteral(s[u]));break;case 50:this.$=r.addDataToNode(r,o[u],o[u])(new r.BooleanLiteral(s[u]));break;case 51:this.$=r.addDataToNode(r,o[u],o[u])(new r.InfinityLiteral(s[u]));break;case 52:this.$=r.addDataToNode(r,o[u],o[u])(new r.NaNLiteral(s[u]));break;case 53:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Assign(s[u-2],s[u]));break;case 54:this.$=r.addDataToNode(r,o[u-3],o[u])(new r.Assign(s[u-3],s[u]));break;case 55:this.$=r.addDataToNode(r,o[u-4],o[u])(new r.Assign(s[u-4],s[u-1]));break;case 56:case 115:case 120:case 121:case 123:case 124:case 125:case 126:case 128:case 282:case 283:this.$=r.addDataToNode(r,o[u],o[u])(new r.Value(s[u]));break;case 58:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Assign(r.addDataToNode(r,o[u-2])(new r.Value(s[u-2])),s[u],"object",{operatorToken:r.addDataToNode(r,o[u-1])(new r.Literal(s[u-1]))}));break;case 59:this.$=r.addDataToNode(r,o[u-4],o[u])(new r.Assign(r.addDataToNode(r,o[u-4])(new r.Value(s[u-4])),s[u-1],"object",{operatorToken:r.addDataToNode(r,o[u-3])(new r.Literal(s[u-3]))}));break;case 60:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Assign(r.addDataToNode(r,o[u-2])(new r.Value(s[u-2])),s[u],null,{operatorToken:r.addDataToNode(r,o[u-1])(new r.Literal(s[u-1]))}));break;case 61:this.$=r.addDataToNode(r,o[u-4],o[u])(new r.Assign(r.addDataToNode(r,o[u-4])(new r.Value(s[u-4])),s[u-1],null,{operatorToken:r.addDataToNode(r,o[u-3])(new r.Literal(s[u-3]))}));break;case 65:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Value(new r.ComputedPropertyName(s[u-1])));break;case 68:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Splat(new r.Value(s[u-1])));break;case 69:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Splat(new r.Value(s[u])));break;case 70:case 113:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Splat(s[u-1]));break;case 71:case 114:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Splat(s[u]));break;case 77:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.SuperCall(r.addDataToNode(r,o[u-1])(new r.Super),s[u],!1,s[u-1]));break;case 78:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Call(new r.Value(s[u-1]),s[u]));break;case 79:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Call(s[u-1],s[u]));break;case 80:case 81:this.$=r.addDataToNode(r,o[u-1],o[u])((new r.Value(s[u-1])).add(s[u]));break;case 82:case 131:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Access(s[u]));break;case 84:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Return(s[u]));break;case 85:this.$=r.addDataToNode(r,o[u-3],o[u])(new r.Return(new r.Value(s[u-1])));break;case 86:this.$=r.addDataToNode(r,o[u],o[u])(new r.Return);break;case 87:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.YieldReturn(s[u]));break;case 88:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.YieldReturn);break;case 89:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.AwaitReturn(s[u]));break;case 90:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.AwaitReturn);break;case 91:this.$=r.addDataToNode(r,o[u-4],o[u])(new r.Code(s[u-3],s[u],s[u-1],r.addDataToNode(r,o[u-4])(new r.Literal(s[u-4]))));break;case 92:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Code([],s[u],s[u-1]));break;case 93:this.$=r.addDataToNode(r,o[u-4],o[u])(new r.Code(s[u-3],r.addDataToNode(r,o[u])(r.Block.wrap([s[u]])),s[u-1],r.addDataToNode(r,o[u-4])(new r.Literal(s[u-4]))));break;case 94:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Code([],r.addDataToNode(r,o[u])(r.Block.wrap([s[u]])),s[u-1]));break;case 95:case 96:this.$=r.addDataToNode(r,o[u],o[u])(new r.FuncGlyph(s[u]));break;case 99:case 142:case 232:this.$=r.addDataToNode(r,o[u],o[u])([]);break;case 100:case 143:case 162:case 183:case 216:case 230:case 234:case 284:this.$=r.addDataToNode(r,o[u],o[u])([s[u]]);break;case 101:case 144:case 163:case 184:case 217:case 226:this.$=r.addDataToNode(r,o[u-2],o[u])(s[u-2].concat(s[u]));break;case 102:case 145:case 164:case 185:case 218:this.$=r.addDataToNode(r,o[u-3],o[u])(s[u-3].concat(s[u]));break;case 103:case 146:case 166:case 187:case 220:this.$=r.addDataToNode(r,o[u-5],o[u])(s[u-5].concat(s[u-2]));break;case 104:this.$=r.addDataToNode(r,o[u],o[u])(new r.Param(s[u]));break;case 105:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Param(s[u-1],null,!0));break;case 106:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Param(s[u],null,!0));break;case 107:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Param(s[u-2],s[u]));break;case 108:case 224:this.$=r.addDataToNode(r,o[u],o[u])(new r.Expansion);break;case 116:this.$=r.addDataToNode(r,o[u-1],o[u])(s[u-1].add(s[u]));break;case 117:this.$=r.addDataToNode(r,o[u-1],o[u])((new r.Value(s[u-1])).add(s[u]));break;case 129:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Super(r.addDataToNode(r,o[u])(new r.Access(s[u])),[],!1,s[u-2]));break;case 130:this.$=r.addDataToNode(r,o[u-3],o[u])(new r.Super(r.addDataToNode(r,o[u-1])(new r.Index(s[u-1])),[],!1,s[u-3]));break;case 132:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Access(s[u],"soak"));break;case 133:this.$=r.addDataToNode(r,o[u-1],o[u])([r.addDataToNode(r,o[u-1])(new r.Access(new r.PropertyName("prototype"))),r.addDataToNode(r,o[u])(new r.Access(s[u]))]);break;case 134:this.$=r.addDataToNode(r,o[u-1],o[u])([r.addDataToNode(r,o[u-1])(new r.Access(new r.PropertyName("prototype"),"soak")),r.addDataToNode(r,o[u])(new r.Access(s[u]))]);break;case 135:this.$=r.addDataToNode(r,o[u],o[u])(new r.Access(new r.PropertyName("prototype")));break;case 138:this.$=r.addDataToNode(r,o[u-1],o[u])(r.extend(s[u],{soak:!0}));break;case 139:this.$=r.addDataToNode(r,o[u],o[u])(new r.Index(s[u]));break;case 140:this.$=r.addDataToNode(r,o[u],o[u])(new r.Slice(s[u]));break;case 141:this.$=r.addDataToNode(r,o[u-3],o[u])(new r.Obj(s[u-2],s[u-3].generated));break;case 147:this.$=r.addDataToNode(r,o[u],o[u])(new r.Class);break;case 148:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Class(null,null,s[u]));break;case 149:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Class(null,s[u]));break;case 150:this.$=r.addDataToNode(r,o[u-3],o[u])(new r.Class(null,s[u-1],s[u]));break;case 151:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Class(s[u]));break;case 152:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Class(s[u-1],null,s[u]));break;case 153:this.$=r.addDataToNode(r,o[u-3],o[u])(new r.Class(s[u-2],s[u]));break;case 154:this.$=r.addDataToNode(r,o[u-4],o[u])(new r.Class(s[u-3],s[u-1],s[u]));break;case 155:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.ImportDeclaration(null,s[u]));break;case 156:this.$=r.addDataToNode(r,o[u-3],o[u])(new r.ImportDeclaration(new r.ImportClause(s[u-2],null),s[u]));break;case 157:this.$=r.addDataToNode(r,o[u-3],o[u])(new r.ImportDeclaration(new r.ImportClause(null,s[u-2]),s[u]));break;case 158:this.$=r.addDataToNode(r,o[u-4],o[u])(new r.ImportDeclaration(new r.ImportClause(null,new r.ImportSpecifierList([])),s[u]));break;case 159:this.$=r.addDataToNode(r,o[u-6],o[u])(new r.ImportDeclaration(new r.ImportClause(null,new r.ImportSpecifierList(s[u-4])),s[u]));break;case 160:this.$=r.addDataToNode(r,o[u-5],o[u])(new r.ImportDeclaration(new r.ImportClause(s[u-4],s[u-2]),s[u]));break;case 161:this.$=r.addDataToNode(r,o[u-8],o[u])(new r.ImportDeclaration(new r.ImportClause(s[u-7],new r.ImportSpecifierList(s[u-4])),s[u]));break;case 165:case 186:case 199:case 219:this.$=r.addDataToNode(r,o[u-3],o[u])(s[u-2]);break;case 167:this.$=r.addDataToNode(r,o[u],o[u])(new r.ImportSpecifier(s[u]));break;case 168:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.ImportSpecifier(s[u-2],s[u]));break;case 169:this.$=r.addDataToNode(r,o[u],o[u])(new r.ImportSpecifier(new r.Literal(s[u])));break;case 170:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.ImportSpecifier(new r.Literal(s[u-2]),s[u]));break;case 171:this.$=r.addDataToNode(r,o[u],o[u])(new r.ImportDefaultSpecifier(s[u]));break;case 172:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.ImportNamespaceSpecifier(new r.Literal(s[u-2]),s[u]));break;case 173:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.ExportNamedDeclaration(new r.ExportSpecifierList([])));break;case 174:this.$=r.addDataToNode(r,o[u-4],o[u])(new r.ExportNamedDeclaration(new r.ExportSpecifierList(s[u-2])));break;case 175:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.ExportNamedDeclaration(s[u]));break;case 176:this.$=r.addDataToNode(r,o[u-3],o[u])(new r.ExportNamedDeclaration(new r.Assign(s[u-2],s[u],null,{moduleDeclaration:"export"})));break;case 177:this.$=r.addDataToNode(r,o[u-4],o[u])(new r.ExportNamedDeclaration(new r.Assign(s[u-3],s[u],null,{moduleDeclaration:"export"})));break;case 178:this.$=r.addDataToNode(r,o[u-5],o[u])(new r.ExportNamedDeclaration(new r.Assign(s[u-4],s[u-1],null,{moduleDeclaration:"export"})));break;case 179:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.ExportDefaultDeclaration(s[u]));break;case 180:this.$=r.addDataToNode(r,o[u-4],o[u])(new r.ExportDefaultDeclaration(new r.Value(s[u-1])));break;case 181:this.$=r.addDataToNode(r,o[u-3],o[u])(new r.ExportAllDeclaration(new r.Literal(s[u-2]),s[u]));break;case 182:this.$=r.addDataToNode(r,o[u-6],o[u])(new r.ExportNamedDeclaration(new r.ExportSpecifierList(s[u-4]),s[u]));break;case 188:this.$=r.addDataToNode(r,o[u],o[u])(new r.ExportSpecifier(s[u]));break;case 189:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.ExportSpecifier(s[u-2],s[u]));break;case 190:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.ExportSpecifier(s[u-2],new r.Literal(s[u])));break;case 191:this.$=r.addDataToNode(r,o[u],o[u])(new r.ExportSpecifier(new r.Literal(s[u])));break;case 192:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.ExportSpecifier(new r.Literal(s[u-2]),s[u]));break;case 193:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.TaggedTemplateCall(s[u-2],s[u],s[u-1]));break;case 194:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Call(s[u-2],s[u],s[u-1]));break;case 195:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.SuperCall(r.addDataToNode(r,o[u-2])(new r.Super),s[u],s[u-1],s[u-2]));break;case 196:this.$=r.addDataToNode(r,o[u],o[u])(!1);break;case 197:this.$=r.addDataToNode(r,o[u],o[u])(!0);break;case 198:this.$=r.addDataToNode(r,o[u-1],o[u])([]);break;case 200:case 201:this.$=r.addDataToNode(r,o[u],o[u])(new r.Value(new r.ThisLiteral(s[u])));break;case 202:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Value(r.addDataToNode(r,o[u-1])(new r.ThisLiteral(s[u-1])),[r.addDataToNode(r,o[u])(new r.Access(s[u]))],"this"));break;case 203:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Arr([]));break;case 204:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Arr(s[u-1]));break;case 205:this.$=r.addDataToNode(r,o[u-3],o[u])(new r.Arr([].concat(s[u-2],s[u-1])));break;case 206:this.$=r.addDataToNode(r,o[u],o[u])("inclusive");break;case 207:this.$=r.addDataToNode(r,o[u],o[u])("exclusive");break;case 208:case 209:this.$=r.addDataToNode(r,o[u-4],o[u])(new r.Range(s[u-3],s[u-1],s[u-2]));break;case 210:case 212:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Range(s[u-2],s[u],s[u-1]));break;case 211:case 213:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Range(s[u-1],null,s[u]));break;case 214:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Range(null,s[u],s[u-1]));break;case 215:this.$=r.addDataToNode(r,o[u],o[u])(new r.Range(null,null,s[u]));break;case 227:this.$=r.addDataToNode(r,o[u-3],o[u])(s[u-3].concat(s[u-2],s[u]));break;case 228:this.$=r.addDataToNode(r,o[u-3],o[u])(s[u-2].concat(s[u-1]));break;case 229:this.$=r.addDataToNode(r,o[u-5],o[u])(s[u-5].concat(s[u-4],s[u-2],s[u-1]));break;case 231:case 235:case 331:this.$=r.addDataToNode(r,o[u-1],o[u])(s[u-1].concat(s[u]));break;case 233:this.$=r.addDataToNode(r,o[u-1],o[u])([].concat(s[u]));break;case 236:this.$=r.addDataToNode(r,o[u],o[u])(new r.Elision);break;case 239:case 240:this.$=r.addDataToNode(r,o[u-2],o[u])([].concat(s[u-2],s[u]));break;case 241:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Try(s[u]));break;case 242:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Try(s[u-1],s[u][0],s[u][1]));break;case 243:this.$=r.addDataToNode(r,o[u-3],o[u])(new r.Try(s[u-2],null,null,s[u]));break;case 244:this.$=r.addDataToNode(r,o[u-4],o[u])(new r.Try(s[u-3],s[u-2][0],s[u-2][1],s[u]));break;case 245:this.$=r.addDataToNode(r,o[u-2],o[u])([s[u-1],s[u]]);break;case 246:this.$=r.addDataToNode(r,o[u-2],o[u])([r.addDataToNode(r,o[u-1])(new r.Value(s[u-1])),s[u]]);break;case 247:this.$=r.addDataToNode(r,o[u-1],o[u])([null,s[u]]);break;case 248:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Throw(s[u]));break;case 249:this.$=r.addDataToNode(r,o[u-3],o[u])(new r.Throw(new r.Value(s[u-1])));break;case 250:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Parens(s[u-1]));break;case 251:this.$=r.addDataToNode(r,o[u-4],o[u])(new r.Parens(s[u-2]));break;case 252:case 256:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.While(s[u]));break;case 253:case 257:case 258:this.$=r.addDataToNode(r,o[u-3],o[u])(new r.While(s[u-2],{guard:s[u]}));break;case 254:case 259:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.While(s[u],{invert:!0}));break;case 255:case 260:case 261:this.$=r.addDataToNode(r,o[u-3],o[u])(new r.While(s[u-2],{invert:!0,guard:s[u]}));break;case 262:case 263:this.$=r.addDataToNode(r,o[u-1],o[u])(s[u-1].addBody(s[u]));break;case 264:case 265:this.$=r.addDataToNode(r,o[u-1],o[u])(s[u].addBody(r.addDataToNode(r,o[u-1])(r.Block.wrap([s[u-1]]))));break;case 266:this.$=r.addDataToNode(r,o[u],o[u])(s[u]);break;case 267:this.$=r.addDataToNode(r,o[u-1],o[u])((new r.While(r.addDataToNode(r,o[u-1])(new r.BooleanLiteral("true")))).addBody(s[u]));break;case 268:this.$=r.addDataToNode(r,o[u-1],o[u])((new r.While(r.addDataToNode(r,o[u-1])(new r.BooleanLiteral("true")))).addBody(r.addDataToNode(r,o[u])(r.Block.wrap([s[u]]))));break;case 269:case 270:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.For(s[u-1],s[u]));break;case 271:case 272:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.For(s[u],s[u-1]));break;case 273:this.$=r.addDataToNode(r,o[u-1],o[u])({source:r.addDataToNode(r,o[u])(new r.Value(s[u]))});break;case 274:case 276:this.$=r.addDataToNode(r,o[u-3],o[u])({source:r.addDataToNode(r,o[u-2])(new r.Value(s[u-2])),step:s[u]});break;case 275:case 277:this.$=r.addDataToNode(r,o[u-1],o[u])(function(){return s[u].own=s[u-1].own,s[u].ownTag=s[u-1].ownTag,s[u].name=s[u-1][0],s[u].index=s[u-1][1],s[u]}());break;case 278:this.$=r.addDataToNode(r,o[u-1],o[u])(s[u]);break;case 279:this.$=r.addDataToNode(r,o[u-2],o[u])(function(){return s[u].own=!0,s[u].ownTag=r.addDataToNode(r,o[u-1])(new r.Literal(s[u-1])),s[u]}());break;case 285:this.$=r.addDataToNode(r,o[u-2],o[u])([s[u-2],s[u]]);break;case 286:case 305:this.$=r.addDataToNode(r,o[u-1],o[u])({source:s[u]});break;case 287:case 306:this.$=r.addDataToNode(r,o[u-1],o[u])({source:s[u],object:!0});break;case 288:case 289:case 307:case 308:this.$=r.addDataToNode(r,o[u-3],o[u])({source:s[u-2],guard:s[u]});break;case 290:case 291:case 309:case 310:this.$=r.addDataToNode(r,o[u-3],o[u])({source:s[u-2],guard:s[u],object:!0});break;case 292:case 293:case 311:case 312:this.$=r.addDataToNode(r,o[u-3],o[u])({source:s[u-2],step:s[u]});break;case 294:case 295:case 296:case 297:case 313:case 314:case 315:case 316:this.$=r.addDataToNode(r,o[u-5],o[u])({source:s[u-4],guard:s[u-2],step:s[u]});break;case 298:case 299:case 300:case 301:case 317:case 318:case 319:case 320:this.$=r.addDataToNode(r,o[u-5],o[u])({source:s[u-4],step:s[u-2],guard:s[u]});break;case 302:case 321:this.$=r.addDataToNode(r,o[u-1],o[u])({source:s[u],from:!0});break;case 303:case 304:case 322:case 323:this.$=r.addDataToNode(r,o[u-3],o[u])({source:s[u-2],guard:s[u],from:!0});break;case 324:case 325:this.$=r.addDataToNode(r,o[u-4],o[u])(new r.Switch(s[u-3],s[u-1]));break;case 326:case 327:this.$=r.addDataToNode(r,o[u-6],o[u])(new r.Switch(s[u-5],s[u-3],s[u-1]));break;case 328:this.$=r.addDataToNode(r,o[u-3],o[u])(new r.Switch(null,s[u-1]));break;case 329:this.$=r.addDataToNode(r,o[u-5],o[u])(new r.Switch(null,s[u-3],s[u-1]));break;case 332:this.$=r.addDataToNode(r,o[u-2],o[u])([[s[u-1],s[u]]]);break;case 333:this.$=r.addDataToNode(r,o[u-3],o[u])([[s[u-2],s[u-1]]]);break;case 334:case 340:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.If(s[u-1],s[u],{type:s[u-2]}));break;case 335:case 341:this.$=r.addDataToNode(r,o[u-4],o[u])(s[u-4].addElse(r.addDataToNode(r,o[u-2],o[u])(new r.If(s[u-1],s[u],{type:s[u-2]}))));break;case 337:case 343:this.$=r.addDataToNode(r,o[u-2],o[u])(s[u-2].addElse(s[u]));break;case 338:case 339:case 344:case 345:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.If(s[u],r.addDataToNode(r,o[u-2])(r.Block.wrap([s[u-2]])),{type:s[u-1],statement:!0}));break;case 349:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Op("-",s[u]));break;case 350:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Op("+",s[u]));break;case 352:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Op("--",s[u]));break;case 353:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Op("++",s[u]));break;case 354:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Op("--",s[u-1],null,!0));break;case 355:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Op("++",s[u-1],null,!0));break;case 356:this.$=r.addDataToNode(r,o[u-1],o[u])(new r.Existence(s[u-1]));break;case 357:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Op("+",s[u-2],s[u]));break;case 358:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Op("-",s[u-2],s[u]));break;case 359:case 360:case 361:case 362:case 363:case 364:case 365:case 366:case 367:case 368:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Op(s[u-1],s[u-2],s[u]));break;case 369:this.$=r.addDataToNode(r,o[u-2],o[u])(function(){return"!"===s[u-1].charAt(0)?(new r.Op(s[u-1].slice(1),s[u-2],s[u])).invert():new r.Op(s[u-1],s[u-2],s[u])}());break;case 370:this.$=r.addDataToNode(r,o[u-2],o[u])(new r.Assign(s[u-2],s[u],s[u-1]));break;case 371:this.$=r.addDataToNode(r,o[u-4],o[u])(new r.Assign(s[u-4],s[u-1],s[u-3]));break;case 372:this.$=r.addDataToNode(r,o[u-3],o[u])(new r.Assign(s[u-3],s[u],s[u-2]))}},table:[{1:[2,1],3:1,4:2,5:3,7:4,8:5,9:6,10:7,11:27,12:28,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:r,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:w,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{1:[3]},{1:[2,2],6:X},t(V,[2,3]),t($,[2,6],{151:111,154:112,158:116,148:J,150:K,156:Q,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t($,[2,7]),t($,[2,8],{158:116,151:118,154:119,148:J,150:K,156:Q,174:ht}),t($,[2,9]),t(pt,[2,16],{124:120,99:121,104:127,45:dt,46:dt,126:dt,80:vt,81:mt,101:gt,102:yt,103:bt,105:wt,125:Et}),t(pt,[2,17],{104:127,99:130,80:vt,81:mt,101:gt,102:yt,103:bt,105:wt}),t(pt,[2,18]),t(pt,[2,19]),t(pt,[2,20]),t(pt,[2,21]),t(pt,[2,22]),t(pt,[2,23]),t(pt,[2,24]),t(pt,[2,25]),t(pt,[2,26]),t(pt,[2,27]),t($,[2,28]),t($,[2,29]),t($,[2,30]),t(St,[2,12]),t(St,[2,13]),t(St,[2,14]),t(St,[2,15]),t($,[2,10]),t($,[2,11]),t(xt,Tt,{61:[1,131]}),t(xt,[2,123]),t(xt,[2,124]),t(xt,[2,125]),t(xt,Nt),t(xt,[2,127]),t(xt,[2,128]),t(Ct,kt,{87:132,94:133,95:134,37:136,67:137,96:138,73:139,38:i,39:s,68:Lt,70:At,107:T,130:Ot}),{5:143,7:4,8:5,9:6,10:7,11:27,12:28,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:r,34:142,35:Mt,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:w,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:145,8:146,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:150,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:156,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:157,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:158,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:[1,159],85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{17:161,18:162,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:163,67:79,68:g,73:62,74:31,75:35,76:34,77:y,86:Pt,89:152,90:S,91:x,96:61,98:160,100:32,107:T,129:L,130:A,145:_},{17:161,18:162,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:163,67:79,68:g,73:62,74:31,75:35,76:34,77:y,86:Pt,89:152,90:S,91:x,96:61,98:164,100:32,107:T,129:L,130:A,145:_},t(jt,Ft,{180:[1,165],181:[1,166],194:[1,167]}),t(pt,[2,336],{169:[1,168]}),{34:169,35:Mt},{34:170,35:Mt},{34:171,35:Mt},t(pt,[2,266]),{34:172,35:Mt},{34:173,35:Mt},{7:174,8:175,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,35:[1,176],37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(It,[2,147],{53:30,74:31,100:32,51:33,76:34,75:35,96:61,73:62,42:63,48:65,37:78,67:79,44:88,89:152,17:161,18:162,60:163,34:177,98:179,35:Mt,38:i,39:s,43:o,45:u,46:a,49:f,50:l,54:c,55:h,56:p,57:d,58:v,59:m,68:g,77:y,86:Pt,90:S,91:x,107:T,111:[1,178],129:L,130:A,145:_}),{7:180,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,35:[1,181],37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t([1,6,35,36,47,69,70,93,127,135,146,148,149,150,156,157,174,182,183,184,185,186,187,188,189,190,191,192,193],qt,{17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,13:23,15:25,16:26,60:29,53:30,74:31,100:32,51:33,76:34,75:35,98:45,172:46,151:48,147:49,152:50,154:51,155:52,96:61,73:62,42:63,48:65,37:78,67:79,158:85,44:88,89:152,9:154,7:182,14:n,32:_t,33:Rt,38:i,39:s,43:o,45:u,46:a,49:f,50:l,54:c,55:h,56:p,57:d,58:v,59:m,68:g,77:y,84:[1,184],85:Dt,86:Pt,90:S,91:x,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,153:H,167:j,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W}),t($,[2,342],{169:[1,185]}),t([1,6,36,47,69,70,93,127,135,146,148,149,150,156,157,174],Ut,{17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,13:23,15:25,16:26,60:29,53:30,74:31,100:32,51:33,76:34,75:35,98:45,172:46,151:48,147:49,152:50,154:51,155:52,96:61,73:62,42:63,48:65,37:78,67:79,158:85,44:88,89:152,9:154,7:186,14:n,32:_t,35:zt,38:i,39:s,43:o,45:u,46:a,49:f,50:l,54:c,55:h,56:p,57:d,58:v,59:m,68:g,77:y,84:b,85:Dt,86:Pt,90:S,91:x,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,153:H,167:j,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W}),{37:192,38:i,39:s,44:188,45:u,46:a,107:[1,191],113:189,114:190,119:Wt},{26:195,37:196,38:i,39:s,107:[1,194],110:N,118:[1,197],122:[1,198]},t(jt,[2,120]),t(jt,[2,121]),t(xt,[2,45]),t(xt,[2,46]),t(xt,[2,47]),t(xt,[2,48]),t(xt,[2,49]),t(xt,[2,50]),t(xt,[2,51]),t(xt,[2,52]),{4:199,5:3,7:4,8:5,9:6,10:7,11:27,12:28,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:r,35:[1,200],37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:w,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:201,8:202,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,35:Xt,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,69:Vt,70:$t,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,93:Jt,96:61,97:211,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,131:204,132:205,136:210,137:207,138:206,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{80:Kt,81:Qt,124:213,125:Et,126:dt},t(xt,[2,200]),t(xt,[2,201],{40:216,41:Gt}),t(Yt,[2,95]),t(Yt,[2,96]),t(Zt,[2,115]),t(Zt,[2,118]),{7:218,8:219,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:220,8:221,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:222,8:223,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:225,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,34:224,35:Mt,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{37:230,38:i,39:s,67:231,68:g,73:233,96:232,100:226,107:T,130:Ot,161:227,162:en,163:229},{159:234,160:235,164:[1,236],165:[1,237],166:[1,238]},t([6,35,93,109],tn,{44:88,108:239,62:240,63:241,64:242,66:243,42:244,71:246,37:247,40:248,67:249,72:251,73:252,74:253,75:254,76:255,38:i,39:s,41:Gt,43:o,45:u,46:a,68:nn,70:rn,77:sn,107:T,129:L,130:A,145:_}),t(on,[2,39]),t(on,[2,40]),t(xt,[2,43]),{17:161,18:162,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:257,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:163,67:79,68:g,73:62,74:31,75:35,76:34,77:y,86:Pt,89:152,90:S,91:x,96:61,98:258,100:32,107:T,129:L,130:A,145:_},t(un,[2,36]),t(un,[2,37]),t(an,[2,41]),{4:259,5:3,7:4,8:5,9:6,10:7,11:27,12:28,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:r,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:w,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(V,[2,5],{7:4,8:5,9:6,10:7,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,13:23,15:25,16:26,11:27,12:28,60:29,53:30,74:31,100:32,51:33,76:34,75:35,89:37,98:45,172:46,151:48,147:49,152:50,154:51,155:52,175:57,96:61,73:62,42:63,48:65,37:78,67:79,158:85,44:88,5:260,14:n,32:r,38:i,39:s,43:o,45:u,46:a,49:f,50:l,54:c,55:h,56:p,57:d,58:v,59:m,68:g,77:y,84:b,85:w,86:E,90:S,91:x,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,148:D,150:P,153:H,156:B,167:j,173:F,176:I,177:q,178:R,179:U,180:z,181:W}),t(pt,[2,356]),{7:261,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:262,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:263,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:264,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:265,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:266,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:267,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:268,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:269,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:270,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:271,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:272,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:273,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:274,8:275,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(pt,[2,265]),t(pt,[2,270]),{7:220,8:276,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:222,8:277,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{37:230,38:i,39:s,67:231,68:g,73:233,96:232,100:278,107:T,130:Ot,161:227,162:en,163:229},{159:234,164:[1,279],165:[1,280],166:[1,281]},{7:282,8:283,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(pt,[2,264]),t(pt,[2,269]),{44:284,45:u,46:a,78:285,126:fn},t(Zt,[2,116]),t(ln,[2,197]),{40:287,41:Gt},{40:288,41:Gt},t(Zt,[2,135],{40:289,41:Gt}),{40:290,41:Gt},t(Zt,[2,136]),{7:292,8:294,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,70:cn,73:62,74:31,75:35,76:34,77:y,82:291,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,106:293,107:T,110:N,112:C,120:k,129:L,130:A,134:295,135:hn,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{81:mt,104:298,105:wt},t(Zt,[2,117]),{6:[1,300],7:299,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,35:[1,301],37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t(pn,dn,{92:304,88:[1,302],93:vn}),t(mn,[2,100]),t(mn,[2,104],{61:[1,306],70:[1,305]}),t(mn,[2,108],{37:136,67:137,96:138,73:139,95:307,38:i,39:s,68:Lt,107:T,130:Ot}),t(gn,[2,109]),t(gn,[2,110]),t(gn,[2,111]),t(gn,[2,112]),{40:216,41:Gt},{7:308,8:309,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,35:Xt,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,69:Vt,70:$t,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,93:Jt,96:61,97:211,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,131:204,132:205,136:210,137:207,138:206,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(yn,[2,92]),t($,[2,94]),{4:311,5:3,7:4,8:5,9:6,10:7,11:27,12:28,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:r,36:[1,310],37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:w,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(bn,wn,{151:111,154:112,158:116,182:et}),t($,[2,346]),{7:158,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{148:J,150:K,151:118,154:119,156:Q,158:116,174:ht},t([1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,157,174,182,183,184,185,186,187,188,189,190,191,192,193],qt,{17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,13:23,15:25,16:26,60:29,53:30,74:31,100:32,51:33,76:34,75:35,98:45,172:46,151:48,147:49,152:50,154:51,155:52,96:61,73:62,42:63,48:65,37:78,67:79,158:85,44:88,89:152,9:154,7:182,14:n,32:_t,33:Rt,38:i,39:s,43:o,45:u,46:a,49:f,50:l,54:c,55:h,56:p,57:d,58:v,59:m,68:g,77:y,84:b,85:Dt,86:Pt,90:S,91:x,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,153:H,167:j,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W}),t(En,[2,348],{151:111,154:112,158:116,182:et,184:nt}),t(Ct,kt,{94:133,95:134,37:136,67:137,96:138,73:139,87:313,38:i,39:s,68:Lt,70:At,107:T,130:Ot}),{34:142,35:Mt},{7:314,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{148:J,150:K,151:118,154:119,156:Q,158:116,174:[1,315]},{7:316,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t(En,[2,349],{151:111,154:112,158:116,182:et,184:nt}),t(En,[2,350],{151:111,154:112,158:116,182:et,184:nt}),t(bn,[2,351],{151:111,154:112,158:116,182:et}),t($,[2,90],{17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,13:23,15:25,16:26,60:29,53:30,74:31,100:32,51:33,76:34,75:35,98:45,172:46,151:48,147:49,152:50,154:51,155:52,96:61,73:62,42:63,48:65,37:78,67:79,158:85,44:88,89:152,9:154,7:317,14:n,32:_t,38:i,39:s,43:o,45:u,46:a,49:f,50:l,54:c,55:h,56:p,57:d,58:v,59:m,68:g,77:y,84:b,85:Dt,86:Pt,90:S,91:x,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,148:Ut,150:Ut,156:Ut,174:Ut,153:H,167:j,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W}),t(pt,[2,352],{45:Ft,46:Ft,80:Ft,81:Ft,101:Ft,102:Ft,103:Ft,105:Ft,125:Ft,126:Ft}),t(ln,dt,{124:120,99:121,104:127,80:vt,81:mt,101:gt,102:yt,103:bt,105:wt,125:Et}),{80:vt,81:mt,99:130,101:gt,102:yt,103:bt,104:127,105:wt},t(Sn,Tt),t(pt,[2,353],{45:Ft,46:Ft,80:Ft,81:Ft,101:Ft,102:Ft,103:Ft,105:Ft,125:Ft,126:Ft}),t(pt,[2,354]),t(pt,[2,355]),{6:[1,320],7:318,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,35:[1,319],37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{34:321,35:Mt,173:[1,322]},t(pt,[2,241],{141:323,142:[1,324],143:[1,325]}),t(pt,[2,262]),t(pt,[2,263]),t(pt,[2,271]),t(pt,[2,272]),{35:[1,326],148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[1,327]},{168:328,170:329,171:xn},t(pt,[2,148]),{7:331,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t(It,[2,151],{34:332,35:Mt,45:Ft,46:Ft,80:Ft,81:Ft,101:Ft,102:Ft,103:Ft,105:Ft,125:Ft,126:Ft,111:[1,333]}),t(Tn,[2,248],{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{73:334,107:T},t(Tn,[2,32],{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{7:335,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t([1,6,36,47,69,70,93,127,135,146,149,157],[2,88],{17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,13:23,15:25,16:26,60:29,53:30,74:31,100:32,51:33,76:34,75:35,98:45,172:46,151:48,147:49,152:50,154:51,155:52,96:61,73:62,42:63,48:65,37:78,67:79,158:85,44:88,89:152,9:154,7:336,14:n,32:_t,35:zt,38:i,39:s,43:o,45:u,46:a,49:f,50:l,54:c,55:h,56:p,57:d,58:v,59:m,68:g,77:y,84:b,85:Dt,86:Pt,90:S,91:x,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,148:Ut,150:Ut,156:Ut,174:Ut,153:H,167:j,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W}),{34:337,35:Mt,173:[1,338]},t(St,Nn,{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{73:339,107:T},t(St,[2,155]),{33:[1,340],93:[1,341]},{33:[1,342]},{35:Cn,37:347,38:i,39:s,109:[1,343],115:344,116:345,118:kn},t([33,93],[2,171]),{117:[1,349]},{35:Ln,37:354,38:i,39:s,109:[1,350],118:An,121:351,123:352},t(St,[2,175]),{61:[1,356]},{7:357,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,35:[1,358],37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{33:[1,359]},{6:X,146:[1,360]},{4:361,5:3,7:4,8:5,9:6,10:7,11:27,12:28,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:r,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:w,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(On,Mn,{151:111,154:112,158:116,134:362,70:[1,363],135:hn,148:J,150:K,156:Q,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(On,_n,{134:364,70:cn,135:hn}),t(Dn,[2,203]),{7:308,8:309,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,69:[1,365],70:$t,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,93:Jt,96:61,97:211,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,136:367,138:366,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t([6,35,69],dn,{133:368,92:370,93:Pn}),t(Hn,[2,234]),t(Bn,[2,225]),{7:308,8:309,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,35:Xt,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,70:$t,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,93:Jt,96:61,97:211,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,131:372,132:371,136:210,137:207,138:206,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(Hn,[2,236]),t(Bn,[2,230]),t(jn,[2,223]),t(jn,[2,224],{17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,13:23,15:25,16:26,60:29,53:30,74:31,100:32,51:33,76:34,75:35,98:45,172:46,151:48,147:49,152:50,154:51,155:52,96:61,73:62,42:63,48:65,37:78,67:79,158:85,44:88,89:152,9:154,7:373,14:n,32:_t,38:i,39:s,43:o,45:u,46:a,49:f,50:l,54:c,55:h,56:p,57:d,58:v,59:m,68:g,77:y,84:b,85:Dt,86:Pt,90:S,91:x,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,148:D,150:P,153:H,156:B,167:j,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W}),{78:374,126:fn},{40:375,41:Gt},{7:376,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t(Fn,[2,202]),t(Fn,[2,38]),{34:377,35:Mt,148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{34:378,35:Mt},t(In,[2,256],{151:111,154:112,158:116,148:J,149:[1,379],150:K,156:Q,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{35:[2,252],149:[1,380]},t(In,[2,259],{151:111,154:112,158:116,148:J,149:[1,381],150:K,156:Q,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{35:[2,254],149:[1,382]},t(pt,[2,267]),t(qn,[2,268],{151:111,154:112,158:116,148:J,150:K,156:Q,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{35:Rn,157:[1,383]},t(Un,[2,278]),{37:230,38:i,39:s,67:231,68:Lt,73:233,96:232,107:T,130:Ot,161:384,163:229},t(Un,[2,284],{93:[1,385]}),t(zn,[2,280]),t(zn,[2,281]),t(zn,[2,282]),t(zn,[2,283]),t(pt,[2,275]),{35:[2,277]},{7:386,8:387,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:388,8:389,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:390,8:391,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(Wn,dn,{92:392,93:Xn}),t(Vn,[2,143]),t(Vn,[2,56],{65:[1,394]}),t(Vn,[2,57]),t($n,[2,66],{78:397,79:398,61:[1,395],70:[1,396],80:Jn,81:Kn,126:fn}),t($n,[2,67]),{37:247,38:i,39:s,40:248,41:Gt,66:401,67:249,68:nn,71:402,72:251,73:252,74:253,75:254,76:255,77:sn,107:T,129:L,130:A,145:_},{70:[1,403],78:404,79:405,80:Jn,81:Kn,126:fn},t(Qn,[2,62]),t(Qn,[2,63]),t(Qn,[2,64]),{7:406,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t(Gn,[2,72]),t(Gn,[2,73]),t(Gn,[2,74]),t(Gn,[2,75]),t(Gn,[2,76]),{78:407,80:Kt,81:Qt,126:fn},t(Sn,Nt,{52:[1,408]}),t(Sn,Ft),{6:X,47:[1,409]},t(V,[2,4]),t(Yn,[2,357],{151:111,154:112,158:116,182:et,183:tt,184:nt}),t(Yn,[2,358],{151:111,154:112,158:116,182:et,183:tt,184:nt}),t(En,[2,359],{151:111,154:112,158:116,182:et,184:nt}),t(En,[2,360],{151:111,154:112,158:116,182:et,184:nt}),t([1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,157,174,185,186,187,188,189,190,191,192,193],[2,361],{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt}),t([1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,157,174,186,187,188,189,190,191,192],[2,362],{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,193:ct}),t([1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,157,174,187,188,189,190,191,192],[2,363],{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,193:ct}),t([1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,157,174,188,189,190,191,192],[2,364],{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,193:ct}),t([1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,157,174,189,190,191,192],[2,365],{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,193:ct}),t([1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,157,174,190,191,192],[2,366],{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,193:ct}),t([1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,157,174,191,192],[2,367],{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,193:ct}),t([1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,157,174,192],[2,368],{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,193:ct}),t([1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,157,174,186,187,188,189,190,191,192,193],[2,369],{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt}),t(qn,Zn,{151:111,154:112,158:116,148:J,150:K,156:Q,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t($,[2,345]),{149:[1,410]},{149:[1,411]},t([1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,149,150,156,174,178,179,182,183,184,185,186,187,188,189,190,191,192,193],Rn,{157:[1,412]}),{7:413,8:414,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:415,8:416,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:417,8:418,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(qn,er,{151:111,154:112,158:116,148:J,150:K,156:Q,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t($,[2,344]),t(tr,[2,193]),t(tr,[2,194]),{7:308,8:309,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,35:nr,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,70:$t,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,97:211,98:45,100:32,107:T,110:N,112:C,120:k,127:[1,419],128:420,129:L,130:A,136:421,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(Zt,[2,131]),t(Zt,[2,132]),t(Zt,[2,133]),t(Zt,[2,134]),{83:[1,423]},{70:cn,83:[2,139],134:424,135:hn,148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{83:[2,140]},{70:cn,134:425,135:hn},{7:426,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,83:[2,215],84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t(rr,[2,206]),t(rr,ir),t(Zt,[2,138]),t(Tn,[2,53],{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{7:427,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:428,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{89:429,90:S,91:x},t(sr,or,{95:134,37:136,67:137,96:138,73:139,94:430,38:i,39:s,68:Lt,70:At,107:T,130:Ot}),{6:ur,35:ar},t(mn,[2,105]),{7:433,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t(mn,[2,106]),t(jn,Mn,{151:111,154:112,158:116,70:[1,434],148:J,150:K,156:Q,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(jn,_n),t(fr,[2,34]),{6:X,36:[1,435]},{7:436,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t(pn,dn,{92:304,88:[1,437],93:vn}),t(bn,wn,{151:111,154:112,158:116,182:et}),{7:438,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{34:377,35:Mt,148:J,150:K,151:111,154:112,156:Q,158:116,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},t($,[2,89],{151:111,154:112,158:116,148:Nn,150:Nn,156:Nn,174:Nn,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(Tn,[2,370],{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{7:439,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:440,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t(pt,[2,337]),{7:441,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t(pt,[2,242],{142:[1,442]}),{34:443,35:Mt},{34:446,35:Mt,37:444,38:i,39:s,73:445,107:T},{168:447,170:329,171:xn},{168:448,170:329,171:xn},{36:[1,449],169:[1,450],170:451,171:xn},t(cr,[2,330]),{7:453,8:454,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,139:452,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(hr,[2,149],{151:111,154:112,158:116,34:455,35:Mt,148:J,150:K,156:Q,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(pt,[2,152]),{7:456,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{36:[1,457]},t(Tn,[2,33],{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t($,[2,87],{151:111,154:112,158:116,148:Nn,150:Nn,156:Nn,174:Nn,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t($,[2,343]),{7:459,8:458,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{36:[1,460]},{44:461,45:u,46:a},{107:[1,463],114:462,119:Wt},{44:464,45:u,46:a},{33:[1,465]},t(Wn,dn,{92:466,93:pr}),t(Vn,[2,162]),{35:Cn,37:347,38:i,39:s,115:468,116:345,118:kn},t(Vn,[2,167],{117:[1,469]}),t(Vn,[2,169],{117:[1,470]}),{37:471,38:i,39:s},t(St,[2,173]),t(Wn,dn,{92:472,93:dr}),t(Vn,[2,183]),{35:Ln,37:354,38:i,39:s,118:An,121:474,123:352},t(Vn,[2,188],{117:[1,475]}),t(Vn,[2,191],{117:[1,476]}),{6:[1,478],7:477,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,35:[1,479],37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t(vr,[2,179],{151:111,154:112,158:116,148:J,150:K,156:Q,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{73:480,107:T},{44:481,45:u,46:a},t(xt,[2,250]),{6:X,36:[1,482]},{7:483,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t([14,32,38,39,43,45,46,49,50,54,55,56,57,58,59,68,77,84,85,86,90,91,107,110,112,120,129,130,140,144,145,148,150,153,156,167,173,176,177,178,179,180,181],ir,{6:mr,35:mr,69:mr,93:mr}),{7:484,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t(Dn,[2,204]),t(Hn,[2,235]),t(Bn,[2,231]),{6:gr,35:yr,69:[1,485]},t(br,or,{17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,13:23,15:25,16:26,60:29,53:30,74:31,100:32,51:33,76:34,75:35,89:37,98:45,172:46,151:48,147:49,152:50,154:51,155:52,175:57,96:61,73:62,42:63,48:65,37:78,67:79,158:85,44:88,9:148,138:206,136:210,97:211,7:308,8:309,137:488,131:489,14:n,32:_t,38:i,39:s,43:o,45:u,46:a,49:f,50:l,54:c,55:h,56:p,57:d,58:v,59:m,68:g,70:$t,77:y,84:b,85:Dt,86:E,90:S,91:x,93:Jt,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,148:D,150:P,153:H,156:B,167:j,173:F,176:I,177:q,178:R,179:U,180:z,181:W}),t(br,[2,232]),t(sr,dn,{92:370,133:490,93:Pn}),{7:308,8:309,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,70:$t,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,93:Jt,96:61,97:211,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,136:367,138:366,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(jn,[2,114],{151:111,154:112,158:116,148:J,150:K,156:Q,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(tr,[2,195]),t(xt,[2,129]),{83:[1,491],148:J,150:K,151:111,154:112,156:Q,158:116,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},t(wr,[2,334]),t(Er,[2,340]),{7:492,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:493,8:494,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:495,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:496,8:497,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:498,8:499,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(Un,[2,279]),{37:230,38:i,39:s,67:231,68:Lt,73:233,96:232,107:T,130:Ot,163:500},{35:Sr,148:J,149:[1,501],150:K,151:111,154:112,156:Q,157:[1,502],158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,305],149:[1,503],157:[1,504]},{35:xr,148:J,149:[1,505],150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,306],149:[1,506]},{35:Tr,148:J,149:[1,507],150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,321],149:[1,508]},{6:Nr,35:Cr,109:[1,509]},t(kr,or,{44:88,63:241,64:242,66:243,42:244,71:246,37:247,40:248,67:249,72:251,73:252,74:253,75:254,76:255,62:512,38:i,39:s,41:Gt,43:o,45:u,46:a,68:nn,70:rn,77:sn,107:T,129:L,130:A,145:_}),{7:513,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,35:[1,514],37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:515,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,35:[1,516],37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t(Vn,[2,68]),t(Gn,[2,78]),t(Gn,[2,80]),{40:517,41:Gt},{7:292,8:294,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,70:cn,73:62,74:31,75:35,76:34,77:y,82:518,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,106:293,107:T,110:N,112:C,120:k,129:L,130:A,134:295,135:hn,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(Vn,[2,69],{78:397,79:398,80:Jn,81:Kn,126:fn}),t(Vn,[2,71],{78:404,79:405,80:Jn,81:Kn,126:fn}),t(Vn,[2,70]),t(Gn,[2,79]),t(Gn,[2,81]),{69:[1,519],148:J,150:K,151:111,154:112,156:Q,158:116,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},t(Gn,[2,77]),t(xt,[2,44]),t(an,[2,42]),{7:520,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:521,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:522,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t([1,6,35,36,47,69,70,83,88,93,109,127,135,146,148,150,156,174],Sr,{151:111,154:112,158:116,149:[1,523],157:[1,524],178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{149:[1,525],157:[1,526]},t(Lr,xr,{151:111,154:112,158:116,149:[1,527],178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{149:[1,528]},t(Lr,Tr,{151:111,154:112,158:116,149:[1,529],178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{149:[1,530]},t(tr,[2,198]),t([6,35,127],dn,{92:531,93:Ar}),t(Or,[2,216]),{7:308,8:309,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,35:nr,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,70:$t,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,97:211,98:45,100:32,107:T,110:N,112:C,120:k,128:533,129:L,130:A,136:421,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(Zt,[2,137]),{7:534,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,83:[2,211],84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:535,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,83:[2,213],84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{83:[2,214],148:J,150:K,151:111,154:112,156:Q,158:116,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},t(Tn,[2,54],{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{36:[1,536],148:J,150:K,151:111,154:112,156:Q,158:116,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{5:538,7:4,8:5,9:6,10:7,11:27,12:28,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:r,34:537,35:Mt,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:w,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(mn,[2,101]),{37:136,38:i,39:s,67:137,68:Lt,70:At,73:139,94:539,95:134,96:138,107:T,130:Ot},t(Mr,kt,{94:133,95:134,37:136,67:137,96:138,73:139,87:540,38:i,39:s,68:Lt,70:At,107:T,130:Ot}),t(mn,[2,107],{151:111,154:112,158:116,148:J,150:K,156:Q,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(jn,mr),t(fr,[2,35]),t(qn,Zn,{151:111,154:112,158:116,148:J,150:K,156:Q,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{89:541,90:S,91:x},t(qn,er,{151:111,154:112,158:116,148:J,150:K,156:Q,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{36:[1,542],148:J,150:K,151:111,154:112,156:Q,158:116,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},t(Tn,[2,372],{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{34:543,35:Mt,148:J,150:K,151:111,154:112,156:Q,158:116,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{34:544,35:Mt},t(pt,[2,243]),{34:545,35:Mt},{34:546,35:Mt},t(_r,[2,247]),{36:[1,547],169:[1,548],170:451,171:xn},{36:[1,549],169:[1,550],170:451,171:xn},t(pt,[2,328]),{34:551,35:Mt},t(cr,[2,331]),{34:552,35:Mt,93:[1,553]},t(Dr,[2,237],{151:111,154:112,158:116,148:J,150:K,156:Q,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(Dr,[2,238]),t(pt,[2,150]),t(hr,[2,153],{151:111,154:112,158:116,34:554,35:Mt,148:J,150:K,156:Q,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(pt,[2,249]),{34:555,35:Mt},{148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},t(St,[2,85]),t(St,[2,156]),{33:[1,556]},{35:Cn,37:347,38:i,39:s,115:557,116:345,118:kn},t(St,[2,157]),{44:558,45:u,46:a},{6:Pr,35:Hr,109:[1,559]},t(kr,or,{37:347,116:562,38:i,39:s,118:kn}),t(sr,dn,{92:563,93:pr}),{37:564,38:i,39:s},{37:565,38:i,39:s},{33:[2,172]},{6:Br,35:jr,109:[1,566]},t(kr,or,{37:354,123:569,38:i,39:s,118:An}),t(sr,dn,{92:570,93:dr}),{37:571,38:i,39:s,118:[1,572]},{37:573,38:i,39:s},t(vr,[2,176],{151:111,154:112,158:116,148:J,150:K,156:Q,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{7:574,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:575,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{36:[1,576]},t(St,[2,181]),{146:[1,577]},{69:[1,578],148:J,150:K,151:111,154:112,156:Q,158:116,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{69:[1,579],148:J,150:K,151:111,154:112,156:Q,158:116,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},t(Dn,[2,205]),{7:308,8:309,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,70:$t,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,93:Jt,96:61,97:211,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,131:372,136:210,137:580,138:206,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:308,8:309,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,35:Xt,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,70:$t,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,93:Jt,96:61,97:211,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,131:372,132:581,136:210,137:207,138:206,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(Bn,[2,226]),t(br,[2,233],{17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,13:23,15:25,16:26,60:29,53:30,74:31,100:32,51:33,76:34,75:35,89:37,98:45,172:46,151:48,147:49,152:50,154:51,155:52,175:57,96:61,73:62,42:63,48:65,37:78,67:79,158:85,44:88,9:148,97:211,7:308,8:309,138:366,136:367,14:n,32:_t,38:i,39:s,43:o,45:u,46:a,49:f,50:l,54:c,55:h,56:p,57:d,58:v,59:m,68:g,70:$t,77:y,84:b,85:Dt,86:E,90:S,91:x,93:Jt,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,148:D,150:P,153:H,156:B,167:j,173:F,176:I,177:q,178:R,179:U,180:z,181:W}),{6:gr,35:yr,36:[1,582]},t(xt,[2,130]),t(qn,[2,257],{151:111,154:112,158:116,148:J,150:K,156:Q,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{35:Fr,148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,253]},t(qn,[2,260],{151:111,154:112,158:116,148:J,150:K,156:Q,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{35:Ir,148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,255]},{35:qr,148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,276]},t(Un,[2,285]),{7:583,8:584,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:585,8:586,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:587,8:588,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:589,8:590,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:591,8:592,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:593,8:594,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:595,8:596,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:597,8:598,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(Dn,[2,141]),{37:247,38:i,39:s,40:248,41:Gt,42:244,43:o,44:88,45:u,46:a,62:599,63:241,64:242,66:243,67:249,68:nn,70:rn,71:246,72:251,73:252,74:253,75:254,76:255,77:sn,107:T,129:L,130:A,145:_},t(Mr,tn,{44:88,62:240,63:241,64:242,66:243,42:244,71:246,37:247,40:248,67:249,72:251,73:252,74:253,75:254,76:255,108:600,38:i,39:s,41:Gt,43:o,45:u,46:a,68:nn,70:rn,77:sn,107:T,129:L,130:A,145:_}),t(Vn,[2,144]),t(Vn,[2,58],{151:111,154:112,158:116,148:J,150:K,156:Q,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{7:601,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t(Vn,[2,60],{151:111,154:112,158:116,148:J,150:K,156:Q,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{7:602,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t(Gn,[2,82]),{83:[1,603]},t(Qn,[2,65]),t(qn,Fr,{151:111,154:112,158:116,148:J,150:K,156:Q,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(qn,Ir,{151:111,154:112,158:116,148:J,150:K,156:Q,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(qn,qr,{151:111,154:112,158:116,148:J,150:K,156:Q,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{7:604,8:605,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:606,8:607,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:608,8:609,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:610,8:611,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:612,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:613,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:614,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:615,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{6:Rr,35:Ur,127:[1,616]},t([6,35,36,127],or,{17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,13:23,15:25,16:26,60:29,53:30,74:31,100:32,51:33,76:34,75:35,89:37,98:45,172:46,151:48,147:49,152:50,154:51,155:52,175:57,96:61,73:62,42:63,48:65,37:78,67:79,158:85,44:88,9:148,97:211,7:308,8:309,136:619,14:n,32:_t,38:i,39:s,43:o,45:u,46:a,49:f,50:l,54:c,55:h,56:p,57:d,58:v,59:m,68:g,70:$t,77:y,84:b,85:Dt,86:E,90:S,91:x,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,148:D,150:P,153:H,156:B,167:j,173:F,176:I,177:q,178:R,179:U,180:z,181:W}),t(sr,dn,{92:620,93:Ar}),{83:[2,210],148:J,150:K,151:111,154:112,156:Q,158:116,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{83:[2,212],148:J,150:K,151:111,154:112,156:Q,158:116,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},t(pt,[2,55]),t(yn,[2,91]),t($,[2,93]),t(mn,[2,102]),t(sr,dn,{92:621,93:vn}),{34:537,35:Mt},t(pt,[2,371]),t(wr,[2,335]),t(pt,[2,244]),t(_r,[2,245]),t(_r,[2,246]),t(pt,[2,324]),{34:622,35:Mt},t(pt,[2,325]),{34:623,35:Mt},{36:[1,624]},t(cr,[2,332],{6:[1,625]}),{7:626,8:627,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(pt,[2,154]),t(Er,[2,341]),{44:628,45:u,46:a},t(Wn,dn,{92:629,93:pr}),t(St,[2,158]),{33:[1,630]},{37:347,38:i,39:s,116:631,118:kn},{35:Cn,37:347,38:i,39:s,115:632,116:345,118:kn},t(Vn,[2,163]),{6:Pr,35:Hr,36:[1,633]},t(Vn,[2,168]),t(Vn,[2,170]),t(St,[2,174],{33:[1,634]}),{37:354,38:i,39:s,118:An,123:635},{35:Ln,37:354,38:i,39:s,118:An,121:636,123:352},t(Vn,[2,184]),{6:Br,35:jr,36:[1,637]},t(Vn,[2,189]),t(Vn,[2,190]),t(Vn,[2,192]),t(vr,[2,177],{151:111,154:112,158:116,148:J,150:K,156:Q,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{36:[1,638],148:J,150:K,151:111,154:112,156:Q,158:116,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},t(St,[2,180]),t(xt,[2,251]),t(xt,[2,208]),t(xt,[2,209]),t(Bn,[2,227]),t(sr,dn,{92:370,133:639,93:Pn}),t(Bn,[2,228]),{35:zr,148:J,150:K,151:111,154:112,156:Q,157:[1,640],158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,307],157:[1,641]},{35:Wr,148:J,149:[1,642],150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,311],149:[1,643]},{35:Xr,148:J,150:K,151:111,154:112,156:Q,157:[1,644],158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,308],157:[1,645]},{35:Vr,148:J,149:[1,646],150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,312],149:[1,647]},{35:$r,148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,309]},{35:Jr,148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,310]},{35:Kr,148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,322]},{35:Qr,148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,323]},t(Vn,[2,145]),t(sr,dn,{92:648,93:Xn}),{36:[1,649],148:J,150:K,151:111,154:112,156:Q,158:116,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{36:[1,650],148:J,150:K,151:111,154:112,156:Q,158:116,174:lr,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},t(Gn,[2,83]),t(Gr,zr,{151:111,154:112,158:116,157:[1,651],178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{157:[1,652]},t(Lr,Wr,{151:111,154:112,158:116,149:[1,653],178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{149:[1,654]},t(Gr,Xr,{151:111,154:112,158:116,157:[1,655],178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{157:[1,656]},t(Lr,Vr,{151:111,154:112,158:116,149:[1,657],178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{149:[1,658]},t(Tn,$r,{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(Tn,Jr,{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(Tn,Kr,{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(Tn,Qr,{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(tr,[2,199]),{7:308,8:309,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,70:$t,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,97:211,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,136:659,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:308,8:309,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,35:nr,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,70:$t,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,97:211,98:45,100:32,107:T,110:N,112:C,120:k,128:660,129:L,130:A,136:421,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},t(Or,[2,217]),{6:Rr,35:Ur,36:[1,661]},{6:ur,35:ar,36:[1,662]},{36:[1,663]},{36:[1,664]},t(pt,[2,329]),t(cr,[2,333]),t(Dr,[2,239],{151:111,154:112,158:116,148:J,150:K,156:Q,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(Dr,[2,240]),t(St,[2,160]),{6:Pr,35:Hr,109:[1,665]},{44:666,45:u,46:a},t(Vn,[2,164]),t(sr,dn,{92:667,93:pr}),t(Vn,[2,165]),{44:668,45:u,46:a},t(Vn,[2,185]),t(sr,dn,{92:669,93:dr}),t(Vn,[2,186]),t(St,[2,178]),{6:gr,35:yr,36:[1,670]},{7:671,8:672,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:673,8:674,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:675,8:676,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:677,8:678,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:679,8:680,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:681,8:682,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:683,8:684,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{7:685,8:686,9:148,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,29:20,30:21,31:22,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:E,89:37,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:F,175:57,176:I,177:q,178:R,179:U,180:z,181:W},{6:Nr,35:Cr,36:[1,687]},t(Vn,[2,59]),t(Vn,[2,61]),{7:688,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:689,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:690,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:691,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:692,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:693,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:694,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},{7:695,9:154,13:23,14:n,15:25,16:26,17:8,18:9,19:10,20:11,21:12,22:13,23:14,24:15,25:16,26:17,27:18,28:19,32:_t,37:78,38:i,39:s,42:63,43:o,44:88,45:u,46:a,48:65,49:f,50:l,51:33,53:30,54:c,55:h,56:p,57:d,58:v,59:m,60:29,67:79,68:g,73:62,74:31,75:35,76:34,77:y,84:b,85:Dt,86:Pt,89:152,90:S,91:x,96:61,98:45,100:32,107:T,110:N,112:C,120:k,129:L,130:A,140:O,144:M,145:_,147:49,148:D,150:P,151:48,152:50,153:H,154:51,155:52,156:B,158:85,167:j,172:46,173:Ht,176:Bt,177:q,178:R,179:U,180:z,181:W},t(Or,[2,218]),t(sr,dn,{92:696,93:Ar}),t(Or,[2,219]),t(mn,[2,103]),t(pt,[2,326]),t(pt,[2,327]),{33:[1,697]},t(St,[2,159]),{6:Pr,35:Hr,36:[1,698]},t(St,[2,182]),{6:Br,35:jr,36:[1,699]},t(Bn,[2,229]),{35:Yr,148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,313]},{35:Zr,148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,315]},{35:ei,148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,317]},{35:ti,148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,319]},{35:ni,148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,314]},{35:ri,148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,316]},{35:ii,148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,318]},{35:si,148:J,150:K,151:111,154:112,156:Q,158:116,174:G,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct},{35:[2,320]},t(Vn,[2,146]),t(Tn,Yr,{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(Tn,Zr,{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(Tn,ei,{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(Tn,ti,{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(Tn,ni,{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(Tn,ri,{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(Tn,ii,{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),t(Tn,si,{151:111,154:112,158:116,178:Y,179:Z,182:et,183:tt,184:nt,185:rt,186:it,187:st,188:ot,189:ut,190:at,191:ft,192:lt,193:ct}),{6:Rr,35:Ur,36:[1,700]},{44:701,45:u,46:a},t(Vn,[2,166]),t(Vn,[2,187]),t(Or,[2,220]),t(St,[2,161])],defaultActions:{235:[2,277],293:[2,140],471:[2,172],494:[2,253],497:[2,255],499:[2,276],592:[2,309],594:[2,310],596:[2,322],598:[2,323],672:[2,313],674:[2,315],676:[2,317],678:[2,319],680:[2,314],682:[2,316],684:[2,318],686:[2,320]},parseError:function(e,t){if(!t.recoverable){var n=new Error(e);throw n.hash=t,n}this.trace(e)},parse:function(e){var t=this,n=[0],r=[null],i=[],s=this.table,o="",u=0,a=0,f=0,l=1,c=i.slice.call(arguments,1),h=Object.create(this.lexer),p={yy:{}};for(var d in this.yy)Object.prototype.hasOwnProperty.call(this.yy,d)&&(p.yy[d]=this.yy[d]);h.setInput(e,p.yy),p.yy.lexer=h,p.yy.parser=this,"undefined"==typeof h.yylloc&&(h.yylloc={});var v=h.yylloc;i.push(v);var m=h.options&&h.options.ranges;this.parseError="function"==typeof p.yy.parseError?p.yy.parseError:Object.getPrototypeOf(this).parseError;var g=function(){var e;return e=h.lex()||l,"number"!=typeof e&&(e=t.symbols_[e]||e),e};for(var y={},b,w,E,S,x,T,N,C,k;;){if(E=n[n.length-1],this.defaultActions[E]?S=this.defaultActions[E]:((null===b||"undefined"==typeof b)&&(b=g()),S=s[E]&&s[E][b]),"undefined"==typeof S||!S.length||!S[0]){var L="";for(T in k=[],s[E])this.terminals_[T]&&T>2&&k.push("'"+this.terminals_[T]+"'");L=h.showPosition?"Parse error on line "+(u+1)+":\n"+h.showPosition()+"\nExpecting "+k.join(", ")+", got '"+(this.terminals_[b]||b)+"'":"Parse error on line "+(u+1)+": Unexpected "+(b==l?"end of input":"'"+(this.terminals_[b]||b)+"'"),this.parseError(L,{text:h.match,token:this.terminals_[b]||b,line:h.yylineno,loc:v,expected:k})}if(S[0]instanceof Array&&1t.call(this.compiledComments,u))&&(this.compiledComments.push(u),a=u.here?(new O(u)).compileNode(n):(new Q(u)).compileNode(n),a.isHereComment&&!a.newLine||r.includeCommentFragments()?h(a):(0===i.length&&i.push(this.makeCode("")),a.unshift?(null==(s=i[0]).precedingComments&&(s.precedingComments=[]),i[0].precedingComments.push(a)):(null==(o=i[i.length-1]).followingComments&&(o.followingComments=[]),i[i.length-1].followingComments.push(a))));return i}},{key:"cache",value:function(t,n,r){var i,s,u;return i=null==r?this.shouldCache():r(this),i?(s=new _(t.scope.freeVariable("ref")),u=new o(s,this),n?[u.compileToFragments(t,n),[this.makeCode(s.value)]]:[u,s]):(s=n?this.compileToFragments(t,n):this,[s,s])}},{key:"hoist",value:function(){var t,n,r;return this.hoisted=!0,r=new M(this),t=this.compileNode,n=this.compileToFragments,this.compileNode=function(e){return r.update(t,e)},this.compileToFragments=function(e){return r.update(n,e)},r}},{key:"cacheToCodeFragments",value:function(t){return[Xt(t[0]),Xt(t[1])]}},{key:"makeReturn",value:function(t){var n;return n=this.unwrapAll(),t?new h(new G(t+".push"),[n]):new vt(n)}},{key:"contains",value:function(t){var n;return n=void 0,this.traverseChildren(!1,function(e){if(t(e))return n=e,!1}),n}},{key:"lastNode",value:function(t){return 0===t.length?null:t[t.length-1]}},{key:"toString",value:function r(){var e=0=V?this.wrapInParentheses(i):i)}},{key:"compileRoot",value:function(t){var n,r,i,s,o,u;for(t.indent=t.bare?"":Ct,t.level=K,this.spaced=!0,t.scope=new gt(null,this,null,null==(o=t.referencedVars)?[]:o),u=t.locals||[],r=0,i=u.length;r=$?this.wrapInParentheses(n):n}}]),t}(st),e.StringLiteral=Et=function(e){function t(){return _classCallCheck(this,t),_possibleConstructorReturn(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments))}return _inherits(t,e),_createClass(t,[{key:"compileNode",value:function(){var n;return n=this.csx?[this.makeCode(this.unquote(!0,!0))]:_get(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"compileNode",this).call(this)}},{key:"unquote",value:function(){var t=0=W?"(void 0)":"void 0")]}}]),t}(G),e.NullLiteral=it=function(e){function t(){return _classCallCheck(this,t),_possibleConstructorReturn(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"null"))}return _inherits(t,e),t}(G),e.BooleanLiteral=l=function(e){function t(){return _classCallCheck(this,t),_possibleConstructorReturn(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments))}return _inherits(t,e),t}(G),e.Return=vt=function(){var e=function(e){function n(e){_classCallCheck(this,n);var t=_possibleConstructorReturn(this,(n.__proto__||Object.getPrototypeOf(n)).call(this));return t.expression=e,t}return _inherits(n,e),_createClass(n,[{key:"compileToFragments",value:function(t,r){var i,s;return i=null==(s=this.expression)?void 0:s.makeReturn(),!i||i instanceof n?_get(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"compileToFragments",this).call(this,t,r):i.compileToFragments(t,r)}},{key:"compileNode",value:function(n){var r,i,s,o;if(r=[],this.expression)for(r=this.expression.compileToFragments(n,J),un(r,this.makeCode(this.tab+"return ")),s=0,o=r.length;sthis.properties.length&&!this.base.shouldCache()&&(null==f||!f.shouldCache()))?[this,this]:(u=new t(this.base,this.properties.slice(0,-1)),u.shouldCache()&&(a=new _(n.scope.freeVariable("base")),u=new t(new ft(new o(a,u)))),!f)?[u,a]:(f.shouldCache()&&(l=new _(n.scope.freeVariable("name")),f=new R(new o(l,f.index)),l=new R(l)),[u.add(f),new t(a||u.base,[l||f])])}},{key:"compileNode",value:function(t){var n,r,i,s,o;for(this.base.front=this.front,o=this.properties,n=o.length&&null!=this.base.cached?this.base.cached:this.base.compileToFragments(t,o.length?W:null),o.length&&mt.test(Xt(n))&&n.push(this.makeCode(".")),r=0,i=o.length;rs.length&&(s=o);this.content=this.content.replace(RegExp("^("+o+")","gm"),"")}return this.content="/*"+this.content+(r?" ":"")+"*/",n=this.makeCode(this.content),n.newLine=this.newLine,n.unshift=this.unshift,n.multiline=f,n.isComment=n.isHereComment=!0,n}}]),n}(a),e.LineComment=Q=function(e){function t(e){var n=e.content,r=e.newLine,i=e.unshift;_classCallCheck(this,t);var s=_possibleConstructorReturn(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return s.content=n,s.newLine=r,s.unshift=i,s}return _inherits(t,e),_createClass(t,[{key:"compileNode",value:function(){var t;return t=this.makeCode(/^\s*$/.test(this.content)?"":"//"+this.content),t.newLine=this.newLine,t.unshift=this.unshift,t.trail=!this.newLine&&!this.unshift,t.isComment=t.isLineComment=!0,t}}]),t}(a),e.Call=h=function(){var e=function(e){function t(e){var n=1")),(m=f).push.apply(m,_toConsumableArray(a.compileNode(t,V))),(g=f).push.apply(g,[this.makeCode("")]))}else f.push(this.makeCode(" />"));return f}}]),t}(a);return e.prototype.children=["variable","args"],e}.call(this),e.SuperCall=Tt=function(){var e=function(e){function t(){return _classCallCheck(this,t),_possibleConstructorReturn(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments))}return _inherits(t,e),_createClass(t,[{key:"isStatement",value:function(t){var n;return(null==(n=this.expressions)?void 0:n.length)&&t.level===K}},{key:"compileNode",value:function(n){var r,i,s,o;if(null==(i=this.expressions)||!i.length)return _get(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"compileNode",this).call(this,n);if(o=new G(Xt(_get(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"compileNode",this).call(this,n))),s=new f(this.expressions.slice()),n.level>K){var u=o.cache(n,null,Bt),a=_slicedToArray(u,2);o=a[0],r=a[1],s.push(r)}return s.unshift(o),s.compileToFragments(n,n.level===K?n.level:V)}}]),t}(h);return e.prototype.children=h.prototype.children.concat(["expressions"]),e}.call(this),e.Super=xt=function(){var e=function(e){function t(e){_classCallCheck(this,t);var n=_possibleConstructorReturn(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return n.accessor=e,n}return _inherits(t,e),_createClass(t,[{key:"compileNode",value:function(t){var n,r,i,s,u,a,f,l;if(r=t.scope.namedMethod(),(null==r?void 0:r.isMethod)||this.error("cannot use super outside of an instance method"),null==r.ctor&&null==this.accessor){var c=r;i=c.name,l=c.variable,(i.shouldCache()||i instanceof R&&i.index.isAssignable())&&(s=new _(t.scope.parent.freeVariable("name")),i.index=new o(s,i.index)),this.accessor=null==s?i:new R(s)}return(null==(u=this.accessor)||null==(a=u.name)?void 0:a.comments)&&(f=this.accessor.name.comments,delete this.accessor.name.comments),n=(new Pt(new G("super"),this.accessor?[this.accessor]:[])).compileToFragments(t),f&&It(f,this.accessor.name),n}}]),t}(a);return e.prototype.children=["accessor"],e}.call(this),e.RegexWithInterpolations=dt=function(e){function t(){var e=0"+this.equals;var g=[this.fromNum,this.toNum];return i=g[0],d=g[1],h=this.stepNum?this.stepNum+" !== 0":this.stepVar+" !== 0",r=a?null==this.step?i<=d?l+" "+d:s+" "+d:(f=i+" <= "+o+" && "+l+" "+d,v=i+" >= "+o+" && "+s+" "+d,i<=d?h+" && "+f:h+" && "+v):(f=this.fromVar+" <= "+o+" && "+l+" "+this.toVar,v=this.fromVar+" >= "+o+" && "+s+" "+this.toVar,h+" && ("+this.fromVar+" <= "+this.toVar+" ? "+f+" : "+v+")"),n=this.stepVar?this.stepVar+" > 0":this.fromVar+" <= "+this.toVar,p=this.stepVar?o+" += "+this.stepVar:a?c?i<=d?"++"+o:"--"+o:i<=d?o+"++":o+"--":c?n+" ? ++"+o+" : --"+o:n+" ? "+o+"++ : "+o+"--",c&&(m=u+" = "+m),c&&(p=u+" = "+p),[this.makeCode(m+"; "+r+"; "+p)]}},{key:"compileArray",value:function(t){var n,r,i,s,o,u,a,f,l,c,h,p,d;return(a=null!=this.fromNum&&null!=this.toNum,a&&20>=_Mathabs(this.fromNum-this.toNum))?(c=function(){for(var e=[],t=h=this.fromNum,n=this.toNum;h<=n?t<=n:t>=n;h<=n?t++:t--)e.push(t);return e}.apply(this),this.exclusive&&c.pop(),[this.makeCode("["+c.join(", ")+"]")]):(u=this.tab+Ct,o=t.scope.freeVariable("i",{single:!0,reserve:!1}),p=t.scope.freeVariable("results",{reserve:!1}),l="\n"+u+"var "+p+" = [];",a?(t.index=o,r=Xt(this.compileNode(t))):(d=o+" = "+this.fromC+(this.toC===this.toVar?"":", "+this.toC),i=this.fromVar+" <= "+this.toVar,r="var "+d+"; "+i+" ? "+o+" <"+this.equals+" "+this.toVar+" : "+o+" >"+this.equals+" "+this.toVar+"; "+i+" ? "+o+"++ : "+o+"--"),f="{ "+p+".push("+o+"); }\n"+u+"return "+p+";\n"+t.indent,s=function(e){return null==e?void 0:e.contains(Jt)},(s(this.from)||s(this.to))&&(n=", arguments"),[this.makeCode("(function() {"+l+"\n"+u+"for ("+r+")"+f+"}).apply(this"+(null==n?"":n)+")")])}}]),t}(a);return e.prototype.children=["from","to"],e}.call(this),e.Slice=yt=function(){var e=function(e){function t(e){_classCallCheck(this,t);var n=_possibleConstructorReturn(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return n.range=e,n}return _inherits(t,e),_createClass(t,[{key:"compileNode",value:function(t){var n=this.range,r,i,s,o,u,a;return u=n.to,s=n.from,(null==s?void 0:s.shouldCache())&&(s=new Pt(new ft(s))),(null==u?void 0:u.shouldCache())&&(u=new Pt(new ft(u))),o=(null==s?void 0:s.compileToFragments(t,J))||[this.makeCode("0")],u&&(r=u.compileToFragments(t,J),i=Xt(r),(this.range.exclusive||-1!=+i)&&(a=", "+(this.range.exclusive?i:u.isNumber()?""+(+i+1):(r=u.compileToFragments(t,W),"+"+Xt(r)+" + 1 || 9e9")))),[this.makeCode(".slice("+Xt(o)+(a||"")+")")]}}]),t}(a);return e.prototype.children=["range"],e}.call(this),e.Obj=ot=function(){var e=function(e){function t(e){var n=1E)return u.push(new Pt(new ot(y.slice(E,r),!0)))};t=y[r];)(c=this.addInitializerExpression(t))&&(b(),u.push(c),l.push(c),E=r+1),r++;b(),n.apply(o,[a,a-a+1].concat(u)),u,a+=u.length}else(c=this.addInitializerExpression(s))&&(l.push(c),o[a]=c),a+=1;for(p=0,m=l.length;pV||u&&this.variable.base instanceof ot&&!this.nestedLhs&&!0!==this.param?this.wrapInParentheses(i):i)}},{key:"compileObjectDestruct",value:function(t){var n,o,u,a,l,c,p,d,v,m,g,y;if(o=function(e){var n;if(e instanceof r){var i=e.variable.cache(t),s=_slicedToArray(i,2);return e.variable=s[0],n=s[1],n}return e},u=function(e){var n,i;return i=o(e),n=e instanceof r&&e.variable!==i,n||!i.isAssignable()?i:new G("'"+i.compileWithoutComments(t)+"'")},v=function(n,a){var f,l,c,h,p,d,m,g,y,b,w;for(b=[],w=void 0,null==a.properties&&(a=new Pt(a)),l=c=0,h=n.length;c=$?this.wrapInParentheses(f):f;var J=O,Q=_slicedToArray(J,1);return L=Q[0],1===M&&L instanceof w&&L.error("Destructuring assignment has no target"),I=function(){var e,t,n;for(n=[],E=e=0,t=O.length;et.call(v,E):return new Pt(L.base);default:return L}}(),y=function(){switch(!1){case!(L instanceof bt):return l(u,E);default:return new Pt(new G(u),[new R(new st(E))])}}();d=Qt(s.unwrap().value),d&&s.error(d),m.push(a.push((new r(s,y,null,{param:o.param,subpattern:!0})).compileToFragments(n,V)))}return m},u=function(e,t,i){var u;return t=new Pt(new s(e,!0)),u=i instanceof Pt?i:new Pt(new G(i)),a.push((new r(t,u,null,{param:o.param,subpattern:!0})).compileToFragments(n,V))},D=function(e,t,n){return p(e)?k(e,t,n):u(e,t,n)},q.length?(d=q[0],C=O.slice(0,d+(N?1:0)),j=O.slice(d+1),0!==C.length&&D(C,W,X),0!==j.length&&(H=function(){switch(!1){case!N:return c(O[d].unwrapAll().value,-1*j.length);case!x:return l(X,-1*j.length)}}(),p(j)&&(B=H,H=n.scope.freeVariable("ref"),a.push([this.makeCode(H+" = ")].concat(_toConsumableArray(B.compileToFragments(n,V))))),D(j,W,H))):D(O,W,X),U||this.subpattern||a.push(W),m=this.joinFragmentArrays(a,", "),n.levelK?this.wrapInParentheses(i):i}},{key:"eachName",value:function(t){return this.variable.unwrapAll().eachName(t)}}]),r}(a);return e.prototype.children=["variable","value"],e.prototype.isAssignable=Bt,e}.call(this),e.FuncGlyph=A=function(e){function t(e){_classCallCheck(this,t);var n=_possibleConstructorReturn(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return n.glyph=e,n}return _inherits(t,e),t}(a),e.Code=d=function(){var e=function(e){function n(e,t,r,i){_classCallCheck(this,n);var s=_possibleConstructorReturn(this,(n.__proto__||Object.getPrototypeOf(n)).call(this)),o;return s.funcGlyph=r,s.paramStart=i,s.params=e||[],s.body=t||new f,s.bound="=>"===(null==(o=s.funcGlyph)?void 0:o.glyph),s.isGenerator=!1,s.isAsync=!1,s.isMethod=!1,s.body.traverseChildren(!1,function(e){if((e instanceof ut&&e.isYield()||e instanceof jt)&&(s.isGenerator=!0),(e instanceof ut&&e.isAwait()||e instanceof u)&&(s.isAsync=!0),s.isGenerator&&s.isAsync)return e.error("function can't contain both yield and await")}),s}return _inherits(n,e),_createClass(n,[{key:"isStatement",value:function(){return this.isMethod}},{key:"makeScope",value:function(t){return new gt(t,this.body,this)}},{key:"compileNode",value:function(n){var r,i,u,a,f,l,c,p,d,v,m,g,y,b,E,S,x,T,N,C,k,L,A,O,M,P,H,B,j,F,I,q,R,U,X,V,$,J,K,Q,Y,Z,et;for(this.ctor&&(this.isAsync&&this.name.error("Class constructor may not be async"),this.isGenerator&&this.name.error("Class constructor may not be a generator")),this.bound&&((null==(F=n.scope.method)?void 0:F.bound)&&(this.context=n.scope.method.context),!this.context&&(this.context="this")),n.scope=Rt(n,"classScope")||this.makeScope(n.scope),n.scope.shared=Rt(n,"sharedScope"),n.indent+=Ct,delete n.bare,delete n.isExistentialEquals,H=[],p=[],Y=null==(I=null==(q=this.thisAssignments)?void 0:q.slice())?[]:I,B=[],m=!1,v=!1,M=[],this.eachParamName(function(e,r,i,s){var u,a;if(0<=t.call(M,e)&&r.error("multiple parameters named '"+e+"'"),M.push(e),r.this)return e=r.properties[0].name.value,0<=t.call(z,e)&&(e="_"+e),a=new _(n.scope.freeVariable(e,{reserve:!1})),u=i.name instanceof ot&&s instanceof o&&"="===s.operatorToken.value?new o(new _(e),a,"object"):a,i.renameParam(r,u),Y.push(new o(r,a))}),R=this.params,g=b=0,x=R.length;b")),u.push(this.makeCode(" {")),null==a?void 0:a.length){var at;(at=u).push.apply(at,[this.makeCode("\n")].concat(_toConsumableArray(a),[this.makeCode("\n"+this.tab)]))}return u.push(this.makeCode("}")),this.isMethod?$t(u,this):this.front||n.level>=W?this.wrapInParentheses(u):u}},{key:"eachParamName",value:function(t){var n,r,i,s,o;for(s=this.params,o=[],n=0,r=s.length;n"===t||">="===t||"<="===t||"==="===t||"!=="===t}},{key:"invert",value:function(){var t,n,i,o,u;if(this.isChainable()&&this.first.isChainable()){for(t=!0,n=this;n&&n.operator;)t&&(t=n.operator in r),n=n.first;if(!t)return(new ft(this)).invert();for(n=this;n&&n.operator;)n.invert=!n.invert,n.operator=r[n.operator],n=n.first;return this}return(o=r[this.operator])?(this.operator=o,this.first.unwrap()instanceof s&&this.first.invert(),this):this.second?(new ft(this)).invert():"!"===this.operator&&(i=this.first.unwrap())instanceof s&&("!"===(u=i.operator)||"in"===u||"instanceof"===u)?i:new s("!",this)}},{key:"unfoldSoak",value:function(t){var n;return("++"===(n=this.operator)||"--"===n||"delete"===n)&&on(t,this,"first")}},{key:"generateDo",value:function(t){var n,r,i,s,u,a,f,l;for(a=[],r=t instanceof o&&(f=t.value.unwrap())instanceof d?f:t,l=r.params||[],i=0,s=l.length;i=W?(new ft(this)).compileToFragments(t):(i="+"===n||"-"===n,("new"===n||"typeof"===n||"delete"===n||i&&this.first instanceof s&&this.first.operator===n)&&r.push([this.makeCode(" ")]),(i&&this.first instanceof s||"new"===n&&this.first.isStatement(t))&&(this.first=new ft(this.first)),r.push(this.first.compileToFragments(t,$)),this.flip&&r.reverse(),this.joinFragmentArrays(r,""))}},{key:"compileContinuation",value:function(n){var r,i,s,o;return i=[],r=this.operator,null==n.scope.parent&&this.error(this.operator+" can only occur inside functions"),(null==(s=n.scope.method)?void 0:s.bound)&&n.scope.method.isGenerator&&this.error("yield cannot occur inside bound (fat arrow) functions"),0<=t.call(Object.keys(this.first),"expression")&&!(this.first instanceof Ot)?null!=this.first.expression&&i.push(this.first.expression.compileToFragments(n,$)):(n.level>=J&&i.push([this.makeCode("(")]),i.push([this.makeCode(r)]),""!==(null==(o=this.first.base)?void 0:o.value)&&i.push([this.makeCode(" ")]),i.push(this.first.compileToFragments(n,$)),n.level>=J&&i.push([this.makeCode(")")])),this.joinFragmentArrays(i,"")}},{key:"compilePower",value:function(t){var n;return n=new Pt(new _("Math"),[new i(new ct("pow"))]),(new h(n,[this.first,this.second])).compileToFragments(t)}},{key:"compileFloorDivision",value:function(t){var n,r,o;return r=new Pt(new _("Math"),[new i(new ct("floor"))]),o=this.second.shouldCache()?new ft(this.second):this.second,n=new s("/",this.first,o),(new h(r,[n])).compileToFragments(t)}},{key:"compileModulo",value:function(t){var n;return n=new Pt(new G(an("modulo",t))),(new h(n,[this.first,this.second])).compileToFragments(t)}},{key:"toString",value:function u(e){return _get(s.prototype.__proto__||Object.getPrototypeOf(s.prototype),"toString",this).call(this,e,this.constructor.name+" "+this.operator)}}]),s}(a),n,r;return n={"==":"===","!=":"!==",of:"in",yieldfrom:"yield*"},r={"!==":"===","===":"!=="},e.prototype.children=["first","second"],e}.call(this),e.In=q=function(){var e=function(e){function t(e,n){_classCallCheck(this,t);var r=_possibleConstructorReturn(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return r.object=e,r.array=n,r}return _inherits(t,e),_createClass(t,[{key:"compileNode",value:function(t){var n,r,i,s,o;if(this.array instanceof Pt&&this.array.isArray()&&this.array.base.objects.length){for(o=this.array.base.objects,r=0,i=o.length;r= 0"))),Xt(o)===Xt(s))?i:(i=o.concat(this.makeCode(", "),i),t.levelt.call(s,n)&&s.push(n);return delete e.comments}}),It(s,i),Zt(i.expression,i),i}return _inherits(n,e),_createClass(n,[{key:"compileNode",value:function(t){var n,r,i;if(this.expression.front=this.front,i=this.expression.compile(t,$),this.expression.unwrap()instanceof _&&!t.scope.check(i)){var s=this.negated?["===","||"]:["!==","&&"],o=_slicedToArray(s,2);n=o[0],r=o[1],i="typeof "+i+" "+n+' "undefined"'+("undefined"===this.comparisonTarget?"":" "+r+" "+i+" "+n+" "+this.comparisonTarget)}else n="null"===this.comparisonTarget?this.negated?"==":"!=":this.negated?"===":"!==",i=i+" "+n+" "+this.comparisonTarget;return[this.makeCode(t.level<=X?i:"("+i+")")]}}]),n}(a);return e.prototype.children=["expression"],e.prototype.invert=tt,e}.call(this),e.Parens=ft=function(){var e=function(e){function t(e){_classCallCheck(this,t);var n=_possibleConstructorReturn(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return n.body=e,n}return _inherits(t,e),_createClass(t,[{key:"unwrap",value:function(){return this.body}},{key:"shouldCache",value:function(){return this.body.shouldCache()}},{key:"compileNode",value:function(t){var n,r,i,s,o;return(r=this.body.unwrap(),o=null==(s=r.comments)?void 0:s.some(function(e){return e.here&&!e.unshift&&!e.newLine}),r instanceof Pt&&r.isAtomic()&&!this.csxAttribute&&!o)?(r.front=this.front,r.compileToFragments(t)):(i=r.compileToFragments(t,J),n=t.level<$&&!o&&(r instanceof ut||r.unwrap()instanceof h||r instanceof L&&r.returns)&&(t.level=i.length),this.csxAttribute?this.wrapInBraces(i):n?i:this.wrapInParentheses(i))}}]),t}(a);return e.prototype.children=["body"],e}.call(this),e.StringWithInterpolations=St=function(){var e=function(e){function t(e){_classCallCheck(this,t);var n=_possibleConstructorReturn(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return n.body=e,n}return _inherits(t,e),_createClass(t,[{key:"unwrap",value:function(){return this}},{key:"shouldCache",value:function(){return this.body.shouldCache()}},{key:"compileNode",value:function(n){var r,i,s,o,u,a,f,l,c;if(this.csxAttribute)return c=new ft(new t(this.body)),c.csxAttribute=!0,c.compileNode(n);for(o=this.body.unwrap(),s=[],l=[],o.traverseChildren(!1,function(e){var t,n,r,i,o,u;if(e instanceof Et){if(e.comments){var a;(a=l).push.apply(a,_toConsumableArray(e.comments)),delete e.comments}return s.push(e),!0}if(e instanceof ft){if(0!==l.length){for(n=0,i=l.length;nF,(!this.step||null==F||!d)&&(N=H.freeVariable("len")),c=""+x+E+" = 0, "+N+" = "+q+".length",h=""+x+E+" = "+q+".length - 1",a=E+" < "+N,l=E+" >= 0",this.step?(null==F?(a=I+" > 0 ? "+a+" : "+l,c="("+I+" > 0 ? ("+c+") : "+h+")"):d&&(a=l,c=h),b=E+" += "+I):b=""+(S===E?E+"++":"++"+E),v=[this.makeCode(c+"; "+a+"; "+x+b)])),this.returns&&(O=""+this.tab+P+" = [];\n",M="\n"+this.tab+"return "+P+";",s.makeReturn(P)),this.guard&&(1=X?this.wrapInParentheses(s):s}},{key:"unfoldSoak",value:function(){return this.soak&&this}}]),t}(a);return e.prototype.children=["condition","body","elseBody"],e}.call(this),_t={modulo:function(){return"function(a, b) { return (+a % (b = +b) + b) % b; }"},objectWithoutKeys:function(){return"function(o, ks) { var res = {}; for (var k in o) ([].indexOf.call(ks, k) < 0 && {}.hasOwnProperty.call(o, k)) && (res[k] = o[k]); return res; }"},boundMethodCheck:function(){return"function(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new Error('Bound instance method accessed before binding'); } }"},_extends:function(){return"Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }"},hasProp:function(){return"{}.hasOwnProperty"},indexOf:function(){return"[].indexOf"},slice:function(){return"[].slice"},splice:function(){return"[].splice"}},K=1,J=2,V=3,X=4,$=5,W=6,Ct=" ",mt=/^[+-]?\d+$/,an=function(e,t){var n,r;return r=t.scope.root,e in r.utilities?r.utilities[e]:(n=r.freeVariable(e),r.assign(n,_t[e](t)),r.utilities[e]=n)},en=function(e,t){var n=!(2=t);)t--;return n&&[n.sourceLine,n.sourceColumn]}}]),e}(),n=function(){var e=function(){function e(){_classCallCheck(this,e),this.lines=[]}return _createClass(e,[{key:"add",value:function(n,r){var i=2=r);)r--;return s&&s.sourceLocation(i)}},{key:"generate",value:function(){var t=0"],y={version:3,file:t.generatedFile||"",sourceRoot:t.sourceRoot||"",sources:g,names:[],mappings:r},(t.sourceMap||t.inlineMap)&&(y.sourcesContent=[n]),y}},{key:"encodeVlq",value:function(t){var n,u,a,f;for(n="",a=0>t?1:0,f=(_Mathabs(t)<<1)+a;f||!n;)u=f&s,f>>=i,f&&(u|=r),n+=this.encodeBase64(u);return n}},{key:"encodeBase64",value:function(t){return n[t]||function(){throw new Error("Cannot Base64 encode value: "+t)}()}}]),e}(),n,r,i,s;return i=5,r=1<",u(a,e),null==m[a]&&(m[a]=[]),m[a].push(e),p&&(x=new s),O=h.tokenize(e,t),t.referencedVars=function(){var e,t,n;for(n=[],e=0,t=O.length;e"),f=e.getLineNumber(),r=e.getColumnNumber(),c=t(s,f,r),i=c?s+":"+c[0]+":"+c[1]:s+":"+f+":"+r),o=e.getFunctionName(),u=e.isConstructor(),a=!e.isToplevel()&&!u,a?(l=e.getMethodName(),p=e.getTypeName(),o?(h=n="",p&&o.indexOf(p)&&(h=p+"."),l&&o.indexOf("."+l)!==o.length-l.length-1&&(n=" [as "+l+"]"),""+h+o+n+" ("+i+")"):p+"."+(l||"")+" ("+i+")"):u?"new "+(o||"")+" ("+i+")":o?o+" ("+i+")":i},l=function(e,n,i){var s,o,u,f,l,h;if(""===e||(f=e.slice(e.lastIndexOf(".")),0<=t.call(r,f))){if(""!==e&&null!=v[e])return v[e][v[e].length-1];if(null!=v[""])for(l=v[""],o=l.length-1;0<=o;o+=-1)if(u=l[o],h=u.sourceLocation([n-1,i-1]),null!=(null==h?void 0:h[0])&&null!=h[1])return u;return null==m[e]?null:(s=a(m[e][m[e].length-1],{filename:e,sourceMap:!0,literate:c.isLiterate(e)}),s.sourceMap)}return null},Error.prepareStackTrace=function(t,n){var r,i,s;return s=function(e,t,n){var r,i;return i=l(e,t,n),null!=i&&(r=i.sourceLocation([t-1,n-1])),null==r?null:[r[0]+1,r[1]+1]},i=function(){var t,i,o;for(o=[],t=0,i=n.length;t0||-1)*Math.floor(Math.abs(e))),e}function B(e){var t=typeof e;return e===null||t==="undefined"||t==="boolean"||t==="number"||t==="string"}function j(e){var t,n,r;if(B(e))return e;n=e.valueOf;if(typeof n=="function"){t=n.call(e);if(B(t))return t}r=e.toString;if(typeof r=="function"){t=r.call(e);if(B(t))return t}throw new TypeError}Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!="function")throw new TypeError("Function.prototype.bind called on incompatible "+n);var i=u.call(arguments,1),s=function(){if(this instanceof s){var e=n.apply(this,i.concat(u.call(arguments)));return Object(e)===e?e:this}return n.apply(t,i.concat(u.call(arguments)))};return n.prototype&&(r.prototype=n.prototype,s.prototype=new r,r.prototype=null),s});var i=Function.prototype.call,s=Array.prototype,o=Object.prototype,u=s.slice,a=i.bind(o.toString),f=i.bind(o.hasOwnProperty),l,c,h,p,d;if(d=f(o,"__defineGetter__"))l=i.bind(o.__defineGetter__),c=i.bind(o.__defineSetter__),h=i.bind(o.__lookupGetter__),p=i.bind(o.__lookupSetter__);if([1,2].splice(0).length!=2)if(!function(){function e(e){var t=new Array(e+2);return t[0]=t[1]=0,t}var t=[],n;t.splice.apply(t,e(20)),t.splice.apply(t,e(26)),n=t.length,t.splice(5,0,"XXX"),n+1==t.length;if(n+1==t.length)return!0}())Array.prototype.splice=function(e,t){var n=this.length;e>0?e>n&&(e=n):e==void 0?e=0:e<0&&(e=Math.max(n+e,0)),e+ta)for(h=l;h--;)this[f+h]=this[a+h];if(s&&e===c)this.length=c,this.push.apply(this,i);else{this.length=c+s;for(h=0;h>>0;if(a(t)!="[object Function]")throw new TypeError;while(++s>>0,s=Array(i),o=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var u=0;u>>0,s=[],o,u=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var f=0;f>>0,s=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var o=0;o>>0,s=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var o=0;o>>0;if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");if(!i&&arguments.length==1)throw new TypeError("reduce of empty array with no initial value");var s=0,o;if(arguments.length>=2)o=arguments[1];else do{if(s in r){o=r[s++];break}if(++s>=i)throw new TypeError("reduce of empty array with no initial value")}while(!0);for(;s>>0;if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");if(!i&&arguments.length==1)throw new TypeError("reduceRight of empty array with no initial value");var s,o=i-1;if(arguments.length>=2)s=arguments[1];else do{if(o in r){s=r[o--];break}if(--o<0)throw new TypeError("reduceRight of empty array with no initial value")}while(!0);do o in this&&(s=t.call(void 0,s,r[o],o,n));while(o--);return s});if(!Array.prototype.indexOf||[0,1].indexOf(1,2)!=-1)Array.prototype.indexOf=function(t){var n=g&&a(this)=="[object String]"?this.split(""):F(this),r=n.length>>>0;if(!r)return-1;var i=0;arguments.length>1&&(i=H(arguments[1])),i=i>=0?i:Math.max(0,r+i);for(;i>>0;if(!r)return-1;var i=r-1;arguments.length>1&&(i=Math.min(i,H(arguments[1]))),i=i>=0?i:r-Math.abs(i);for(;i>=0;i--)if(i in n&&t===n[i])return i;return-1};Object.getPrototypeOf||(Object.getPrototypeOf=function(t){return t.__proto__||(t.constructor?t.constructor.prototype:o)});if(!Object.getOwnPropertyDescriptor){var y="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(t,n){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(y+t);if(!f(t,n))return;var r,i,s;r={enumerable:!0,configurable:!0};if(d){var u=t.__proto__;t.__proto__=o;var i=h(t,n),s=p(t,n);t.__proto__=u;if(i||s)return i&&(r.get=i),s&&(r.set=s),r}return r.value=t[n],r}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(t){return Object.keys(t)});if(!Object.create){var b;Object.prototype.__proto__===null?b=function(){return{__proto__:null}}:b=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(t,n){var r;if(t===null)r=b();else{if(typeof t!="object")throw new TypeError("typeof prototype["+typeof t+"] != 'object'");var i=function(){};i.prototype=t,r=new i,r.__proto__=t}return n!==void 0&&Object.defineProperties(r,n),r}}if(Object.defineProperty){var E=w({}),S=typeof document=="undefined"||w(document.createElement("div"));if(!E||!S)var x=Object.defineProperty}if(!Object.defineProperty||x){var T="Property description must be an object: ",N="Object.defineProperty called on non-object: ",C="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(t,n,r){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(N+t);if(typeof r!="object"&&typeof r!="function"||r===null)throw new TypeError(T+r);if(x)try{return x.call(Object,t,n,r)}catch(i){}if(f(r,"value"))if(d&&(h(t,n)||p(t,n))){var s=t.__proto__;t.__proto__=o,delete t[n],t[n]=r.value,t.__proto__=s}else t[n]=r.value;else{if(!d)throw new TypeError(C);f(r,"get")&&l(t,n,r.get),f(r,"set")&&c(t,n,r.set)}return t}}Object.defineProperties||(Object.defineProperties=function(t,n){for(var r in n)f(n,r)&&Object.defineProperty(t,r,n[r]);return t}),Object.seal||(Object.seal=function(t){return t}),Object.freeze||(Object.freeze=function(t){return t});try{Object.freeze(function(){})}catch(k){Object.freeze=function(t){return function(n){return typeof n=="function"?n:t(n)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(t){return t}),Object.isSealed||(Object.isSealed=function(t){return!1}),Object.isFrozen||(Object.isFrozen=function(t){return!1}),Object.isExtensible||(Object.isExtensible=function(t){if(Object(t)===t)throw new TypeError;var n="";while(f(t,n))n+="?";t[n]=!0;var r=f(t,n);return delete t[n],r});if(!Object.keys){var L=!0,A=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],O=A.length;for(var M in{toString:null})L=!1;Object.keys=function I(e){if(typeof e!="object"&&typeof e!="function"||e===null)throw new TypeError("Object.keys called on a non-object");var I=[];for(var t in e)f(e,t)&&I.push(t);if(L)for(var n=0,r=O;n [" + + this.end.row + + "/" + + this.end.column + + "]" + ); + }), + (this.contains = function (e, t) { + return this.compare(e, t) == 0; + }), + (this.compareRange = function (e) { + var t, + n = e.end, + r = e.start; + return ( + (t = this.compare(n.row, n.column)), + t == 1 + ? ((t = this.compare(r.row, r.column)), t == 1 ? 2 : t == 0 ? 1 : 0) + : t == -1 + ? -2 + : ((t = this.compare(r.row, r.column)), + t == -1 ? -1 : t == 1 ? 42 : 0) + ); + }), + (this.comparePoint = function (e) { + return this.compare(e.row, e.column); + }), + (this.containsRange = function (e) { + return this.comparePoint(e.start) == 0 && this.comparePoint(e.end) == 0; + }), + (this.intersects = function (e) { + var t = this.compareRange(e); + return t == -1 || t == 0 || t == 1; + }), + (this.isEnd = function (e, t) { + return this.end.row == e && this.end.column == t; + }), + (this.isStart = function (e, t) { + return this.start.row == e && this.start.column == t; + }), + (this.setStart = function (e, t) { + typeof e == "object" + ? ((this.start.column = e.column), (this.start.row = e.row)) + : ((this.start.row = e), (this.start.column = t)); + }), + (this.setEnd = function (e, t) { + typeof e == "object" + ? ((this.end.column = e.column), (this.end.row = e.row)) + : ((this.end.row = e), (this.end.column = t)); + }), + (this.inside = function (e, t) { + return this.compare(e, t) == 0 + ? this.isEnd(e, t) || this.isStart(e, t) + ? !1 + : !0 + : !1; + }), + (this.insideStart = function (e, t) { + return this.compare(e, t) == 0 ? (this.isEnd(e, t) ? !1 : !0) : !1; + }), + (this.insideEnd = function (e, t) { + return this.compare(e, t) == 0 ? (this.isStart(e, t) ? !1 : !0) : !1; + }), + (this.compare = function (e, t) { + return !this.isMultiLine() && e === this.start.row + ? t < this.start.column + ? -1 + : t > this.end.column + ? 1 + : 0 + : e < this.start.row + ? -1 + : e > this.end.row + ? 1 + : this.start.row === e + ? t >= this.start.column + ? 0 + : -1 + : this.end.row === e + ? t <= this.end.column + ? 0 + : 1 + : 0; + }), + (this.compareStart = function (e, t) { + return this.start.row == e && this.start.column == t ? -1 : this.compare(e, t); + }), + (this.compareEnd = function (e, t) { + return this.end.row == e && this.end.column == t ? 1 : this.compare(e, t); + }), + (this.compareInside = function (e, t) { + return this.end.row == e && this.end.column == t + ? 1 + : this.start.row == e && this.start.column == t + ? -1 + : this.compare(e, t); + }), + (this.clipRows = function (e, t) { + if (this.end.row > t) var n = { row: t + 1, column: 0 }; + else if (this.end.row < e) var n = { row: e, column: 0 }; + if (this.start.row > t) var r = { row: t + 1, column: 0 }; + else if (this.start.row < e) var r = { row: e, column: 0 }; + return i.fromPoints(r || this.start, n || this.end); + }), + (this.extend = function (e, t) { + var n = this.compare(e, t); + if (n == 0) return this; + if (n == -1) var r = { row: e, column: t }; + else var s = { row: e, column: t }; + return i.fromPoints(r || this.start, s || this.end); + }), + (this.isEmpty = function () { + return this.start.row === this.end.row && this.start.column === this.end.column; + }), + (this.isMultiLine = function () { + return this.start.row !== this.end.row; + }), + (this.clone = function () { + return i.fromPoints(this.start, this.end); + }), + (this.collapseRows = function () { + return this.end.column == 0 + ? new i(this.start.row, 0, Math.max(this.start.row, this.end.row - 1), 0) + : new i(this.start.row, 0, this.end.row, 0); + }), + (this.toScreenRange = function (e) { + var t = e.documentToScreenPosition(this.start), + n = e.documentToScreenPosition(this.end); + return new i(t.row, t.column, n.row, n.column); + }), + (this.moveBy = function (e, t) { + (this.start.row += e), + (this.start.column += t), + (this.end.row += e), + (this.end.column += t); + }); + }).call(i.prototype), + (i.fromPoints = function (e, t) { + return new i(e.row, e.column, t.row, t.column); + }), + (i.comparePoints = r), + (i.comparePoints = function (e, t) { + return e.row - t.row || e.column - t.column; + }), + (t.Range = i); + }), + define("ace/apply_delta", [], function (e, t, n) { + "use strict"; + function r(e, t) { + throw (console.log("Invalid Delta:", e), "Invalid Delta: " + t); + } + function i(e, t) { + return t.row >= 0 && t.row < e.length && t.column >= 0 && t.column <= e[t.row].length; + } + function s(e, t) { + t.action != "insert" && + t.action != "remove" && + r(t, "delta.action must be 'insert' or 'remove'"), + t.lines instanceof Array || r(t, "delta.lines must be an Array"), + (!t.start || !t.end) && r(t, "delta.start/end must be an present"); + var n = t.start; + i(e, t.start) || r(t, "delta.start must be contained in document"); + var s = t.end; + t.action == "remove" && + !i(e, s) && + r(t, "delta.end must contained in document for 'remove' actions"); + var o = s.row - n.row, + u = s.column - (o == 0 ? n.column : 0); + (o != t.lines.length - 1 || t.lines[o].length != u) && + r(t, "delta.range must match delta lines"); + } + t.applyDelta = function (e, t, n) { + var r = t.start.row, + i = t.start.column, + s = e[r] || ""; + switch (t.action) { + case "insert": + var o = t.lines; + if (o.length === 1) e[r] = s.substring(0, i) + t.lines[0] + s.substring(i); + else { + var u = [r, 1].concat(t.lines); + e.splice.apply(e, u), + (e[r] = s.substring(0, i) + e[r]), + (e[r + t.lines.length - 1] += s.substring(i)); + } + break; + case "remove": + var a = t.end.column, + f = t.end.row; + r === f + ? (e[r] = s.substring(0, i) + s.substring(a)) + : e.splice(r, f - r + 1, s.substring(0, i) + e[f].substring(a)); + } + }; + }), + define("ace/lib/event_emitter", [], function (e, t, n) { + "use strict"; + var r = {}, + i = function () { + this.propagationStopped = !0; + }, + s = function () { + this.defaultPrevented = !0; + }; + (r._emit = r._dispatchEvent = + function (e, t) { + this._eventRegistry || (this._eventRegistry = {}), + this._defaultHandlers || (this._defaultHandlers = {}); + var n = this._eventRegistry[e] || [], + r = this._defaultHandlers[e]; + if (!n.length && !r) return; + if (typeof t != "object" || !t) t = {}; + t.type || (t.type = e), + t.stopPropagation || (t.stopPropagation = i), + t.preventDefault || (t.preventDefault = s), + (n = n.slice()); + for (var o = 0; o < n.length; o++) { + n[o](t, this); + if (t.propagationStopped) break; + } + if (r && !t.defaultPrevented) return r(t, this); + }), + (r._signal = function (e, t) { + var n = (this._eventRegistry || {})[e]; + if (!n) return; + n = n.slice(); + for (var r = 0; r < n.length; r++) n[r](t, this); + }), + (r.once = function (e, t) { + var n = this; + t && + this.addEventListener(e, function r() { + n.removeEventListener(e, r), t.apply(null, arguments); + }); + }), + (r.setDefaultHandler = function (e, t) { + var n = this._defaultHandlers; + n || (n = this._defaultHandlers = { _disabled_: {} }); + if (n[e]) { + var r = n[e], + i = n._disabled_[e]; + i || (n._disabled_[e] = i = []), i.push(r); + var s = i.indexOf(t); + s != -1 && i.splice(s, 1); + } + n[e] = t; + }), + (r.removeDefaultHandler = function (e, t) { + var n = this._defaultHandlers; + if (!n) return; + var r = n._disabled_[e]; + if (n[e] == t) r && this.setDefaultHandler(e, r.pop()); + else if (r) { + var i = r.indexOf(t); + i != -1 && r.splice(i, 1); + } + }), + (r.on = r.addEventListener = + function (e, t, n) { + this._eventRegistry = this._eventRegistry || {}; + var r = this._eventRegistry[e]; + return ( + r || (r = this._eventRegistry[e] = []), + r.indexOf(t) == -1 && r[n ? "unshift" : "push"](t), + t + ); + }), + (r.off = + r.removeListener = + r.removeEventListener = + function (e, t) { + this._eventRegistry = this._eventRegistry || {}; + var n = this._eventRegistry[e]; + if (!n) return; + var r = n.indexOf(t); + r !== -1 && n.splice(r, 1); + }), + (r.removeAllListeners = function (e) { + this._eventRegistry && (this._eventRegistry[e] = []); + }), + (t.EventEmitter = r); + }), + define("ace/anchor", [], function (e, t, n) { + "use strict"; + var r = e("./lib/oop"), + i = e("./lib/event_emitter").EventEmitter, + s = (t.Anchor = function (e, t, n) { + (this.$onChange = this.onChange.bind(this)), + this.attach(e), + typeof n == "undefined" + ? this.setPosition(t.row, t.column) + : this.setPosition(t, n); + }); + (function () { + function e(e, t, n) { + var r = n ? e.column <= t.column : e.column < t.column; + return e.row < t.row || (e.row == t.row && r); + } + function t(t, n, r) { + var i = t.action == "insert", + s = (i ? 1 : -1) * (t.end.row - t.start.row), + o = (i ? 1 : -1) * (t.end.column - t.start.column), + u = t.start, + a = i ? u : t.end; + return e(n, u, r) + ? { row: n.row, column: n.column } + : e(a, n, !r) + ? { row: n.row + s, column: n.column + (n.row == a.row ? o : 0) } + : { row: u.row, column: u.column }; + } + r.implement(this, i), + (this.getPosition = function () { + return this.$clipPositionToDocument(this.row, this.column); + }), + (this.getDocument = function () { + return this.document; + }), + (this.$insertRight = !1), + (this.onChange = function (e) { + if (e.start.row == e.end.row && e.start.row != this.row) return; + if (e.start.row > this.row) return; + var n = t(e, { row: this.row, column: this.column }, this.$insertRight); + this.setPosition(n.row, n.column, !0); + }), + (this.setPosition = function (e, t, n) { + var r; + n ? (r = { row: e, column: t }) : (r = this.$clipPositionToDocument(e, t)); + if (this.row == r.row && this.column == r.column) return; + var i = { row: this.row, column: this.column }; + (this.row = r.row), + (this.column = r.column), + this._signal("change", { old: i, value: r }); + }), + (this.detach = function () { + this.document.removeEventListener("change", this.$onChange); + }), + (this.attach = function (e) { + (this.document = e || this.document), + this.document.on("change", this.$onChange); + }), + (this.$clipPositionToDocument = function (e, t) { + var n = {}; + return ( + e >= this.document.getLength() + ? ((n.row = Math.max(0, this.document.getLength() - 1)), + (n.column = this.document.getLine(n.row).length)) + : e < 0 + ? ((n.row = 0), (n.column = 0)) + : ((n.row = e), + (n.column = Math.min( + this.document.getLine(n.row).length, + Math.max(0, t), + ))), + t < 0 && (n.column = 0), + n + ); + }); + }).call(s.prototype); + }), + define("ace/document", [], function (e, t, n) { + "use strict"; + var r = e("./lib/oop"), + i = e("./apply_delta").applyDelta, + s = e("./lib/event_emitter").EventEmitter, + o = e("./range").Range, + u = e("./anchor").Anchor, + a = function (e) { + (this.$lines = [""]), + e.length === 0 + ? (this.$lines = [""]) + : Array.isArray(e) + ? this.insertMergedLines({ row: 0, column: 0 }, e) + : this.insert({ row: 0, column: 0 }, e); + }; + (function () { + r.implement(this, s), + (this.setValue = function (e) { + var t = this.getLength() - 1; + this.remove(new o(0, 0, t, this.getLine(t).length)), + this.insert({ row: 0, column: 0 }, e); + }), + (this.getValue = function () { + return this.getAllLines().join(this.getNewLineCharacter()); + }), + (this.createAnchor = function (e, t) { + return new u(this, e, t); + }), + "aaa".split(/a/).length === 0 + ? (this.$split = function (e) { + return e.replace(/\r\n|\r/g, "\n").split("\n"); + }) + : (this.$split = function (e) { + return e.split(/\r\n|\r|\n/); + }), + (this.$detectNewLine = function (e) { + var t = e.match(/^.*?(\r\n|\r|\n)/m); + (this.$autoNewLine = t ? t[1] : "\n"), this._signal("changeNewLineMode"); + }), + (this.getNewLineCharacter = function () { + switch (this.$newLineMode) { + case "windows": + return "\r\n"; + case "unix": + return "\n"; + default: + return this.$autoNewLine || "\n"; + } + }), + (this.$autoNewLine = ""), + (this.$newLineMode = "auto"), + (this.setNewLineMode = function (e) { + if (this.$newLineMode === e) return; + (this.$newLineMode = e), this._signal("changeNewLineMode"); + }), + (this.getNewLineMode = function () { + return this.$newLineMode; + }), + (this.isNewLine = function (e) { + return e == "\r\n" || e == "\r" || e == "\n"; + }), + (this.getLine = function (e) { + return this.$lines[e] || ""; + }), + (this.getLines = function (e, t) { + return this.$lines.slice(e, t + 1); + }), + (this.getAllLines = function () { + return this.getLines(0, this.getLength()); + }), + (this.getLength = function () { + return this.$lines.length; + }), + (this.getTextRange = function (e) { + return this.getLinesForRange(e).join(this.getNewLineCharacter()); + }), + (this.getLinesForRange = function (e) { + var t; + if (e.start.row === e.end.row) + t = [this.getLine(e.start.row).substring(e.start.column, e.end.column)]; + else { + (t = this.getLines(e.start.row, e.end.row)), + (t[0] = (t[0] || "").substring(e.start.column)); + var n = t.length - 1; + e.end.row - e.start.row == n && (t[n] = t[n].substring(0, e.end.column)); + } + return t; + }), + (this.insertLines = function (e, t) { + return ( + console.warn( + "Use of document.insertLines is deprecated. Use the insertFullLines method instead.", + ), + this.insertFullLines(e, t) + ); + }), + (this.removeLines = function (e, t) { + return ( + console.warn( + "Use of document.removeLines is deprecated. Use the removeFullLines method instead.", + ), + this.removeFullLines(e, t) + ); + }), + (this.insertNewLine = function (e) { + return ( + console.warn( + "Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead.", + ), + this.insertMergedLines(e, ["", ""]) + ); + }), + (this.insert = function (e, t) { + return ( + this.getLength() <= 1 && this.$detectNewLine(t), + this.insertMergedLines(e, this.$split(t)) + ); + }), + (this.insertInLine = function (e, t) { + var n = this.clippedPos(e.row, e.column), + r = this.pos(e.row, e.column + t.length); + return ( + this.applyDelta({ start: n, end: r, action: "insert", lines: [t] }, !0), + this.clonePos(r) + ); + }), + (this.clippedPos = function (e, t) { + var n = this.getLength(); + e === undefined + ? (e = n) + : e < 0 + ? (e = 0) + : e >= n && ((e = n - 1), (t = undefined)); + var r = this.getLine(e); + return ( + t == undefined && (t = r.length), + (t = Math.min(Math.max(t, 0), r.length)), + { row: e, column: t } + ); + }), + (this.clonePos = function (e) { + return { row: e.row, column: e.column }; + }), + (this.pos = function (e, t) { + return { row: e, column: t }; + }), + (this.$clipPosition = function (e) { + var t = this.getLength(); + return ( + e.row >= t + ? ((e.row = Math.max(0, t - 1)), + (e.column = this.getLine(t - 1).length)) + : ((e.row = Math.max(0, e.row)), + (e.column = Math.min( + Math.max(e.column, 0), + this.getLine(e.row).length, + ))), + e + ); + }), + (this.insertFullLines = function (e, t) { + e = Math.min(Math.max(e, 0), this.getLength()); + var n = 0; + e < this.getLength() + ? ((t = t.concat([""])), (n = 0)) + : ((t = [""].concat(t)), e--, (n = this.$lines[e].length)), + this.insertMergedLines({ row: e, column: n }, t); + }), + (this.insertMergedLines = function (e, t) { + var n = this.clippedPos(e.row, e.column), + r = { + row: n.row + t.length - 1, + column: (t.length == 1 ? n.column : 0) + t[t.length - 1].length, + }; + return ( + this.applyDelta({ start: n, end: r, action: "insert", lines: t }), + this.clonePos(r) + ); + }), + (this.remove = function (e) { + var t = this.clippedPos(e.start.row, e.start.column), + n = this.clippedPos(e.end.row, e.end.column); + return ( + this.applyDelta({ + start: t, + end: n, + action: "remove", + lines: this.getLinesForRange({ start: t, end: n }), + }), + this.clonePos(t) + ); + }), + (this.removeInLine = function (e, t, n) { + var r = this.clippedPos(e, t), + i = this.clippedPos(e, n); + return ( + this.applyDelta( + { + start: r, + end: i, + action: "remove", + lines: this.getLinesForRange({ start: r, end: i }), + }, + !0, + ), + this.clonePos(r) + ); + }), + (this.removeFullLines = function (e, t) { + (e = Math.min(Math.max(0, e), this.getLength() - 1)), + (t = Math.min(Math.max(0, t), this.getLength() - 1)); + var n = t == this.getLength() - 1 && e > 0, + r = t < this.getLength() - 1, + i = n ? e - 1 : e, + s = n ? this.getLine(i).length : 0, + u = r ? t + 1 : t, + a = r ? 0 : this.getLine(u).length, + f = new o(i, s, u, a), + l = this.$lines.slice(e, t + 1); + return ( + this.applyDelta({ + start: f.start, + end: f.end, + action: "remove", + lines: this.getLinesForRange(f), + }), + l + ); + }), + (this.removeNewLine = function (e) { + e < this.getLength() - 1 && + e >= 0 && + this.applyDelta({ + start: this.pos(e, this.getLine(e).length), + end: this.pos(e + 1, 0), + action: "remove", + lines: ["", ""], + }); + }), + (this.replace = function (e, t) { + e instanceof o || (e = o.fromPoints(e.start, e.end)); + if (t.length === 0 && e.isEmpty()) return e.start; + if (t == this.getTextRange(e)) return e.end; + this.remove(e); + var n; + return t ? (n = this.insert(e.start, t)) : (n = e.start), n; + }), + (this.applyDeltas = function (e) { + for (var t = 0; t < e.length; t++) this.applyDelta(e[t]); + }), + (this.revertDeltas = function (e) { + for (var t = e.length - 1; t >= 0; t--) this.revertDelta(e[t]); + }), + (this.applyDelta = function (e, t) { + var n = e.action == "insert"; + if (n ? e.lines.length <= 1 && !e.lines[0] : !o.comparePoints(e.start, e.end)) + return; + n && e.lines.length > 2e4 + ? this.$splitAndapplyLargeDelta(e, 2e4) + : (i(this.$lines, e, t), this._signal("change", e)); + }), + (this.$splitAndapplyLargeDelta = function (e, t) { + var n = e.lines, + r = n.length - t + 1, + i = e.start.row, + s = e.start.column; + for (var o = 0, u = 0; o < r; o = u) { + u += t - 1; + var a = n.slice(o, u); + a.push(""), + this.applyDelta( + { + start: this.pos(i + o, s), + end: this.pos(i + u, (s = 0)), + action: e.action, + lines: a, + }, + !0, + ); + } + (e.lines = n.slice(o)), + (e.start.row = i + o), + (e.start.column = s), + this.applyDelta(e, !0); + }), + (this.revertDelta = function (e) { + this.applyDelta({ + start: this.clonePos(e.start), + end: this.clonePos(e.end), + action: e.action == "insert" ? "remove" : "insert", + lines: e.lines.slice(), + }); + }), + (this.indexToPosition = function (e, t) { + var n = this.$lines || this.getAllLines(), + r = this.getNewLineCharacter().length; + for (var i = t || 0, s = n.length; i < s; i++) { + e -= n[i].length + r; + if (e < 0) return { row: i, column: e + n[i].length + r }; + } + return { row: s - 1, column: e + n[s - 1].length + r }; + }), + (this.positionToIndex = function (e, t) { + var n = this.$lines || this.getAllLines(), + r = this.getNewLineCharacter().length, + i = 0, + s = Math.min(e.row, n.length); + for (var o = t || 0; o < s; ++o) i += n[o].length + r; + return i + e.column; + }); + }).call(a.prototype), + (t.Document = a); + }), + define("ace/lib/lang", [], function (e, t, n) { + "use strict"; + (t.last = function (e) { + return e[e.length - 1]; + }), + (t.stringReverse = function (e) { + return e.split("").reverse().join(""); + }), + (t.stringRepeat = function (e, t) { + var n = ""; + while (t > 0) { + t & 1 && (n += e); + if ((t >>= 1)) e += e; + } + return n; + }); + var r = /^\s\s*/, + i = /\s\s*$/; + (t.stringTrimLeft = function (e) { + return e.replace(r, ""); + }), + (t.stringTrimRight = function (e) { + return e.replace(i, ""); + }), + (t.copyObject = function (e) { + var t = {}; + for (var n in e) t[n] = e[n]; + return t; + }), + (t.copyArray = function (e) { + var t = []; + for (var n = 0, r = e.length; n < r; n++) + e[n] && typeof e[n] == "object" + ? (t[n] = this.copyObject(e[n])) + : (t[n] = e[n]); + return t; + }), + (t.deepCopy = function s(e) { + if (typeof e != "object" || !e) return e; + var t; + if (Array.isArray(e)) { + t = []; + for (var n = 0; n < e.length; n++) t[n] = s(e[n]); + return t; + } + if (Object.prototype.toString.call(e) !== "[object Object]") return e; + t = {}; + for (var n in e) t[n] = s(e[n]); + return t; + }), + (t.arrayToMap = function (e) { + var t = {}; + for (var n = 0; n < e.length; n++) t[e[n]] = 1; + return t; + }), + (t.createMap = function (e) { + var t = Object.create(null); + for (var n in e) t[n] = e[n]; + return t; + }), + (t.arrayRemove = function (e, t) { + for (var n = 0; n <= e.length; n++) t === e[n] && e.splice(n, 1); + }), + (t.escapeRegExp = function (e) { + return e.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1"); + }), + (t.escapeHTML = function (e) { + return ("" + e) + .replace(/&/g, "&") + .replace(/"/g, """) + .replace(/'/g, "'") + .replace(/=6" }, + directories: { lib: "./lib/coffeescript" }, + main: "./lib/coffeescript/index", + browser: "./lib/coffeescript/browser", + bin: { coffee: "./bin/coffee", cake: "./bin/cake" }, + files: ["bin", "lib", "register.js", "repl.js"], + scripts: { + test: "node ./bin/cake test", + "test-harmony": "node --harmony ./bin/cake test", + }, + homepage: "http://coffeescript.org", + bugs: "https://github.com/jashkenas/coffeescript/issues", + repository: { + type: "git", + url: "git://github.com/jashkenas/coffeescript.git", + }, + devDependencies: { + "babel-core": "~6.26.0", + "babel-preset-babili": "~0.1.4", + "babel-preset-env": "~1.6.1", + "babel-preset-minify": "^0.3.0", + codemirror: "^5.32.0", + docco: "~0.8.0", + "highlight.js": "~9.12.0", + jison: ">=0.4.18", + "markdown-it": "~8.4.0", + underscore: "~1.8.3", + webpack: "~3.10.0", + }, + dependencies: {}, + }; + })()), + (require["./helpers"] = (function () { + var e = {}; + return ( + function () { + var t, n, r, i, s, o, u, a; + (e.starts = function (e, t, n) { + return t === e.substr(n, t.length); + }), + (e.ends = function (e, t, n) { + var r; + return ( + (r = t.length), + t === e.substr(e.length - r - (n || 0), r) + ); + }), + (e.repeat = u = + function (e, t) { + var n; + for (n = ""; 0 < t; ) + 1 & t && (n += e), (t >>>= 1), (e += e); + return n; + }), + (e.compact = function (e) { + var t, n, r, i; + for (i = [], t = 0, r = e.length; t < r; t++) + (n = e[t]), n && i.push(n); + return i; + }), + (e.count = function (e, t) { + var n, r; + if (((n = r = 0), !t.length)) return 1 / 0; + for (; (r = 1 + e.indexOf(t, r)); ) n++; + return n; + }), + (e.merge = function (e, t) { + return i(i({}, e), t); + }), + (i = e.extend = + function (e, t) { + var n, r; + for (n in t) (r = t[n]), (e[n] = r); + return e; + }), + (e.flatten = s = + function (t) { + var n, r, i, o; + for (r = [], i = 0, o = t.length; i < o; i++) + (n = t[i]), + "[object Array]" === + Object.prototype.toString.call(n) + ? (r = r.concat(s(n))) + : r.push(n); + return r; + }), + (e.del = function (e, t) { + var n; + return (n = e[t]), delete e[t], n; + }), + (e.some = + null == (o = Array.prototype.some) + ? function (e) { + var t, n, r, i; + for (i = this, n = 0, r = i.length; n < r; n++) + if (((t = i[n]), e(t))) return !0; + return !1; + } + : o), + (e.invertLiterate = function (e) { + var t, n, r, i, s, o, u, a, f; + for ( + a = [], + t = /^\s*$/, + r = /^[\t ]/, + u = /^(?:\t?| {0,3})(?:[\*\-\+]|[0-9]{1,9}\.)[ \t]/, + i = !1, + f = e.split("\n"), + n = 0, + s = f.length; + n < s; + n++ + ) + (o = f[n]), + t.test(o) + ? ((i = !1), a.push(o)) + : i || u.test(o) + ? ((i = !0), a.push("# " + o)) + : !i && r.test(o) + ? a.push(o) + : ((i = !0), a.push("# " + o)); + return a.join("\n"); + }), + (n = function (e, t) { + return t + ? { + first_line: e.first_line, + first_column: e.first_column, + last_line: t.last_line, + last_column: t.last_column, + } + : e; + }), + (r = function (e) { + return ( + e.first_line + + "x" + + e.first_column + + "-" + + e.last_line + + "x" + + e.last_column + ); + }), + (e.addDataToNode = function (e, i, s) { + return function (o) { + var u, a, f, l, c, h; + if ( + (null != + (null == o + ? void 0 + : o.updateLocationDataIfMissing) && + null != i && + o.updateLocationDataIfMissing(n(i, s)), + !e.tokenComments) + ) + for ( + e.tokenComments = {}, + l = e.parser.tokens, + u = 0, + a = l.length; + u < a; + u++ + ) + if (((c = l[u]), !!c.comments)) + if ( + ((h = r(c[2])), + null == e.tokenComments[h]) + ) + e.tokenComments[h] = c.comments; + else { + var p; + (p = e.tokenComments[h]).push.apply( + p, + _toConsumableArray(c.comments), + ); + } + return ( + null != o.locationData && + ((f = r(o.locationData)), + null != e.tokenComments[f] && + t(e.tokenComments[f], o)), + o + ); + }; + }), + (e.attachCommentsToNode = t = + function (e, t) { + var n; + if (null != e && 0 !== e.length) + return ( + null == t.comments && (t.comments = []), + (n = t.comments).push.apply( + n, + _toConsumableArray(e), + ) + ); + }), + (e.locationDataToString = function (e) { + var t; + return ( + "2" in e && "first_line" in e[2] + ? (t = e[2]) + : "first_line" in e && (t = e), + t + ? t.first_line + + 1 + + ":" + + (t.first_column + 1) + + "-" + + (t.last_line + 1 + ":" + (t.last_column + 1)) + : "No location data" + ); + }), + (e.baseFileName = function (e) { + var t = + 1 < arguments.length && + void 0 !== arguments[1] && + arguments[1], + n = + 2 < arguments.length && + void 0 !== arguments[2] && + arguments[2], + r, + i; + return ((i = n ? /\\|\// : /\//), + (r = e.split(i)), + (e = r[r.length - 1]), + !(t && 0 <= e.indexOf("."))) + ? e + : ((r = e.split(".")), + r.pop(), + "coffee" === r[r.length - 1] && + 1 < r.length && + r.pop(), + r.join(".")); + }), + (e.isCoffee = function (e) { + return /\.((lit)?coffee|coffee\.md)$/.test(e); + }), + (e.isLiterate = function (e) { + return /\.(litcoffee|coffee\.md)$/.test(e); + }), + (e.throwSyntaxError = function (e, t) { + var n; + throw ( + ((n = new SyntaxError(e)), + (n.location = t), + (n.toString = a), + (n.stack = n.toString()), + n) + ); + }), + (e.updateSyntaxError = function (e, t, n) { + return ( + e.toString === a && + (e.code || (e.code = t), + e.filename || (e.filename = n), + (e.stack = e.toString())), + e + ); + }), + (a = function () { + var e, t, n, r, i, s, o, a, f, l, c, h, p, d; + if (!this.code || !this.location) + return Error.prototype.toString.call(this); + var v = this.location; + return ( + (o = v.first_line), + (s = v.first_column), + (f = v.last_line), + (a = v.last_column), + null == f && (f = o), + null == a && (a = s), + (i = this.filename || "[stdin]"), + (e = this.code.split("\n")[o]), + (d = s), + (r = o === f ? a + 1 : e.length), + (l = + e.slice(0, d).replace(/[^\s]/g, " ") + + u("^", r - d)), + "undefined" != typeof process && + null !== process && + (n = + (null == (c = process.stdout) + ? void 0 + : c.isTTY) && + (null == (h = process.env) || + !h.NODE_DISABLE_COLORS)), + (null == (p = this.colorful) ? n : p) && + ((t = function (e) { + return "" + e + ""; + }), + (e = e.slice(0, d) + t(e.slice(d, r)) + e.slice(r)), + (l = t(l))), + i + + ":" + + (o + 1) + + ":" + + (s + 1) + + ": error: " + + this.message + + "\n" + + e + + "\n" + + l + ); + }), + (e.nameWhitespaceCharacter = function (e) { + return " " === e + ? "space" + : "\n" === e + ? "newline" + : "\r" === e + ? "carriage return" + : " " === e + ? "tab" + : e; + }); + }.call(this), + { exports: e }.exports + ); + })()), + (require["./rewriter"] = (function () { + var e = {}; + return ( + function () { + var t = [].indexOf, + n = require("./helpers"), + r, + i, + s, + o, + u, + a, + f, + l, + c, + h, + p, + d, + v, + m, + g, + y, + b, + w, + E, + S, + x, + T, + N; + for ( + N = n.throwSyntaxError, + x = function (e, t) { + var n, r, i, s, o; + if (e.comments) { + if (t.comments && 0 !== t.comments.length) { + for ( + o = [], s = e.comments, r = 0, i = s.length; + r < i; + r++ + ) + (n = s[r]), + n.unshift + ? o.push(n) + : t.comments.push(n); + t.comments = o.concat(t.comments); + } else t.comments = e.comments; + return delete e.comments; + } + }, + b = function (e, t, n, r) { + var i; + return ( + (i = [e, t]), + (i.generated = !0), + n && (i.origin = n), + r && x(r, i), + i + ); + }, + e.Rewriter = m = + function () { + var e = (function () { + function e() { + _classCallCheck(this, e); + } + return ( + _createClass(e, [ + { + key: "rewrite", + value: function (t) { + var n, r, i; + return ( + (this.tokens = t), + ("undefined" != + typeof process && + null !== process + ? null == + (n = process.env) + ? void 0 + : n.DEBUG_TOKEN_STREAM + : void 0) && + (process.env + .DEBUG_REWRITTEN_TOKEN_STREAM && + console.log( + "Initial token stream:", + ), + console.log( + function () { + var e, t, n, r; + for ( + n = + this + .tokens, + r = [], + e = 0, + t = + n.length; + e < t; + e++ + ) + (i = n[e]), + r.push( + i[0] + + "/" + + i[1] + + (i.comments + ? "*" + : ""), + ); + return r; + } + .call(this) + .join(" "), + )), + this.removeLeadingNewlines(), + this.closeOpenCalls(), + this.closeOpenIndexes(), + this.normalizeLines(), + this.tagPostfixConditionals(), + this.addImplicitBracesAndParens(), + this.addParensToChainedDoIife(), + this.rescueStowawayComments(), + this.addLocationDataToGeneratedTokens(), + this.enforceValidCSXAttributes(), + this.fixOutdentLocationData(), + ("undefined" != + typeof process && + null !== process + ? null == + (r = process.env) + ? void 0 + : r.DEBUG_REWRITTEN_TOKEN_STREAM + : void 0) && + (process.env + .DEBUG_TOKEN_STREAM && + console.log( + "Rewritten token stream:", + ), + console.log( + function () { + var e, t, n, r; + for ( + n = + this + .tokens, + r = [], + e = 0, + t = + n.length; + e < t; + e++ + ) + (i = n[e]), + r.push( + i[0] + + "/" + + i[1] + + (i.comments + ? "*" + : ""), + ); + return r; + } + .call(this) + .join(" "), + )), + this.tokens + ); + }, + }, + { + key: "scanTokens", + value: function (t) { + var n, r, i; + for ( + i = this.tokens, n = 0; + (r = i[n]); + + ) + n += t.call(this, r, n, i); + return !0; + }, + }, + { + key: "detectEnd", + value: function (n, r, i) { + var s = + 3 < arguments.length && + void 0 !== arguments[3] + ? arguments[3] + : {}, + o, + u, + l, + c, + h; + for ( + h = this.tokens, o = 0; + (c = h[n]); + + ) { + if ( + 0 === o && + r.call(this, c, n) + ) + return i.call( + this, + c, + n, + ); + if ( + (((u = c[0]), + 0 <= t.call(f, u)) + ? (o += 1) + : ((l = c[0]), + 0 <= + t.call( + a, + l, + )) && + (o -= 1), + 0 > o) + ) + return s.returnOnNegativeLevel + ? void 0 + : i.call( + this, + c, + n, + ); + n += 1; + } + return n - 1; + }, + }, + { + key: "removeLeadingNewlines", + value: function () { + var t, n, r, i, s, o, u, a, f; + for ( + u = this.tokens, + t = n = 0, + s = u.length; + n < s; + t = ++n + ) { + var l = _slicedToArray( + u[t], + 1, + ); + if ( + ((f = l[0]), + "TERMINATOR" !== f) + ) + break; + } + if (0 !== t) { + for ( + a = this.tokens.slice( + 0, + t, + ), + r = 0, + o = a.length; + r < o; + r++ + ) + (i = a[r]), + x( + i, + this.tokens[t], + ); + return this.tokens.splice( + 0, + t, + ); + } + }, + }, + { + key: "closeOpenCalls", + value: function () { + var t, n; + return ( + (n = function (e) { + var t; + return ( + ")" === + (t = e[0]) || + "CALL_END" === t + ); + }), + (t = function (e) { + return (e[0] = + "CALL_END"); + }), + this.scanTokens( + function (e, r) { + return ( + "CALL_START" === + e[0] && + this.detectEnd( + r + 1, + n, + t, + ), + 1 + ); + }, + ) + ); + }, + }, + { + key: "closeOpenIndexes", + value: function () { + var t, n; + return ( + (n = function (e) { + var t; + return ( + "]" === + (t = e[0]) || + "INDEX_END" === t + ); + }), + (t = function (e) { + return (e[0] = + "INDEX_END"); + }), + this.scanTokens( + function (e, r) { + return ( + "INDEX_START" === + e[0] && + this.detectEnd( + r + 1, + n, + t, + ), + 1 + ); + }, + ) + ); + }, + }, + { + key: "indexOfTag", + value: function (n) { + var r, i, s, o, u; + r = 0; + for ( + var a = arguments.length, + f = Array( + 1 < a ? a - 1 : 0, + ), + l = 1; + l < a; + l++ + ) + f[l - 1] = arguments[l]; + for ( + i = s = 0, o = f.length; + 0 <= o + ? 0 <= s && s < o + : 0 >= s && s > o; + i = 0 <= o ? ++s : --s + ) + if ( + null != f[i] && + ("string" == + typeof f[i] && + (f[i] = [f[i]]), + (u = this.tag( + n + i + r, + )), + 0 > t.call(f[i], u)) + ) + return -1; + return n + i + r - 1; + }, + }, + { + key: "looksObjectish", + value: function (n) { + var r, i; + return ( + -1 !== + this.indexOfTag( + n, + "@", + null, + ":", + ) || + -1 !== + this.indexOfTag( + n, + null, + ":", + ) || + ((i = this.indexOfTag( + n, + f, + )), + -1 !== i && + ((r = null), + this.detectEnd( + i + 1, + function (e) { + var n; + return ( + (n = e[0]), + 0 <= + t.call( + a, + n, + ) + ); + }, + function (e, t) { + return (r = t); + }, + ), + ":" === + this.tag(r + 1))) + ); + }, + }, + { + key: "findTagsBackwards", + value: function (n, r) { + var i, s, o, u, l, c, h; + for ( + i = []; + 0 <= n && + (i.length || + (((u = this.tag(n)), + 0 > t.call(r, u)) && + (((l = this.tag(n)), + 0 > t.call(f, l)) || + this.tokens[n] + .generated) && + ((c = this.tag(n)), + 0 > t.call(v, c)))); + + ) + ((s = this.tag(n)), + 0 <= t.call(a, s)) && + i.push(this.tag(n)), + ((o = this.tag(n)), + 0 <= t.call(f, o)) && + i.length && + i.pop(), + (n -= 1); + return ( + (h = this.tag(n)), + 0 <= t.call(r, h) + ); + }, + }, + { + key: "addImplicitBracesAndParens", + value: function () { + var n, r; + return ( + (n = []), + (r = null), + this.scanTokens( + function (e, o, u) { + var d = this, + m = + _slicedToArray( + e, + 1, + ), + g, + y, + w, + E, + S, + x, + T, + N, + C, + k, + L, + A, + O, + M, + _, + D, + P, + H, + B, + j, + F, + I, + q, + R, + U, + z, + W, + X, + V, + $, + J, + K, + Q; + Q = m[0]; + var G = (B = + 0 < o + ? u[ + o - + 1 + ] + : []), + Y = + _slicedToArray( + G, + 1, + ); + H = Y[0]; + var Z = (D = + o < + u.length - 1 + ? u[ + o + + 1 + ] + : []), + et = + _slicedToArray( + Z, + 1, + ); + if ( + ((_ = et[0]), + (X = + function () { + return n[ + n.length - + 1 + ]; + }), + (V = o), + (w = function ( + e, + ) { + return ( + o - + V + + e + ); + }), + (k = function ( + e, + ) { + var t; + return null == + e || + null == + (t = + e[2]) + ? void 0 + : t.ours; + }), + (A = function ( + e, + ) { + return ( + k(e) && + "{" === + (null == + e + ? void 0 + : e[0]) + ); + }), + (L = function ( + e, + ) { + return ( + k(e) && + "(" === + (null == + e + ? void 0 + : e[0]) + ); + }), + (x = + function () { + return k( + X(), + ); + }), + (T = + function () { + return L( + X(), + ); + }), + (C = + function () { + return A( + X(), + ); + }), + (N = + function () { + var e; + return ( + x() && + "CONTROL" === + (null == + (e = + X()) + ? void 0 + : e[0]) + ); + }), + ($ = function ( + t, + ) { + return ( + n.push([ + "(", + t, + { + ours: !0, + }, + ]), + u.splice( + t, + 0, + b( + "CALL_START", + "(", + [ + "", + "implicit function call", + e[2], + ], + B, + ), + ) + ); + }), + (g = + function () { + return ( + n.pop(), + u.splice( + o, + 0, + b( + "CALL_END", + ")", + [ + "", + "end of input", + e[2], + ], + B, + ), + ), + (o += 1) + ); + }), + (J = function ( + t, + ) { + var r = + !( + 1 < + arguments.length && + void 0 !== + arguments[1] + ) || + arguments[1], + i; + return ( + n.push([ + "{", + t, + { + sameLine: + !0, + startsLine: + r, + ours: !0, + }, + ]), + (i = + new String( + "{", + )), + (i.generated = + !0), + u.splice( + t, + 0, + b( + "{", + i, + e, + B, + ), + ) + ); + }), + (y = function ( + t, + ) { + return ( + (t = + null == + t + ? o + : t), + n.pop(), + u.splice( + t, + 0, + b( + "}", + "}", + e, + B, + ), + ), + (o += 1) + ); + }), + (E = function ( + e, + ) { + var t; + return ( + (t = + null), + d.detectEnd( + e, + function ( + e, + ) { + return ( + "TERMINATOR" === + e[0] + ); + }, + function ( + e, + n, + ) { + return (t = + n); + }, + { + returnOnNegativeLevel: + !0, + }, + ), + null != + t && + d.looksObjectish( + t + + 1, + ) + ); + }), + ((T() || C()) && + 0 <= + t.call( + s, + Q, + )) || + (C() && + ":" === + H && + "FOR" === + Q)) + ) + return ( + n.push([ + "CONTROL", + o, + { + ours: !0, + }, + ]), + w(1) + ); + if ( + "INDENT" === + Q && + x() + ) { + if ( + "=>" !== + H && + "->" !== + H && + "[" !== H && + "(" !== H && + "," !== H && + "{" !== H && + "ELSE" !== + H && + "=" !== H + ) + for ( + ; + T() || + (C() && + ":" !== + H); + + ) + T() + ? g() + : y(); + return ( + N() && + n.pop(), + n.push([ + Q, + o, + ]), + w(1) + ); + } + if ( + 0 <= + t.call(f, Q) + ) + return ( + n.push([ + Q, + o, + ]), + w(1) + ); + if ( + 0 <= + t.call(a, Q) + ) { + for (; x(); ) + T() + ? g() + : C() + ? y() + : n.pop(); + r = n.pop(); + } + if ( + ((S = + function () { + var n, + r, + i, + s; + return ( + ((i = + d.findTagsBackwards( + o, + [ + "FOR", + ], + ) && + d.findTagsBackwards( + o, + [ + "FORIN", + "FOROF", + "FORFROM", + ], + )), + (n = + i || + d.findTagsBackwards( + o, + [ + "WHILE", + "UNTIL", + "LOOP", + "LEADING_WHEN", + ], + )), + !!n) && + ((r = + !1), + (s = + e[2] + .first_line), + d.detectEnd( + o, + function ( + e, + ) { + var n; + return ( + (n = + e[0]), + 0 <= + t.call( + v, + n, + ) + ); + }, + function ( + e, + t, + ) { + var n = + u[ + t - + 1 + ] || + [], + i = + _slicedToArray( + n, + 3, + ), + o; + return ( + (H = + i[0]), + (o = + i[2] + .first_line), + (r = + s === + o && + ("->" === + H || + "=>" === + H)) + ); + }, + { + returnOnNegativeLevel: + !0, + }, + ), + r) + ); + }), + ((0 <= + t.call( + h, + Q, + ) && + e.spaced) || + ("?" === + Q && + 0 < o && + !u[ + o - + 1 + ] + .spaced)) && + (0 <= + t.call( + l, + _, + ) || + ("..." === + _ && + ((j = + this.tag( + o + + 2, + )), + 0 <= + t.call( + l, + j, + )) && + !this.findTagsBackwards( + o, + [ + "INDEX_START", + "[", + ], + )) || + (0 <= + t.call( + p, + _, + ) && + !D.spaced && + !D.newLine)) && + !S()) + ) + return ( + "?" === Q && + (Q = + e[0] = + "FUNC_EXIST"), + $(o + 1), + w(2) + ); + if ( + 0 <= + t.call( + h, + Q, + ) && + -1 < + this.indexOfTag( + o + 1, + "INDENT", + ) && + this.looksObjectish( + o + 2, + ) && + !this.findTagsBackwards( + o, + [ + "CLASS", + "EXTENDS", + "IF", + "CATCH", + "SWITCH", + "LEADING_WHEN", + "FOR", + "WHILE", + "UNTIL", + ], + ) + ) + return ( + $(o + 1), + n.push([ + "INDENT", + o + 2, + ]), + w(3) + ); + if (":" === Q) { + if ( + ((q = + function () { + var e; + switch ( + !1 + ) { + case ((e = + this.tag( + o - + 1, + )), + 0 > + t.call( + a, + e, + )): + return r[1]; + case "@" !== + this.tag( + o - + 2, + ): + return ( + o - + 2 + ); + default: + return ( + o - + 1 + ); + } + }.call( + this, + )), + (K = + 0 >= + q || + ((F = + this.tag( + q - + 1, + )), + 0 <= + t.call( + v, + F, + )) || + u[q - 1] + .newLine), + X()) + ) { + var tt = + X(), + nt = + _slicedToArray( + tt, + 2, + ); + if ( + ((W = + nt[0]), + (U = + nt[1]), + ("{" === + W || + ("INDENT" === + W && + "{" === + this.tag( + U - + 1, + ))) && + (K || + "," === + this.tag( + q - + 1, + ) || + "{" === + this.tag( + q - + 1, + ))) + ) + return w( + 1, + ); + } + return ( + J(q, !!K), + w(2) + ); + } + if ( + 0 <= + t.call(v, Q) + ) + for ( + O = + n.length - + 1; + 0 <= O && + ((z = n[O]), + !!k(z)); + O += -1 + ) + A(z) && + (z[2].sameLine = + !1); + if ( + ((M = + "OUTDENT" === + H || + B.newLine), + 0 <= + t.call( + c, + Q, + ) || + (0 <= + t.call( + i, + Q, + ) && + M) || + ((".." === + Q || + "..." === + Q) && + this.findTagsBackwards( + o, + [ + "INDEX_START", + ], + ))) + ) + for (; x(); ) { + var rt = + X(), + it = + _slicedToArray( + rt, + 3, + ); + (W = it[0]), + (U = + it[1]); + var st = + it[2]; + if ( + ((R = + st.sameLine), + (K = + st.startsLine), + (T() && + "," !== + H) || + ("," === + H && + "TERMINATOR" === + Q && + null == + _)) + ) + g(); + else if ( + C() && + R && + "TERMINATOR" !== + Q && + ":" !== + H && + (("POST_IF" !== + Q && + "FOR" !== + Q && + "WHILE" !== + Q && + "UNTIL" !== + Q) || + !K || + !E( + o + + 1, + )) + ) + y(); + else { + if ( + !C() || + "TERMINATOR" !== + Q || + "," === + H || + (!!K && + !!this.looksObjectish( + o + + 1, + )) + ) + break; + y(); + } + } + if ( + "," === Q && + !this.looksObjectish( + o + 1, + ) && + C() && + "FOROF" !== + (I = + this.tag( + o + + 2, + )) && + "FORIN" !== I && + ("TERMINATOR" !== + _ || + !this.looksObjectish( + o + 2, + )) + ) + for ( + P = + "OUTDENT" === + _ + ? 1 + : 0; + C(); + + ) + y(o + P); + return w(1); + }, + ) + ); + }, + }, + { + key: "enforceValidCSXAttributes", + value: function () { + return this.scanTokens( + function (e, t, n) { + var r, i; + return ( + e.csxColon && + ((r = n[t + 1]), + "STRING_START" !== + (i = + r[0]) && + "STRING" !== + i && + "(" !== i && + N( + "expected wrapped or quoted JSX attribute", + r[2], + )), + 1 + ); + }, + ); + }, + }, + { + key: "rescueStowawayComments", + value: function () { + var n, r, i; + return ( + (n = function (e, t, n, r) { + return ( + "TERMINATOR" !== + n[t][0] && + n[r]( + b( + "TERMINATOR", + "\n", + n[t], + ), + ), + n[r]( + b( + "JS", + "", + n[t], + e, + ), + ) + ); + }), + (i = function (e, r, i) { + var s, u, a, f, l, c, h; + for ( + u = r; + u !== i.length && + ((l = i[u][0]), + 0 <= t.call(o, l)); + + ) + u++; + if ( + u === i.length || + ((c = i[u][0]), + 0 <= t.call(o, c)) + ) + return ( + (u = + i.length - + 1), + n( + e, + u, + i, + "push", + ), + 1 + ); + for ( + h = e.comments, + a = 0, + f = h.length; + a < f; + a++ + ) + (s = h[a]), + (s.unshift = + !0); + return x(e, i[u]), 1; + }), + (r = function (e, r, i) { + var s, u, a; + for ( + s = r; + -1 !== s && + ((u = i[s][0]), + 0 <= t.call(o, u)); + + ) + s--; + return -1 === s || + ((a = i[s][0]), + 0 <= t.call(o, a)) + ? (n( + e, + 0, + i, + "unshift", + ), + 3) + : (x(e, i[s]), 1); + }), + this.scanTokens( + function (e, n, s) { + var u, a, f, l, c; + if (!e.comments) + return 1; + if ( + ((c = 1), + (f = e[0]), + 0 <= + t.call( + o, + f, + )) + ) { + for ( + u = { + comments: + [], + }, + a = + e + .comments + .length - + 1; + -1 !== a; + + ) + !1 === + e + .comments[ + a + ] + .newLine && + !1 === + e + .comments[ + a + ] + .here && + (u.comments.unshift( + e + .comments[ + a + ], + ), + e.comments.splice( + a, + 1, + )), + a--; + 0 !== + u.comments + .length && + (c = r( + u, + n - 1, + s, + )), + 0 !== + e + .comments + .length && + i( + e, + n, + s, + ); + } else { + for ( + u = { + comments: + [], + }, + a = + e + .comments + .length - + 1; + -1 !== a; + + ) + !e.comments[ + a + ].newLine || + e + .comments[ + a + ] + .unshift || + ("JS" === + e[0] && + e.generated) || + (u.comments.unshift( + e + .comments[ + a + ], + ), + e.comments.splice( + a, + 1, + )), + a--; + 0 !== + u.comments + .length && + (c = i( + u, + n + 1, + s, + )); + } + return ( + 0 === + (null == + (l = + e.comments) + ? void 0 + : l.length) && + delete e.comments, + c + ); + }, + ) + ); + }, + }, + { + key: "addLocationDataToGeneratedTokens", + value: function () { + return this.scanTokens( + function (e, t, n) { + var r, i, s, o, u, a; + if (e[2]) return 1; + if ( + !e.generated && + !e.explicit + ) + return 1; + if ( + "{" === e[0] && + (s = + null == + (u = n[t + 1]) + ? void 0 + : u[2]) + ) { + var f = s; + (i = f.first_line), + (r = + f.first_column); + } else if ( + (o = + null == + (a = n[t - 1]) + ? void 0 + : a[2]) + ) { + var l = o; + (i = l.last_line), + (r = + l.last_column); + } else i = r = 0; + return ( + (e[2] = { + first_line: i, + first_column: r, + last_line: i, + last_column: r, + }), + 1 + ); + }, + ); + }, + }, + { + key: "fixOutdentLocationData", + value: function () { + return this.scanTokens( + function (e, t, n) { + var r; + return "OUTDENT" === + e[0] || + (e.generated && + "CALL_END" === + e[0]) || + (e.generated && + "}" === e[0]) + ? ((r = + n[t - 1][2]), + (e[2] = { + first_line: + r.last_line, + first_column: + r.last_column, + last_line: + r.last_line, + last_column: + r.last_column, + }), + 1) + : 1; + }, + ); + }, + }, + { + key: "addParensToChainedDoIife", + value: function () { + var n, r, s; + return ( + (r = function (e, t) { + return ( + "OUTDENT" === + this.tag(t - 1) + ); + }), + (n = function (e, n) { + var r; + if ( + ((r = e[0]), + !(0 > t.call(i, r))) + ) + return ( + this.tokens.splice( + s, + 0, + b( + "(", + "(", + this + .tokens[ + s + ], + ), + ), + this.tokens.splice( + n + 1, + 0, + b( + ")", + ")", + this + .tokens[ + n + ], + ), + ) + ); + }), + (s = null), + this.scanTokens( + function (e, t) { + var i, o; + return "do" === e[1] + ? ((s = t), + (i = t + 1), + "PARAM_START" === + this.tag( + t + 1, + ) && + ((i = + null), + this.detectEnd( + t + 1, + function ( + e, + t, + ) { + return ( + "PARAM_END" === + this.tag( + t - + 1, + ) + ); + }, + function ( + e, + t, + ) { + return (i = + t); + }, + )), + null == i || + ("->" !== + (o = + this.tag( + i, + )) && + "=>" !== + o) || + "INDENT" !== + this.tag( + i + + 1, + )) + ? 1 + : (this.detectEnd( + i + 1, + r, + n, + ), + 2) + : 1; + }, + ) + ); + }, + }, + { + key: "normalizeLines", + value: function () { + var n = this, + r, + s, + o, + a, + f, + l, + c, + h, + p; + return ( + (p = f = h = null), + (c = null), + (l = null), + (a = []), + (o = function (e, n) { + var r, s, o, a; + return ( + (";" !== e[1] && + ((r = e[0]), + 0 <= + t.call( + g, + r, + )) && + !( + "TERMINATOR" === + e[0] && + ((s = + this.tag( + n + + 1, + )), + 0 <= + t.call( + u, + s, + )) + ) && + ("ELSE" !== + e[0] || + ("THEN" === + p && + !l && + !c)) && + (("CATCH" !== + (o = + e[0]) && + "FINALLY" !== + o) || + ("->" !== + p && + "=>" !== + p))) || + (((a = e[0]), + 0 <= + t.call(i, a)) && + (this.tokens[ + n - 1 + ].newLine || + "OUTDENT" === + this + .tokens[ + n - + 1 + ][0])) + ); + }), + (r = function (e, t) { + return ( + "ELSE" === e[0] && + "THEN" === p && + a.pop(), + this.tokens.splice( + "," === + this.tag( + t - 1, + ) + ? t - 1 + : t, + 0, + h, + ) + ); + }), + (s = function (e, t) { + var r, i, s; + if ( + ((s = a.length), + 0 < s) + ) { + r = a.pop(); + var o = + n.indentation( + e[r], + ), + u = + _slicedToArray( + o, + 2, + ); + return ( + (i = u[1]), + (i[1] = 2 * s), + e.splice( + t, + 0, + i, + ), + (i[1] = 2), + e.splice( + t + 1, + 0, + i, + ), + n.detectEnd( + t + 2, + function ( + e, + ) { + var t; + return ( + "OUTDENT" === + (t = + e[0]) || + "TERMINATOR" === + t + ); + }, + function ( + t, + n, + ) { + if ( + "OUTDENT" === + this.tag( + n, + ) && + "OUTDENT" === + this.tag( + n + + 1, + ) + ) + return e.splice( + n, + 2, + ); + }, + ), + t + 2 + ); + } + return t; + }), + this.scanTokens( + function (e, n, i) { + var d = + _slicedToArray( + e, + 1, + ), + v, + m, + g, + b, + w, + E; + if ( + ((E = d[0]), + (v = + ("->" === + E || + "=>" === + E) && + this.findTagsBackwards( + n, + [ + "IF", + "WHILE", + "FOR", + "UNTIL", + "SWITCH", + "WHEN", + "LEADING_WHEN", + "[", + "INDEX_START", + ], + ) && + !this.findTagsBackwards( + n, + [ + "THEN", + "..", + "...", + ], + )), + "TERMINATOR" === + E) + ) { + if ( + "ELSE" === + this.tag( + n + + 1, + ) && + "OUTDENT" !== + this.tag( + n - + 1, + ) + ) + return ( + i.splice.apply( + i, + [ + n, + 1, + ].concat( + _toConsumableArray( + this.indentation(), + ), + ), + ), + 1 + ); + if ( + ((b = + this.tag( + n + + 1, + )), + 0 <= + t.call( + u, + b, + )) + ) + return ( + i.splice( + n, + 1, + ), + 0 + ); + } + if ("CATCH" === E) + for ( + m = g = 1; + 2 >= g; + m = ++g + ) + if ( + "OUTDENT" === + (w = + this.tag( + n + + m, + )) || + "TERMINATOR" === + w || + "FINALLY" === + w + ) + return ( + i.splice.apply( + i, + [ + n + + m, + 0, + ].concat( + _toConsumableArray( + this.indentation(), + ), + ), + ), + 2 + + m + ); + if ( + ("->" !== E && + "=>" !== + E) || + !( + "," === + this.tag( + n + + 1, + ) || + ("." === + this.tag( + n + + 1, + ) && + e.newLine) + ) + ) { + if ( + 0 <= + t.call( + y, + E, + ) && + "INDENT" !== + this.tag( + n + + 1, + ) && + ("ELSE" !== + E || + "IF" !== + this.tag( + n + + 1, + )) && + !v + ) { + p = E; + var T = + this.indentation( + i[ + n + ], + ), + N = + _slicedToArray( + T, + 2, + ); + return ( + (f = + N[0]), + (h = + N[1]), + "THEN" === + p && + (f.fromThen = + !0), + "THEN" === + E && + ((c = + this.findTagsBackwards( + n, + [ + "LEADING_WHEN", + ], + ) && + "IF" === + this.tag( + n + + 1, + )), + (l = + this.findTagsBackwards( + n, + [ + "IF", + ], + ) && + "IF" === + this.tag( + n + + 1, + ))), + "THEN" === + E && + this.findTagsBackwards( + n, + [ + "IF", + ], + ) && + a.push( + n, + ), + "ELSE" === + E && + "OUTDENT" !== + this.tag( + n - + 1, + ) && + (n = + s( + i, + n, + )), + i.splice( + n + + 1, + 0, + f, + ), + this.detectEnd( + n + + 2, + o, + r, + ), + "THEN" === + E && + i.splice( + n, + 1, + ), + 1 + ); + } + return 1; + } + var S = + this.indentation( + i[n], + ), + x = + _slicedToArray( + S, + 2, + ); + return ( + (f = x[0]), + (h = x[1]), + i.splice( + n + 1, + 0, + f, + h, + ), + 1 + ); + }, + ) + ); + }, + }, + { + key: "tagPostfixConditionals", + value: function () { + var n, r, i; + return ( + (i = null), + (r = function (e, n) { + var r = _slicedToArray( + e, + 1, + ), + i, + s; + s = r[0]; + var o = _slicedToArray( + this.tokens[n - 1], + 1, + ); + return ( + (i = o[0]), + "TERMINATOR" === + s || + ("INDENT" === + s && + 0 > + t.call( + y, + i, + )) + ); + }), + (n = function (e) { + if ( + "INDENT" !== e[0] || + (e.generated && + !e.fromThen) + ) + return (i[0] = + "POST_" + i[0]); + }), + this.scanTokens( + function (e, t) { + return "IF" === e[0] + ? ((i = e), + this.detectEnd( + t + 1, + r, + n, + ), + 1) + : 1; + }, + ) + ); + }, + }, + { + key: "indentation", + value: function (t) { + var n, r; + return ( + (n = ["INDENT", 2]), + (r = ["OUTDENT", 2]), + t + ? ((n.generated = + r.generated = + !0), + (n.origin = r.origin = + t)) + : (n.explicit = + r.explicit = + !0), + [n, r] + ); + }, + }, + { + key: "tag", + value: function (t) { + var n; + return null == + (n = this.tokens[t]) + ? void 0 + : n[0]; + }, + }, + ]), + e + ); + })(); + return (e.prototype.generate = b), e; + }.call(this), + r = [ + ["(", ")"], + ["[", "]"], + ["{", "}"], + ["INDENT", "OUTDENT"], + ["CALL_START", "CALL_END"], + ["PARAM_START", "PARAM_END"], + ["INDEX_START", "INDEX_END"], + ["STRING_START", "STRING_END"], + ["REGEX_START", "REGEX_END"], + ], + e.INVERSES = d = {}, + f = [], + a = [], + w = 0, + S = r.length; + w < S; + w++ + ) { + var C = _slicedToArray(r[w], 2); + (E = C[0]), (T = C[1]), f.push((d[T] = E)), a.push((d[E] = T)); + } + (u = ["CATCH", "THEN", "ELSE", "FINALLY"].concat(a)), + (h = [ + "IDENTIFIER", + "PROPERTY", + "SUPER", + ")", + "CALL_END", + "]", + "INDEX_END", + "@", + "THIS", + ]), + (l = [ + "IDENTIFIER", + "CSX_TAG", + "PROPERTY", + "NUMBER", + "INFINITY", + "NAN", + "STRING", + "STRING_START", + "REGEX", + "REGEX_START", + "JS", + "NEW", + "PARAM_START", + "CLASS", + "IF", + "TRY", + "SWITCH", + "THIS", + "UNDEFINED", + "NULL", + "BOOL", + "UNARY", + "YIELD", + "AWAIT", + "UNARY_MATH", + "SUPER", + "THROW", + "@", + "->", + "=>", + "[", + "(", + "{", + "--", + "++", + ]), + (p = ["+", "-"]), + (c = [ + "POST_IF", + "FOR", + "WHILE", + "UNTIL", + "WHEN", + "BY", + "LOOP", + "TERMINATOR", + ]), + (y = ["ELSE", "->", "=>", "TRY", "FINALLY", "THEN"]), + (g = [ + "TERMINATOR", + "CATCH", + "FINALLY", + "ELSE", + "OUTDENT", + "LEADING_WHEN", + ]), + (v = ["TERMINATOR", "INDENT", "OUTDENT"]), + (i = [".", "?.", "::", "?::"]), + (s = ["IF", "TRY", "FINALLY", "CATCH", "CLASS", "SWITCH"]), + (o = [ + "(", + ")", + "[", + "]", + "{", + "}", + ".", + "..", + "...", + ",", + "=", + "++", + "--", + "?", + "AS", + "AWAIT", + "CALL_START", + "CALL_END", + "DEFAULT", + "ELSE", + "EXTENDS", + "EXPORT", + "FORIN", + "FOROF", + "FORFROM", + "IMPORT", + "INDENT", + "INDEX_SOAK", + "LEADING_WHEN", + "OUTDENT", + "PARAM_END", + "REGEX_START", + "REGEX_END", + "RETURN", + "STRING_END", + "THROW", + "UNARY", + "YIELD", + ].concat(p.concat(c.concat(i.concat(s))))); + }.call(this), + { exports: e }.exports + ); + })()), + (require["./lexer"] = (function () { + var e = {}; + return ( + function () { + var t = [].indexOf, + n = [].slice, + r = require("./rewriter"), + i, + s, + o, + u, + a, + f, + l, + c, + h, + p, + d, + v, + m, + g, + y, + b, + w, + E, + S, + x, + T, + N, + C, + k, + L, + A, + O, + M, + _, + D, + P, + H, + B, + j, + F, + I, + q, + R, + U, + z, + W, + X, + V, + $, + J, + K, + Q, + G, + Y, + Z, + et, + tt, + nt, + rt, + it, + st, + ot, + ut, + at, + ft, + lt, + ct, + ht, + pt, + dt, + vt, + mt, + gt, + yt, + bt, + wt, + Et, + St, + xt; + (K = r.Rewriter), (O = r.INVERSES); + var Tt = require("./helpers"); + (dt = Tt.count), + (St = Tt.starts), + (pt = Tt.compact), + (Et = Tt.repeat), + (vt = Tt.invertLiterate), + (wt = Tt.merge), + (ht = Tt.attachCommentsToNode), + (bt = Tt.locationDataToString), + (xt = Tt.throwSyntaxError), + (e.Lexer = B = + (function () { + function e() { + _classCallCheck(this, e); + } + return ( + _createClass(e, [ + { + key: "tokenize", + value: function (t) { + var n = + 1 < arguments.length && + void 0 !== arguments[1] + ? arguments[1] + : {}, + r, + i, + s, + o; + for ( + this.literate = n.literate, + this.indent = 0, + this.baseIndent = 0, + this.indebt = 0, + this.outdebt = 0, + this.indents = [], + this.indentLiteral = "", + this.ends = [], + this.tokens = [], + this.seenFor = !1, + this.seenImport = !1, + this.seenExport = !1, + this.importSpecifierList = !1, + this.exportSpecifierList = !1, + this.csxDepth = 0, + this.csxObjAttribute = {}, + this.chunkLine = n.line || 0, + this.chunkColumn = + n.column || 0, + t = this.clean(t), + s = 0; + (this.chunk = t.slice(s)); + + ) { + r = + this.identifierToken() || + this.commentToken() || + this.whitespaceToken() || + this.lineToken() || + this.stringToken() || + this.numberToken() || + this.csxToken() || + this.regexToken() || + this.jsToken() || + this.literalToken(); + var u = + this.getLineAndColumnFromChunk( + r, + ), + a = _slicedToArray(u, 2); + if ( + ((this.chunkLine = a[0]), + (this.chunkColumn = a[1]), + (s += r), + n.untilBalanced && + 0 === this.ends.length) + ) + return { + tokens: this.tokens, + index: s, + }; + } + return ( + this.closeIndentation(), + (i = this.ends.pop()) && + this.error( + "missing " + i.tag, + (null == (o = i.origin) + ? i + : o)[2], + ), + !1 === n.rewrite + ? this.tokens + : new K().rewrite(this.tokens) + ); + }, + }, + { + key: "clean", + value: function (t) { + return ( + t.charCodeAt(0) === i && + (t = t.slice(1)), + (t = t + .replace(/\r/g, "") + .replace(st, "")), + ct.test(t) && + ((t = "\n" + t), + this.chunkLine--), + this.literate && (t = vt(t)), + t + ); + }, + }, + { + key: "identifierToken", + value: function () { + var n, + r, + i, + s, + u, + c, + h, + p, + d, + m, + g, + y, + b, + w, + E, + S, + x, + T, + N, + k, + L, + A, + O, + M, + D, + H, + B, + j; + if ( + ((h = this.atCSXTag()), + (D = h ? v : C), + !(d = D.exec(this.chunk))) + ) + return 0; + var F = d, + I = _slicedToArray(F, 3); + if ( + ((p = I[0]), + (u = I[1]), + (r = I[2]), + (c = u.length), + (m = void 0), + "own" === u && "FOR" === this.tag()) + ) + return ( + this.token("OWN", u), u.length + ); + if ( + "from" === u && + "YIELD" === this.tag() + ) + return ( + this.token("FROM", u), u.length + ); + if ("as" === u && this.seenImport) { + if ("*" === this.value()) + this.tokens[ + this.tokens.length - 1 + ][0] = "IMPORT_ALL"; + else if ( + ((b = this.value(!0)), + 0 <= t.call(l, b)) + ) { + g = this.prev(); + var q = [ + "IDENTIFIER", + this.value(!0), + ]; + (g[0] = q[0]), (g[1] = q[1]); + } + if ( + "DEFAULT" === + (w = this.tag()) || + "IMPORT_ALL" === w || + "IDENTIFIER" === w + ) + return ( + this.token("AS", u), + u.length + ); + } + if ("as" === u && this.seenExport) { + if ( + "IDENTIFIER" === + (S = this.tag()) || + "DEFAULT" === S + ) + return ( + this.token("AS", u), + u.length + ); + if ( + ((x = this.value(!0)), + 0 <= t.call(l, x)) + ) { + g = this.prev(); + var R = [ + "IDENTIFIER", + this.value(!0), + ]; + return ( + (g[0] = R[0]), + (g[1] = R[1]), + this.token("AS", u), + u.length + ); + } + } + if ( + "default" !== u || + !this.seenExport || + ("EXPORT" !== (T = this.tag()) && + "AS" !== T) + ) { + if ( + "do" === u && + (M = /^(\s*super)(?!\(\))/.exec( + this.chunk.slice(3), + )) + ) { + this.token("SUPER", "super"), + this.token( + "CALL_START", + "(", + ), + this.token("CALL_END", ")"); + var U = M, + z = _slicedToArray(U, 2); + return ( + (p = z[0]), + (H = z[1]), + H.length + 3 + ); + } + if ( + ((g = this.prev()), + (B = + r || + (null != g && + ("." === (N = g[0]) || + "?." === N || + "::" === N || + "?::" === N || + (!g.spaced && + "@" === g[0]))) + ? "PROPERTY" + : "IDENTIFIER"), + "IDENTIFIER" === B && + (0 <= t.call(_, u) || + 0 <= t.call(l, u)) && + !( + this.exportSpecifierList && + 0 <= t.call(l, u) + ) + ? ((B = u.toUpperCase()), + "WHEN" === B && + ((k = this.tag()), + 0 <= t.call(P, k)) + ? (B = "LEADING_WHEN") + : "FOR" === B + ? (this.seenFor = + !0) + : "UNLESS" === B + ? (B = "IF") + : "IMPORT" === B + ? (this.seenImport = + !0) + : "EXPORT" === B + ? (this.seenExport = + !0) + : 0 <= + t.call( + ot, + B, + ) + ? (B = + "UNARY") + : 0 <= + t.call( + $, + B, + ) && + ("INSTANCEOF" !== + B && + this + .seenFor + ? ((B = + "FOR" + + B), + (this.seenFor = + !1)) + : ((B = + "RELATION"), + "!" === + this.value() && + ((m = + this.tokens.pop()), + (u = + "!" + + u))))) + : "IDENTIFIER" === B && + this.seenFor && + "from" === u && + mt(g) + ? ((B = "FORFROM"), + (this.seenFor = !1)) + : "PROPERTY" === B && + g && + (g.spaced && + ((L = g[0]), + 0 <= t.call(o, L)) && + /^[gs]et$/.test(g[1]) && + 1 < + this.tokens + .length && + "." !== + (A = + this.tokens[ + this.tokens + .length - + 2 + ][0]) && + "?." !== A && + "@" !== A + ? this.error( + "'" + + g[1] + + "' cannot be used as a keyword, or as a function call without parentheses", + g[2], + ) + : 2 < + this.tokens + .length && + ((y = + this.tokens[ + this + .tokens + .length - + 2 + ]), + ("@" === + (O = g[0]) || + "THIS" === + O) && + y && + y.spaced && + /^[gs]et$/.test( + y[1], + ) && + "." !== + (E = + this + .tokens[ + this + .tokens + .length - + 3 + ][0]) && + "?." !== E && + "@" !== E && + this.error( + "'" + + y[1] + + "' cannot be used as a keyword, or as a function call without parentheses", + y[2], + ))), + "IDENTIFIER" === B && + 0 <= t.call(J, u) && + this.error( + "reserved word '" + + u + + "'", + { length: u.length }, + ), + "PROPERTY" === B || + this.exportSpecifierList || + (0 <= t.call(a, u) && + ((n = u), (u = f[u])), + (B = (function () { + return "!" === u + ? "UNARY" + : "==" === u || + "!=" === u + ? "COMPARE" + : "true" === u || + "false" === u + ? "BOOL" + : "break" === + u || + "continue" === + u || + "debugger" === + u + ? "STATEMENT" + : "&&" === + u || + "||" === u + ? u + : B; + })())), + (j = this.token(B, u, 0, c)), + n && (j.origin = [B, n, j[2]]), + m) + ) { + var W = [ + m[2].first_line, + m[2].first_column, + ]; + (j[2].first_line = W[0]), + (j[2].first_column = W[1]); + } + return ( + r && + ((i = p.lastIndexOf( + h ? "=" : ":", + )), + (s = this.token( + ":", + ":", + i, + r.length, + )), + h && (s.csxColon = !0)), + h && + "IDENTIFIER" === B && + ":" !== g[0] && + this.token( + ",", + ",", + 0, + 0, + j, + ), + p.length + ); + } + return ( + this.token("DEFAULT", u), u.length + ); + }, + }, + { + key: "numberToken", + value: function () { + var t, n, r, i, s, o; + if (!(r = q.exec(this.chunk))) return 0; + switch ( + ((i = r[0]), (n = i.length), !1) + ) { + case !/^0[BOX]/.test(i): + this.error( + "radix prefix in '" + + i + + "' must be lowercase", + { offset: 1 }, + ); + break; + case !/^(?!0x).*E/.test(i): + this.error( + "exponential notation in '" + + i + + "' must be indicated with a lowercase 'e'", + { offset: i.indexOf("E") }, + ); + break; + case !/^0\d*[89]/.test(i): + this.error( + "decimal literal '" + + i + + "' must not be prefixed with '0'", + { length: n }, + ); + break; + case !/^0\d+/.test(i): + this.error( + "octal literal '" + + i + + "' must be prefixed with '0o'", + { length: n }, + ); + } + return ( + (t = (function () { + switch (i.charAt(1)) { + case "b": + return 2; + case "o": + return 8; + case "x": + return 16; + default: + return null; + } + })()), + (s = + null == t + ? parseFloat(i) + : parseInt(i.slice(2), t)), + (o = + Infinity === s + ? "INFINITY" + : "NUMBER"), + this.token(o, i, 0, n), + n + ); + }, + }, + { + key: "stringToken", + value: function () { + var t = this, + n = rt.exec(this.chunk) || [], + r = _slicedToArray(n, 1), + i, + s, + o, + u, + a, + f, + l, + c, + h, + p, + d, + v, + m, + g, + y, + b; + if (((v = r[0]), !v)) return 0; + (d = this.prev()), + d && + "from" === this.value() && + (this.seenImport || + this.seenExport) && + (d[0] = "FROM"), + (g = (function () { + return "'" === v + ? nt + : '"' === v + ? Z + : "'''" === v + ? S + : '"""' === v + ? w + : void 0; + })()), + (f = 3 === v.length); + var x = this.matchWithInterpolations( + g, + v, + ); + if ( + ((b = x.tokens), + (a = x.index), + (i = b.length - 1), + (o = v.charAt(0)), + f) + ) { + for ( + c = null, + u = (function () { + var e, t, n; + for ( + n = [], + l = e = 0, + t = b.length; + e < t; + l = ++e + ) + (y = b[l]), + "NEOSTRING" === + y[0] && + n.push( + y[1], + ); + return n; + })().join("#{}"); + (p = E.exec(u)); + + ) + (s = p[1]), + (null === c || + (0 < (m = s.length) && + m < c.length)) && + (c = s); + c && (h = RegExp("\\n" + c, "g")), + this.mergeInterpolationTokens( + b, + { delimiter: o }, + function (e, n) { + return ( + (e = t.formatString( + e, + { + delimiter: + v, + }, + )), + h && + (e = e.replace( + h, + "\n", + )), + 0 === n && + (e = e.replace( + D, + "", + )), + n === i && + (e = e.replace( + it, + "", + )), + e + ); + }, + ); + } else + this.mergeInterpolationTokens( + b, + { delimiter: o }, + function (e, n) { + return ( + (e = t.formatString(e, { + delimiter: v, + })), + (e = e.replace( + G, + function (t, r) { + return (0 === + n && + 0 === r) || + (n === i && + r + + t.length === + e.length) + ? "" + : " "; + }, + )), + e + ); + }, + ); + return ( + this.atCSXTag() && + this.token( + ",", + ",", + 0, + 0, + this.prev, + ), + a + ); + }, + }, + { + key: "commentToken", + value: function () { + var n = + 0 < arguments.length && + void 0 !== arguments[0] + ? arguments[0] + : this.chunk, + r, + i, + s, + o, + u, + a, + f, + l, + h, + p, + d; + if (!(f = n.match(c))) return 0; + var v = f, + m = _slicedToArray(v, 2); + return ( + (r = m[0]), + (u = m[1]), + (o = null), + (h = /^\s*\n+\s*#/.test(r)), + u + ? ((l = b.exec(r)), + l && + this.error( + "block comments cannot contain " + + l[0], + { + offset: l.index, + length: l[0] + .length, + }, + ), + (n = n.replace( + "###" + u + "###", + "", + )), + (n = n.replace(/^\n+/, "")), + this.lineToken(n), + (s = u), + 0 <= t.call(s, "\n") && + (s = s.replace( + RegExp( + "\\n" + + Et( + " ", + this + .indent, + ), + "g", + ), + "\n", + )), + (o = [s])) + : ((s = r.replace( + /^(\n*)/, + "", + )), + (s = s.replace( + /^([ |\t]*)#/gm, + "", + )), + (o = s.split("\n"))), + (i = (function () { + var e, t, n; + for ( + n = [], + a = e = 0, + t = o.length; + e < t; + a = ++e + ) + (s = o[a]), + n.push({ + content: s, + here: null != u, + newLine: + h || 0 !== a, + }); + return n; + })()), + (d = this.prev()), + d + ? ht(i, d) + : ((i[0].newLine = !0), + this.lineToken( + this.chunk.slice( + r.length, + ), + ), + (p = this.makeToken( + "JS", + "", + )), + (p.generated = !0), + (p.comments = i), + this.tokens.push(p), + this.newlineToken(0)), + r.length + ); + }, + }, + { + key: "jsToken", + value: function () { + var t, n; + return "`" === this.chunk.charAt(0) && + (t = + N.exec(this.chunk) || + M.exec(this.chunk)) + ? ((n = t[1].replace( + /\\+(`|$)/g, + function (e) { + return e.slice( + -Math.ceil( + e.length / 2, + ), + ); + }, + )), + this.token( + "JS", + n, + 0, + t[0].length, + ), + t[0].length) + : 0; + }, + }, + { + key: "regexToken", + value: function () { + var n = this, + r, + i, + s, + u, + a, + f, + l, + c, + h, + p, + d, + v, + m, + g, + y, + b; + switch (!1) { + case !(p = X.exec(this.chunk)): + this.error( + "regular expressions cannot begin with " + + p[2], + { + offset: + p.index + + p[1].length, + }, + ); + break; + case !(p = + this.matchWithInterpolations( + x, + "///", + )): + var w = p; + if ( + ((b = w.tokens), + (l = w.index), + (u = this.chunk + .slice(0, l) + .match( + /\s+(#(?!{).*)/g, + )), + u) + ) + for ( + c = 0, h = u.length; + c < h; + c++ + ) + (s = u[c]), + this.commentToken( + s, + ); + break; + case !(p = z.exec(this.chunk)): + var E = p, + S = _slicedToArray(E, 3); + if ( + ((y = S[0]), + (r = S[1]), + (i = S[2]), + this.validateEscapes(r, { + isRegex: !0, + offsetInChunk: 1, + }), + (l = y.length), + (v = this.prev()), + v) + ) + if ( + v.spaced && + ((m = v[0]), + 0 <= t.call(o, m)) + ) { + if (!i || U.test(y)) + return 0; + } else if ( + ((g = v[0]), + 0 <= t.call(I, g)) + ) + return 0; + i || + this.error( + "missing / (unclosed regex)", + ); + break; + default: + return 0; + } + var T = W.exec(this.chunk.slice(l)), + N = _slicedToArray(T, 1); + switch ( + ((f = N[0]), + (a = l + f.length), + (d = this.makeToken( + "REGEX", + null, + 0, + a, + )), + !1) + ) { + case !!lt.test(f): + this.error( + "invalid regular expression flags " + + f, + { + offset: l, + length: f.length, + }, + ); + break; + case !y && 1 !== b.length: + (r = r + ? this.formatRegex(r, { + flags: f, + delimiter: "/", + }) + : this.formatHeregex( + b[0][1], + { flags: f }, + )), + this.token( + "REGEX", + "" + + this.makeDelimitedLiteral( + r, + { + delimiter: + "/", + }, + ) + + f, + 0, + a, + d, + ); + break; + default: + this.token( + "REGEX_START", + "(", + 0, + 0, + d, + ), + this.token( + "IDENTIFIER", + "RegExp", + 0, + 0, + ), + this.token( + "CALL_START", + "(", + 0, + 0, + ), + this.mergeInterpolationTokens( + b, + { + delimiter: '"', + double: !0, + }, + function (e) { + return n.formatHeregex( + e, + { flags: f }, + ); + }, + ), + f && + (this.token( + ",", + ",", + l - 1, + 0, + ), + this.token( + "STRING", + '"' + f + '"', + l - 1, + f.length, + )), + this.token( + ")", + ")", + a - 1, + 0, + ), + this.token( + "REGEX_END", + ")", + a - 1, + 0, + ); + } + return a; + }, + }, + { + key: "lineToken", + value: function () { + var t = + 0 < arguments.length && + void 0 !== arguments[0] + ? arguments[0] + : this.chunk, + n, + r, + i, + s, + o, + u, + a, + f, + l; + if (!(s = F.exec(t))) return 0; + if ( + ((i = s[0]), + (f = this.prev()), + (n = null != f && "\\" === f[0]), + (n && this.seenFor) || + (this.seenFor = !1), + this.importSpecifierList || + (this.seenImport = !1), + this.exportSpecifierList || + (this.seenExport = !1), + (l = + i.length - + 1 - + i.lastIndexOf("\n")), + (a = this.unfinished()), + (u = 0 < l ? i.slice(-l) : ""), + !/^(.?)\1*$/.exec(u)) + ) + return ( + this.error( + "mixed indentation", + { offset: i.length }, + ), + i.length + ); + if ( + ((o = Math.min( + u.length, + this.indentLiteral.length, + )), + u.slice(0, o) !== + this.indentLiteral.slice(0, o)) + ) + return ( + this.error( + "indentation mismatch", + { offset: i.length }, + ), + i.length + ); + if (l - this.indebt === this.indent) + return ( + a + ? this.suppressNewlines() + : this.newlineToken(0), + i.length + ); + if (l > this.indent) { + if (a) + return ( + (this.indebt = + l - this.indent), + this.suppressNewlines(), + i.length + ); + if (!this.tokens.length) + return ( + (this.baseIndent = + this.indent = + l), + (this.indentLiteral = u), + i.length + ); + (r = + l - this.indent + this.outdebt), + this.token( + "INDENT", + r, + i.length - l, + l, + ), + this.indents.push(r), + this.ends.push({ + tag: "OUTDENT", + }), + (this.outdebt = this.indebt = + 0), + (this.indent = l), + (this.indentLiteral = u); + } else + l < this.baseIndent + ? this.error( + "missing indentation", + { offset: i.length }, + ) + : ((this.indebt = 0), + this.outdentToken( + this.indent - l, + a, + i.length, + )); + return i.length; + }, + }, + { + key: "outdentToken", + value: function (n, r, i) { + var s, o, u, a; + for (s = this.indent - n; 0 < n; ) + (u = + this.indents[ + this.indents.length - 1 + ]), + u + ? this.outdebt && + n <= this.outdebt + ? ((this.outdebt -= n), + (n = 0)) + : ((o = + this.indents.pop() + + this.outdebt), + i && + ((a = + this.chunk[ + i + ]), + 0 <= + t.call( + k, + a, + )) && + ((s -= o - n), + (n = o)), + (this.outdebt = 0), + this.pair("OUTDENT"), + this.token( + "OUTDENT", + n, + 0, + i, + ), + (n -= o)) + : (this.outdebt = n = 0); + return ( + o && (this.outdebt -= n), + this.suppressSemicolons(), + "TERMINATOR" === this.tag() || + r || + this.token( + "TERMINATOR", + "\n", + i, + 0, + ), + (this.indent = s), + (this.indentLiteral = + this.indentLiteral.slice(0, s)), + this + ); + }, + }, + { + key: "whitespaceToken", + value: function () { + var t, n, r; + return (t = ct.exec(this.chunk)) || + (n = "\n" === this.chunk.charAt(0)) + ? ((r = this.prev()), + r && + (r[t ? "spaced" : "newLine"] = + !0), + t ? t[0].length : 0) + : 0; + }, + }, + { + key: "newlineToken", + value: function (t) { + return ( + this.suppressSemicolons(), + "TERMINATOR" !== this.tag() && + this.token( + "TERMINATOR", + "\n", + t, + 0, + ), + this + ); + }, + }, + { + key: "suppressNewlines", + value: function () { + var t; + return ( + (t = this.prev()), + "\\" === t[1] && + (t.comments && + 1 < this.tokens.length && + ht( + t.comments, + this.tokens[ + this.tokens.length - + 2 + ], + ), + this.tokens.pop()), + this + ); + }, + }, + { + key: "csxToken", + value: function () { + var n = this, + r, + i, + s, + o, + u, + a, + f, + l, + c, + p, + d, + v, + b, + w; + if ( + ((u = this.chunk[0]), + (d = + 0 < this.tokens.length + ? this.tokens[ + this.tokens.length - 1 + ][0] + : ""), + "<" === u) + ) { + if ( + ((l = + g.exec( + this.chunk.slice(1), + ) || + m.exec( + this.chunk.slice(1), + )), + !l || + !( + 0 < this.csxDepth || + !(p = this.prev()) || + p.spaced || + ((v = p[0]), + 0 > t.call(h, v)) + )) + ) + return 0; + var E = l, + S = _slicedToArray(E, 3); + return ( + (f = S[0]), + (a = S[1]), + (i = S[2]), + (c = this.token( + "CSX_TAG", + a, + 1, + a.length, + )), + this.token("CALL_START", "("), + this.token("[", "["), + this.ends.push({ + tag: "/>", + origin: c, + name: a, + }), + this.csxDepth++, + a.length + 1 + ); + } + if ((s = this.atCSXTag())) { + if ("/>" === this.chunk.slice(0, 2)) + return ( + this.pair("/>"), + this.token("]", "]", 0, 2), + this.token( + "CALL_END", + ")", + 0, + 2, + ), + this.csxDepth--, + 2 + ); + if ("{" === u) + return ( + ":" === d + ? ((b = this.token( + "(", + "(", + )), + (this.csxObjAttribute[ + this.csxDepth + ] = !1)) + : ((b = this.token( + "{", + "{", + )), + (this.csxObjAttribute[ + this.csxDepth + ] = !0)), + this.ends.push({ + tag: "}", + origin: b, + }), + 1 + ); + if (">" === u) { + this.pair("/>"), + (c = this.token("]", "]")), + this.token(",", ","); + var x = + this.matchWithInterpolations( + A, + ">", + "", + }, + ); + }, + ), + (l = + g.exec( + this.chunk.slice(o), + ) || + m.exec( + this.chunk.slice(o), + )), + (l && l[1] === s.name) || + this.error( + "expected corresponding CSX closing tag for " + + s.name, + s.origin[2], + ), + (r = o + s.name.length), + ">" !== this.chunk[r] && + this.error( + "missing closing > after tag name", + { + offset: r, + length: 1, + }, + ), + this.token( + "CALL_END", + ")", + o, + s.name.length + 1, + ), + this.csxDepth--, + r + 1 + ); + } + return 0; + } + return this.atCSXTag(1) + ? "}" === u + ? (this.pair(u), + this.csxObjAttribute[ + this.csxDepth + ] + ? (this.token("}", "}"), + (this.csxObjAttribute[ + this.csxDepth + ] = !1)) + : this.token(")", ")"), + this.token(",", ","), + 1) + : 0 + : 0; + }, + }, + { + key: "atCSXTag", + value: function () { + var t = + 0 < arguments.length && + void 0 !== arguments[0] + ? arguments[0] + : 0, + n, + r, + i; + if (0 === this.csxDepth) return !1; + for ( + n = this.ends.length - 1; + "OUTDENT" === + (null == (i = this.ends[n]) + ? void 0 + : i.tag) || 0 < t--; + + ) + n--; + return ( + (r = this.ends[n]), + "/>" === + (null == r ? void 0 : r.tag) && + r + ); + }, + }, + { + key: "literalToken", + value: function () { + var n, + r, + i, + s, + a, + f, + l, + c, + h, + v, + m, + g, + y; + if ((n = R.exec(this.chunk))) { + var b = n, + w = _slicedToArray(b, 1); + (y = w[0]), + u.test(y) && + this.tagParameters(); + } else y = this.chunk.charAt(0); + if ( + ((m = y), + (s = this.prev()), + s && + 0 <= + t.call( + ["="].concat( + _toConsumableArray( + d, + ), + ), + y, + ) && + ((v = !1), + "=" !== y || + ("||" !== (a = s[1]) && + "&&" !== a) || + s.spaced || + ((s[0] = "COMPOUND_ASSIGN"), + (s[1] += "="), + (s = + this.tokens[ + this.tokens.length - + 2 + ]), + (v = !0)), + s && + "PROPERTY" !== s[0] && + ((i = + null == (f = s.origin) + ? s + : f), + (r = gt(s[1], i[1])), + r && this.error(r, i[2])), + v)) + ) + return y.length; + if ( + ("{" === y && this.seenImport + ? (this.importSpecifierList = + !0) + : this.importSpecifierList && + "}" === y + ? (this.importSpecifierList = + !1) + : "{" === y && + "EXPORT" === + (null == s + ? void 0 + : s[0]) + ? (this.exportSpecifierList = + !0) + : this + .exportSpecifierList && + "}" === y && + (this.exportSpecifierList = + !1), + ";" === y) + ) + ((l = null == s ? void 0 : s[0]), + 0 <= + t.call( + ["="].concat( + _toConsumableArray(at), + ), + l, + )) && + this.error("unexpected ;"), + (this.seenFor = + this.seenImport = + this.seenExport = + !1), + (m = "TERMINATOR"); + else if ( + "*" === y && + "EXPORT" === + (null == s ? void 0 : s[0]) + ) + m = "EXPORT_ALL"; + else if (0 <= t.call(j, y)) m = "MATH"; + else if (0 <= t.call(p, y)) + m = "COMPARE"; + else if (0 <= t.call(d, y)) + m = "COMPOUND_ASSIGN"; + else if (0 <= t.call(ot, y)) + m = "UNARY"; + else if (0 <= t.call(ut, y)) + m = "UNARY_MATH"; + else if (0 <= t.call(Q, y)) m = "SHIFT"; + else if ( + "?" === y && + (null == s ? void 0 : s.spaced) + ) + m = "BIN?"; + else if (s) + if ( + "(" === y && + !s.spaced && + ((c = s[0]), 0 <= t.call(o, c)) + ) + "?" === s[0] && + (s[0] = "FUNC_EXIST"), + (m = "CALL_START"); + else if ( + "[" === y && + ((((h = s[0]), + 0 <= t.call(L, h)) && + !s.spaced) || + "::" === s[0]) + ) + switch ( + ((m = "INDEX_START"), s[0]) + ) { + case "?": + s[0] = "INDEX_SOAK"; + } + return ( + (g = this.makeToken(m, y)), + "(" === y || "{" === y || "[" === y + ? this.ends.push({ + tag: O[y], + origin: g, + }) + : ")" === y || + "}" === y || + "]" === y + ? this.pair(y) + : void 0, + this.tokens.push( + this.makeToken(m, y), + ), + y.length + ); + }, + }, + { + key: "tagParameters", + value: function () { + var t, n, r, i, s; + if (")" !== this.tag()) return this; + for ( + r = [], + s = this.tokens, + t = s.length, + n = s[--t], + n[0] = "PARAM_END"; + (i = s[--t]); + + ) + switch (i[0]) { + case ")": + r.push(i); + break; + case "(": + case "CALL_START": + if (!r.length) + return "(" === i[0] + ? ((i[0] = + "PARAM_START"), + this) + : ((n[0] = + "CALL_END"), + this); + r.pop(); + } + return this; + }, + }, + { + key: "closeIndentation", + value: function () { + return this.outdentToken(this.indent); + }, + }, + { + key: "matchWithInterpolations", + value: function (r, i, s, o) { + var u, + a, + f, + l, + c, + h, + p, + d, + v, + m, + g, + y, + b, + w, + E, + S, + x, + T, + N, + C, + k, + L; + if ( + (null == s && (s = i), + null == o && (o = /^#\{/), + (L = []), + (S = i.length), + this.chunk.slice(0, S) !== i) + ) + return null; + for (C = this.chunk.slice(S); ; ) { + var A = r.exec(C), + O = _slicedToArray(A, 1); + if ( + ((k = O[0]), + this.validateEscapes(k, { + isRegex: + "/" === i.charAt(0), + offsetInChunk: S, + }), + L.push( + this.makeToken( + "NEOSTRING", + k, + S, + ), + ), + (C = C.slice(k.length)), + (S += k.length), + !(w = o.exec(C))) + ) + break; + var M = w, + _ = _slicedToArray(M, 1); + (g = _[0]), (m = g.length - 1); + var D = + this.getLineAndColumnFromChunk( + S + m, + ), + P = _slicedToArray(D, 2); + (b = P[0]), + (p = P[1]), + (N = C.slice(m)); + var H = new e().tokenize(N, { + line: b, + column: p, + untilBalanced: !0, + }); + if ( + ((E = H.tokens), + (v = H.index), + (v += m), + (c = "}" === C[v - 1]), + c) + ) { + var B, j, F, I; + (B = E), + (j = _slicedToArray(B, 1)), + (x = j[0]), + B, + (F = n.call(E, -1)), + (I = _slicedToArray(F, 1)), + (h = I[0]), + F, + (x[0] = x[1] = "("), + (h[0] = h[1] = ")"), + (h.origin = [ + "", + "end of interpolation", + h[2], + ]); + } + "TERMINATOR" === + (null == (T = E[1]) + ? void 0 + : T[0]) && E.splice(1, 1), + c || + ((x = this.makeToken( + "(", + "(", + S, + 0, + )), + (h = this.makeToken( + ")", + ")", + S + v, + 0, + )), + (E = [x].concat( + _toConsumableArray(E), + [h], + ))), + L.push(["TOKENS", E]), + (C = C.slice(v)), + (S += v); + } + return ( + C.slice(0, s.length) !== s && + this.error("missing " + s, { + length: i.length, + }), + (u = L), + (a = _slicedToArray(u, 1)), + (d = a[0]), + u, + (f = n.call(L, -1)), + (l = _slicedToArray(f, 1)), + (y = l[0]), + f, + (d[2].first_column -= i.length), + "\n" === y[1].substr(-1) + ? ((y[2].last_line += 1), + (y[2].last_column = + s.length - 1)) + : (y[2].last_column += + s.length), + 0 === y[1].length && + (y[2].last_column -= 1), + { tokens: L, index: S + s.length } + ); + }, + }, + { + key: "mergeInterpolationTokens", + value: function (t, r, i) { + var s, + o, + u, + a, + f, + l, + c, + h, + p, + d, + v, + m, + g, + y, + b, + w, + E, + S, + x; + for ( + 1 < t.length && + (v = this.token( + "STRING_START", + "(", + 0, + 0, + )), + u = this.tokens.length, + a = f = 0, + h = t.length; + f < h; + a = ++f + ) { + var T; + w = t[a]; + var N = w, + C = _slicedToArray(N, 2); + switch ( + ((b = C[0]), (x = C[1]), b) + ) { + case "TOKENS": + if (2 === x.length) { + if ( + !x[0].comments && + !x[1].comments + ) + continue; + for ( + m = + 0 === + this.csxDepth + ? this.makeToken( + "STRING", + "''", + ) + : this.makeToken( + "JS", + "", + ), + m[2] = x[0][2], + l = 0, + p = x.length; + l < p; + l++ + ) { + var k; + ((S = x[l]), + !!S.comments) && + (null == + m.comments && + (m.comments = + []), + (k = + m.comments).push.apply( + k, + _toConsumableArray( + S.comments, + ), + )); + } + x.splice(1, 0, m); + } + (d = x[0]), (E = x); + break; + case "NEOSTRING": + if ( + ((s = i.call( + this, + w[1], + a, + )), + 0 === s.length) + ) { + if (0 !== a) continue; + o = this.tokens.length; + } + 2 === a && + null != o && + this.tokens.splice( + o, + 2, + ), + (w[0] = "STRING"), + (w[1] = + this.makeDelimitedLiteral( + s, + r, + )), + (d = w), + (E = [w]); + } + this.tokens.length > u && + ((g = this.token("+", "+")), + (g[2] = { + first_line: d[2].first_line, + first_column: + d[2].first_column, + last_line: d[2].first_line, + last_column: + d[2].first_column, + })), + (T = this.tokens).push.apply( + T, + _toConsumableArray(E), + ); + } + if (v) { + var L = n.call(t, -1), + A = _slicedToArray(L, 1); + return ( + (c = A[0]), + (v.origin = [ + "STRING", + null, + { + first_line: + v[2].first_line, + first_column: + v[2].first_column, + last_line: + c[2].last_line, + last_column: + c[2].last_column, + }, + ]), + (v[2] = v.origin[2]), + (y = this.token( + "STRING_END", + ")", + )), + (y[2] = { + first_line: c[2].last_line, + first_column: + c[2].last_column, + last_line: c[2].last_line, + last_column: + c[2].last_column, + }) + ); + } + }, + }, + { + key: "pair", + value: function (t) { + var r, i, s, o, u, a, f; + if ( + ((u = this.ends), + (r = n.call(u, -1)), + (i = _slicedToArray(r, 1)), + (o = i[0]), + r, + t !== + (f = + null == o ? void 0 : o.tag)) + ) { + var l, c; + return ( + "OUTDENT" !== f && + this.error( + "unmatched " + t, + ), + (a = this.indents), + (l = n.call(a, -1)), + (c = _slicedToArray(l, 1)), + (s = c[0]), + l, + this.outdentToken(s, !0), + this.pair(t) + ); + } + return this.ends.pop(); + }, + }, + { + key: "getLineAndColumnFromChunk", + value: function (t) { + var r, i, s, o, u; + if (0 === t) + return [ + this.chunkLine, + this.chunkColumn, + ]; + if ( + ((u = + t >= this.chunk.length + ? this.chunk + : this.chunk.slice( + 0, + +(t - 1) + 1 || 9e9, + )), + (s = dt(u, "\n")), + (r = this.chunkColumn), + 0 < s) + ) { + var a, f; + (o = u.split("\n")), + (a = n.call(o, -1)), + (f = _slicedToArray(a, 1)), + (i = f[0]), + a, + (r = i.length); + } else r += u.length; + return [this.chunkLine + s, r]; + }, + }, + { + key: "makeToken", + value: function (t, n) { + var r = + 2 < arguments.length && + void 0 !== arguments[2] + ? arguments[2] + : 0, + i = + 3 < arguments.length && + void 0 !== arguments[3] + ? arguments[3] + : n.length, + s, + o, + u; + o = {}; + var a = + this.getLineAndColumnFromChunk( + r, + ), + f = _slicedToArray(a, 2); + (o.first_line = f[0]), + (o.first_column = f[1]), + (s = 0 < i ? i - 1 : 0); + var l = this.getLineAndColumnFromChunk( + r + s, + ), + c = _slicedToArray(l, 2); + return ( + (o.last_line = c[0]), + (o.last_column = c[1]), + (u = [t, n, o]), + u + ); + }, + }, + { + key: "token", + value: function (e, t, n, r, i) { + var s; + return ( + (s = this.makeToken(e, t, n, r)), + i && (s.origin = i), + this.tokens.push(s), + s + ); + }, + }, + { + key: "tag", + value: function () { + var t, r, i, s; + return ( + (i = this.tokens), + (t = n.call(i, -1)), + (r = _slicedToArray(t, 1)), + (s = r[0]), + t, + null == s ? void 0 : s[0] + ); + }, + }, + { + key: "value", + value: function () { + var t = + 0 < arguments.length && + void 0 !== arguments[0] && + arguments[0], + r, + i, + s, + o, + u; + return ( + (s = this.tokens), + (r = n.call(s, -1)), + (i = _slicedToArray(r, 1)), + (u = i[0]), + r, + t && + null != + (null == u ? void 0 : u.origin) + ? null == (o = u.origin) + ? void 0 + : o[1] + : null == u + ? void 0 + : u[1] + ); + }, + }, + { + key: "prev", + value: function () { + return this.tokens[ + this.tokens.length - 1 + ]; + }, + }, + { + key: "unfinished", + value: function () { + var n; + return ( + H.test(this.chunk) || + ((n = this.tag()), + 0 <= t.call(at, n)) + ); + }, + }, + { + key: "formatString", + value: function (t, n) { + return this.replaceUnicodeCodePointEscapes( + t.replace(tt, "$1"), + n, + ); + }, + }, + { + key: "formatHeregex", + value: function (t, n) { + return this.formatRegex( + t.replace(T, "$1$2"), + wt(n, { delimiter: "///" }), + ); + }, + }, + { + key: "formatRegex", + value: function (t, n) { + return this.replaceUnicodeCodePointEscapes( + t, + n, + ); + }, + }, + { + key: "unicodeCodePointToUnicodeEscapes", + value: function (t) { + var n, r, i; + return ((i = function (e) { + var t; + return ( + (t = e.toString(16)), + "\\u" + + Et("0", 4 - t.length) + + t + ); + }), + 65536 > t) + ? i(t) + : ((n = + _Mathfloor( + (t - 65536) / 1024, + ) + 55296), + (r = + ((t - 65536) % 1024) + 56320), + "" + i(n) + i(r)); + }, + }, + { + key: "replaceUnicodeCodePointEscapes", + value: function (n, r) { + var i = this, + s; + return ( + (s = + null != r.flags && + 0 > t.call(r.flags, "u")), + n.replace( + ft, + function (e, t, n, o) { + var u; + return t + ? t + : ((u = parseInt( + n, + 16, + )), + 1114111 < u && + i.error( + "unicode code point escapes greater than \\u{10ffff} are not allowed", + { + offset: + o + + r + .delimiter + .length, + length: + n.length + + 4, + }, + ), + s + ? i.unicodeCodePointToUnicodeEscapes( + u, + ) + : e); + }, + ) + ); + }, + }, + { + key: "validateEscapes", + value: function (t) { + var n = + 1 < arguments.length && + void 0 !== arguments[1] + ? arguments[1] + : {}, + r, + i, + s, + o, + u, + a, + f, + l, + c, + h; + if ( + ((o = n.isRegex ? V : et), + (u = o.exec(t)), + !!u) + ) + return ( + u[0], + (r = u[1]), + (f = u[2]), + (i = u[3]), + (h = u[4]), + (c = u[5]), + (a = f + ? "octal escape sequences are not allowed" + : "invalid escape sequence"), + (s = "\\" + (f || i || h || c)), + this.error(a + " " + s, { + offset: + (null == + (l = n.offsetInChunk) + ? 0 + : l) + + u.index + + r.length, + length: s.length, + }) + ); + }, + }, + { + key: "makeDelimitedLiteral", + value: function (t) { + var n = + 1 < arguments.length && + void 0 !== arguments[1] + ? arguments[1] + : {}, + r; + return ( + "" === t && + "/" === n.delimiter && + (t = "(?:)"), + (r = RegExp( + "(\\\\\\\\)|(\\\\0(?=[1-7]))|\\\\?(" + + n.delimiter + + ")|\\\\?(?:(\\n)|(\\r)|(\\u2028)|(\\u2029))|(\\\\.)", + "g", + )), + (t = t.replace( + r, + function ( + e, + t, + r, + i, + s, + o, + u, + a, + f, + ) { + switch (!1) { + case !t: + return n.double + ? t + t + : t; + case !r: + return "\\x00"; + case !i: + return "\\" + i; + case !s: + return "\\n"; + case !o: + return "\\r"; + case !u: + return "\\u2028"; + case !a: + return "\\u2029"; + case !f: + return n.double + ? "\\" + f + : f; + } + }, + )), + "" + n.delimiter + t + n.delimiter + ); + }, + }, + { + key: "suppressSemicolons", + value: function () { + var n, r, i; + for (i = []; ";" === this.value(); ) + this.tokens.pop(), + ((n = + null == (r = this.prev()) + ? void 0 + : r[0]), + 0 <= + t.call( + ["="].concat( + _toConsumableArray( + at, + ), + ), + n, + )) + ? i.push( + this.error( + "unexpected ;", + ), + ) + : i.push(void 0); + return i; + }, + }, + { + key: "error", + value: function (t) { + var n = + 1 < arguments.length && + void 0 !== arguments[1] + ? arguments[1] + : {}, + r, + i, + s, + o, + u, + a, + f; + return ( + (u = + "first_line" in n + ? n + : ((r = + this.getLineAndColumnFromChunk( + null == + (a = n.offset) + ? 0 + : a, + )), + (i = _slicedToArray( + r, + 2, + )), + (o = i[0]), + (s = i[1]), + r, + { + first_line: o, + first_column: s, + last_column: + s + + (null == + (f = n.length) + ? 1 + : f) - + 1, + })), + xt(t, u) + ); + }, + }, + ]), + e + ); + })()), + (gt = function (e) { + var n = + 1 < arguments.length && void 0 !== arguments[1] + ? arguments[1] + : e; + switch (!1) { + case 0 > + t.call( + [].concat( + _toConsumableArray(_), + _toConsumableArray(l), + ), + e, + ): + return "keyword '" + n + "' can't be assigned"; + case 0 > t.call(Y, e): + return "'" + n + "' can't be assigned"; + case 0 > t.call(J, e): + return ( + "reserved word '" + n + "' can't be assigned" + ); + default: + return !1; + } + }), + (e.isUnassignable = gt), + (mt = function (e) { + var t; + return "IDENTIFIER" === e[0] + ? ("from" === e[1] && ((e[1][0] = "IDENTIFIER"), !0), + !0) + : "FOR" !== e[0] && + "{" !== (t = e[1]) && + "[" !== t && + "," !== t && + ":" !== t; + }), + (_ = [ + "true", + "false", + "null", + "this", + "new", + "delete", + "typeof", + "in", + "instanceof", + "return", + "throw", + "break", + "continue", + "debugger", + "yield", + "await", + "if", + "else", + "switch", + "for", + "while", + "do", + "try", + "catch", + "finally", + "class", + "extends", + "super", + "import", + "export", + "default", + ]), + (l = [ + "undefined", + "Infinity", + "NaN", + "then", + "unless", + "until", + "loop", + "of", + "by", + "when", + ]), + (f = { + and: "&&", + or: "||", + is: "==", + isnt: "!=", + not: "!", + yes: "true", + no: "false", + on: "true", + off: "false", + }), + (a = (function () { + var e; + for (yt in ((e = []), f)) e.push(yt); + return e; + })()), + (l = l.concat(a)), + (J = [ + "case", + "function", + "var", + "void", + "with", + "const", + "let", + "enum", + "native", + "implements", + "interface", + "package", + "private", + "protected", + "public", + "static", + ]), + (Y = ["arguments", "eval"]), + (e.JS_FORBIDDEN = _.concat(J).concat(Y)), + (i = 65279), + (C = /^(?!\d)((?:(?!\s)[$\w\x7f-\uffff])+)([^\n\S]*:(?!:))?/), + (g = /^(?![\d<])((?:(?!\s)[\.\-$\w\x7f-\uffff])+)/), + (m = /^()>/), + (v = /^(?!\d)((?:(?!\s)[\-$\w\x7f-\uffff])+)([^\S]*=(?!=))?/), + (q = + /^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i), + (R = + /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>*\/%])\2=?|\?(\.|::)|\.{2,3})/), + (ct = /^[^\n\S]+/), + (c = + /^\s*###([^#][\s\S]*?)(?:###[^\n\S]*|###$)|^(?:\s*#(?!##[^#]).*)+/), + (u = /^[-=]>/), + (F = /^(?:\n[^\n\S]*)+/), + (M = /^`(?!``)((?:[^`\\]|\\[\s\S])*)`/), + (N = /^```((?:[^`\\]|\\[\s\S]|`(?!``))*)```/), + (rt = /^(?:'''|"""|'|")/), + (nt = /^(?:[^\\']|\\[\s\S])*/), + (Z = /^(?:[^\\"#]|\\[\s\S]|\#(?!\{))*/), + (S = /^(?:[^\\']|\\[\s\S]|'(?!''))*/), + (w = /^(?:[^\\"#]|\\[\s\S]|"(?!"")|\#(?!\{))*/), + (A = /^(?:[^\{<])*/), + (y = /^(?:\{|<(?!\/))/), + (tt = /((?:\\\\)+)|\\[^\S\n]*\n\s*/g), + (G = /\s*\n\s*/g), + (E = /\n+([^\n\S]*)(?=\S)/g), + (z = + /^\/(?!\/)((?:[^[\/\n\\]|\\[^\n]|\[(?:\\[^\n]|[^\]\n\\])*\])*)(\/)?/), + (W = /^\w*/), + (lt = /^(?!.*(.).*\1)[imguy]*$/), + (x = + /^(?:[^\\\/#\s]|\\[\s\S]|\/(?!\/\/)|\#(?!\{)|\s+(?:#(?!\{).*)?)*/), + (T = /((?:\\\\)+)|\\(\s)|\s+(?:#.*)?/g), + (X = /^(\/|\/{3}\s*)(\*)/), + (U = /^\/=?\s/), + (b = /\*\//), + (H = /^\s*(?:,|\??\.(?![.\d])|::)/), + (et = + /((?:^|[^\\])(?:\\\\)*)\\(?:(0[0-7]|[1-7])|(x(?![\da-fA-F]{2}).{0,2})|(u\{(?![\da-fA-F]{1,}\})[^}]*\}?)|(u(?!\{|[\da-fA-F]{4}).{0,4}))/), + (V = + /((?:^|[^\\])(?:\\\\)*)\\(?:(0[0-7])|(x(?![\da-fA-F]{2}).{0,2})|(u\{(?![\da-fA-F]{1,}\})[^}]*\}?)|(u(?!\{|[\da-fA-F]{4}).{0,4}))/), + (ft = /(\\\\)|\\u\{([\da-fA-F]+)\}/g), + (D = /^[^\n\S]*\n/), + (it = /\n[^\n\S]*$/), + (st = /\s+$/), + (d = [ + "-=", + "+=", + "/=", + "*=", + "%=", + "||=", + "&&=", + "?=", + "<<=", + ">>=", + ">>>=", + "&=", + "^=", + "|=", + "**=", + "//=", + "%%=", + ]), + (ot = ["NEW", "TYPEOF", "DELETE", "DO"]), + (ut = ["!", "~"]), + (Q = ["<<", ">>", ">>>"]), + (p = ["==", "!=", "<", ">", "<=", ">="]), + (j = ["*", "/", "%", "//", "%%"]), + ($ = ["IN", "OF", "INSTANCEOF"]), + (s = ["TRUE", "FALSE"]), + (o = [ + "IDENTIFIER", + "PROPERTY", + ")", + "]", + "?", + "@", + "THIS", + "SUPER", + ]), + (L = o.concat([ + "NUMBER", + "INFINITY", + "NAN", + "STRING", + "STRING_END", + "REGEX", + "REGEX_END", + "BOOL", + "NULL", + "UNDEFINED", + "}", + "::", + ])), + (h = ["IDENTIFIER", ")", "]", "NUMBER"]), + (I = L.concat(["++", "--"])), + (P = ["INDENT", "OUTDENT", "TERMINATOR"]), + (k = [")", "}", "]"]), + (at = [ + "\\", + ".", + "?.", + "?::", + "UNARY", + "MATH", + "UNARY_MATH", + "+", + "-", + "**", + "SHIFT", + "RELATION", + "COMPARE", + "&", + "^", + "|", + "&&", + "||", + "BIN?", + "EXTENDS", + ]); + }.call(this), + { exports: e }.exports + ); + })()), + (require["./parser"] = (function () { + var e = {}, + t = { exports: e }, + n = (function () { + function e() { + this.yy = {}; + } + var t = function (e, t, n, r) { + for (n = n || {}, r = e.length; r--; n[e[r]] = t); + return n; + }, + n = [1, 24], + r = [1, 56], + i = [1, 91], + s = [1, 92], + o = [1, 87], + u = [1, 93], + a = [1, 94], + f = [1, 89], + l = [1, 90], + c = [1, 64], + h = [1, 66], + p = [1, 67], + d = [1, 68], + v = [1, 69], + m = [1, 70], + g = [1, 72], + y = [1, 73], + b = [1, 58], + w = [1, 42], + E = [1, 36], + S = [1, 76], + x = [1, 77], + T = [1, 86], + N = [1, 54], + C = [1, 59], + k = [1, 60], + L = [1, 74], + A = [1, 75], + O = [1, 47], + M = [1, 55], + _ = [1, 71], + D = [1, 81], + P = [1, 82], + H = [1, 83], + B = [1, 84], + j = [1, 53], + F = [1, 80], + I = [1, 38], + q = [1, 39], + R = [1, 40], + U = [1, 41], + z = [1, 43], + W = [1, 44], + X = [1, 95], + V = [1, 6, 36, 47, 146], + $ = [1, 6, 35, 36, 47, 69, 70, 93, 127, 135, 146, 149, 157], + J = [1, 113], + K = [1, 114], + Q = [1, 115], + G = [1, 110], + Y = [1, 98], + Z = [1, 97], + et = [1, 96], + tt = [1, 99], + nt = [1, 100], + rt = [1, 101], + it = [1, 102], + st = [1, 103], + ot = [1, 104], + ut = [1, 105], + at = [1, 106], + ft = [1, 107], + lt = [1, 108], + ct = [1, 109], + ht = [1, 117], + pt = [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, 135, 146, + 148, 149, 150, 156, 157, 174, 178, 179, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, + ], + dt = [2, 196], + vt = [1, 123], + mt = [1, 128], + gt = [1, 124], + yt = [1, 125], + bt = [1, 126], + wt = [1, 129], + Et = [1, 122], + St = [ + 1, 6, 35, 36, 47, 69, 70, 93, 127, 135, 146, 148, 149, 150, + 156, 157, 174, + ], + xt = [ + 1, 6, 35, 36, 45, 46, 47, 69, 70, 80, 81, 83, 88, 93, 101, + 102, 103, 105, 109, 125, 126, 127, 135, 146, 148, 149, 150, + 156, 157, 174, 178, 179, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, + ], + Tt = [2, 122], + Nt = [2, 126], + Ct = [6, 35, 88, 93], + kt = [2, 99], + Lt = [1, 141], + At = [1, 135], + Ot = [1, 140], + Mt = [1, 144], + _t = [1, 149], + Dt = [1, 147], + Pt = [1, 151], + Ht = [1, 155], + Bt = [1, 153], + jt = [ + 1, 6, 35, 36, 45, 46, 47, 61, 69, 70, 80, 81, 83, 88, 93, + 101, 102, 103, 105, 109, 125, 126, 127, 135, 146, 148, 149, + 150, 156, 157, 174, 178, 179, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193, + ], + Ft = [2, 119], + It = [ + 1, 6, 36, 47, 69, 70, 83, 88, 93, 109, 127, 135, 146, 148, + 149, 150, 156, 157, 174, 178, 179, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, + ], + qt = [2, 31], + Rt = [1, 183], + Ut = [2, 86], + zt = [1, 187], + Wt = [1, 193], + Xt = [1, 208], + Vt = [1, 203], + $t = [1, 212], + Jt = [1, 209], + Kt = [1, 214], + Qt = [1, 215], + Gt = [1, 217], + Yt = [ + 14, 32, 35, 38, 39, 43, 45, 46, 49, 50, 54, 55, 56, 57, 58, + 59, 68, 77, 84, 85, 86, 90, 91, 107, 110, 112, 120, 129, + 130, 140, 144, 145, 148, 150, 153, 156, 167, 173, 176, 177, + 178, 179, 180, 181, + ], + Zt = [ + 1, 6, 35, 36, 45, 46, 47, 61, 69, 70, 80, 81, 83, 88, 93, + 101, 102, 103, 105, 109, 111, 125, 126, 127, 135, 146, 148, + 149, 150, 156, 157, 174, 178, 179, 180, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + ], + en = [1, 228], + tn = [2, 142], + nn = [1, 250], + rn = [1, 245], + sn = [1, 256], + on = [ + 1, 6, 35, 36, 45, 46, 47, 65, 69, 70, 80, 81, 83, 88, 93, + 101, 102, 103, 105, 109, 125, 126, 127, 135, 146, 148, 149, + 150, 156, 157, 174, 178, 179, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193, + ], + un = [ + 1, 6, 33, 35, 36, 45, 46, 47, 61, 65, 69, 70, 80, 81, 83, + 88, 93, 101, 102, 103, 105, 109, 111, 117, 125, 126, 127, + 135, 146, 148, 149, 150, 156, 157, 164, 165, 166, 174, 178, + 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, + ], + an = [ + 1, 6, 35, 36, 45, 46, 47, 52, 65, 69, 70, 80, 81, 83, 88, + 93, 101, 102, 103, 105, 109, 125, 126, 127, 135, 146, 148, + 149, 150, 156, 157, 174, 178, 179, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, + ], + fn = [1, 286], + ln = [45, 46, 126], + cn = [1, 297], + hn = [1, 296], + pn = [6, 35], + dn = [2, 97], + vn = [1, 303], + mn = [6, 35, 36, 88, 93], + gn = [6, 35, 36, 61, 70, 88, 93], + yn = [ + 1, 6, 35, 36, 47, 69, 70, 80, 81, 83, 88, 93, 101, 102, 103, + 105, 109, 127, 135, 146, 148, 149, 150, 156, 157, 174, 178, + 179, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, + ], + bn = [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, 135, 146, + 148, 149, 150, 156, 157, 174, 178, 179, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, + ], + wn = [2, 347], + En = [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, 135, 146, + 148, 149, 150, 156, 157, 174, 178, 179, 183, 185, 186, 187, + 188, 189, 190, 191, 192, 193, + ], + Sn = [45, 46, 80, 81, 101, 102, 103, 105, 125, 126], + xn = [1, 330], + Tn = [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, 135, 146, + 148, 149, 150, 156, 157, 174, + ], + Nn = [2, 84], + Cn = [1, 346], + kn = [1, 348], + Ln = [1, 353], + An = [1, 355], + On = [6, 35, 69, 93], + Mn = [2, 221], + _n = [2, 222], + Dn = [ + 1, 6, 35, 36, 45, 46, 47, 61, 69, 70, 80, 81, 83, 88, 93, + 101, 102, 103, 105, 109, 125, 126, 127, 135, 146, 148, 149, + 150, 156, 157, 164, 165, 166, 174, 178, 179, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, + ], + Pn = [1, 369], + Hn = [ + 6, 14, 32, 35, 36, 38, 39, 43, 45, 46, 49, 50, 54, 55, 56, + 57, 58, 59, 68, 69, 70, 77, 84, 85, 86, 90, 91, 93, 107, + 110, 112, 120, 129, 130, 140, 144, 145, 148, 150, 153, 156, + 167, 173, 176, 177, 178, 179, 180, 181, + ], + Bn = [6, 35, 36, 69, 93], + jn = [6, 35, 36, 69, 93, 127], + Fn = [ + 1, 6, 35, 36, 45, 46, 47, 61, 65, 69, 70, 80, 81, 83, 88, + 93, 101, 102, 103, 105, 109, 111, 125, 126, 127, 135, 146, + 148, 149, 150, 156, 157, 164, 165, 166, 174, 178, 179, 180, + 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, + ], + In = [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, 135, 146, + 157, 174, + ], + qn = [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, 135, 146, + 149, 157, 174, + ], + Rn = [2, 273], + Un = [164, 165, 166], + zn = [93, 164, 165, 166], + Wn = [6, 35, 109], + Xn = [1, 393], + Vn = [6, 35, 36, 93, 109], + $n = [6, 35, 36, 65, 93, 109], + Jn = [1, 399], + Kn = [1, 400], + Qn = [6, 35, 36, 61, 65, 70, 80, 81, 93, 109, 126], + Gn = [6, 35, 36, 70, 80, 81, 93, 109, 126], + Yn = [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, 135, 146, + 148, 149, 150, 156, 157, 174, 178, 179, 185, 186, 187, 188, + 189, 190, 191, 192, 193, + ], + Zn = [2, 339], + er = [2, 338], + tr = [ + 1, 6, 35, 36, 45, 46, 47, 52, 69, 70, 80, 81, 83, 88, 93, + 101, 102, 103, 105, 109, 125, 126, 127, 135, 146, 148, 149, + 150, 156, 157, 174, 178, 179, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193, + ], + nr = [1, 422], + rr = [ + 14, 32, 38, 39, 43, 45, 46, 49, 50, 54, 55, 56, 57, 58, 59, + 68, 77, 83, 84, 85, 86, 90, 91, 107, 110, 112, 120, 129, + 130, 140, 144, 145, 148, 150, 153, 156, 167, 173, 176, 177, + 178, 179, 180, 181, + ], + ir = [2, 207], + sr = [6, 35, 36], + or = [2, 98], + ur = [1, 431], + ar = [1, 432], + fr = [ + 1, 6, 35, 36, 47, 69, 70, 80, 81, 83, 88, 93, 101, 102, 103, + 105, 109, 127, 135, 142, 143, 146, 148, 149, 150, 156, 157, + 169, 171, 174, 178, 179, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, + ], + lr = [1, 312], + cr = [36, 169, 171], + hr = [ + 1, 6, 36, 47, 69, 70, 83, 88, 93, 109, 127, 135, 146, 149, + 157, 174, + ], + pr = [1, 467], + dr = [1, 473], + vr = [ + 1, 6, 35, 36, 47, 69, 70, 93, 127, 135, 146, 149, 157, 174, + ], + mr = [2, 113], + gr = [1, 486], + yr = [1, 487], + br = [6, 35, 36, 69], + wr = [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, 135, 146, + 148, 149, 150, 156, 157, 169, 174, 178, 179, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, + ], + Er = [ + 1, 6, 35, 36, 47, 69, 70, 93, 127, 135, 146, 149, 157, 169, + ], + Sr = [2, 286], + xr = [2, 287], + Tr = [2, 302], + Nr = [1, 510], + Cr = [1, 511], + kr = [6, 35, 36, 109], + Lr = [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, 135, 146, + 148, 150, 156, 157, 174, + ], + Ar = [1, 532], + Or = [6, 35, 36, 93, 127], + Mr = [6, 35, 36, 93], + _r = [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, 135, 142, + 146, 148, 149, 150, 156, 157, 174, 178, 179, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, + ], + Dr = [35, 93], + Pr = [1, 560], + Hr = [1, 561], + Br = [1, 567], + jr = [1, 568], + Fr = [2, 258], + Ir = [2, 261], + qr = [2, 274], + Rr = [1, 617], + Ur = [1, 618], + zr = [2, 288], + Wr = [2, 292], + Xr = [2, 289], + Vr = [2, 293], + $r = [2, 290], + Jr = [2, 291], + Kr = [2, 303], + Qr = [2, 304], + Gr = [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, 135, 146, + 148, 149, 150, 156, 174, + ], + Yr = [2, 294], + Zr = [2, 296], + ei = [2, 298], + ti = [2, 300], + ni = [2, 295], + ri = [2, 297], + ii = [2, 299], + si = [2, 301], + oi = { + trace: function () {}, + yy: {}, + symbols_: { + error: 2, + Root: 3, + Body: 4, + Line: 5, + TERMINATOR: 6, + Expression: 7, + ExpressionLine: 8, + Statement: 9, + FuncDirective: 10, + YieldReturn: 11, + AwaitReturn: 12, + Return: 13, + STATEMENT: 14, + Import: 15, + Export: 16, + Value: 17, + Code: 18, + Operation: 19, + Assign: 20, + If: 21, + Try: 22, + While: 23, + For: 24, + Switch: 25, + Class: 26, + Throw: 27, + Yield: 28, + CodeLine: 29, + IfLine: 30, + OperationLine: 31, + YIELD: 32, + FROM: 33, + Block: 34, + INDENT: 35, + OUTDENT: 36, + Identifier: 37, + IDENTIFIER: 38, + CSX_TAG: 39, + Property: 40, + PROPERTY: 41, + AlphaNumeric: 42, + NUMBER: 43, + String: 44, + STRING: 45, + STRING_START: 46, + STRING_END: 47, + Regex: 48, + REGEX: 49, + REGEX_START: 50, + Invocation: 51, + REGEX_END: 52, + Literal: 53, + JS: 54, + UNDEFINED: 55, + NULL: 56, + BOOL: 57, + INFINITY: 58, + NAN: 59, + Assignable: 60, + "=": 61, + AssignObj: 62, + ObjAssignable: 63, + ObjRestValue: 64, + ":": 65, + SimpleObjAssignable: 66, + ThisProperty: 67, + "[": 68, + "]": 69, + "...": 70, + ObjSpreadExpr: 71, + ObjSpreadIdentifier: 72, + Object: 73, + Parenthetical: 74, + Super: 75, + This: 76, + SUPER: 77, + Arguments: 78, + ObjSpreadAccessor: 79, + ".": 80, + INDEX_START: 81, + IndexValue: 82, + INDEX_END: 83, + RETURN: 84, + AWAIT: 85, + PARAM_START: 86, + ParamList: 87, + PARAM_END: 88, + FuncGlyph: 89, + "->": 90, + "=>": 91, + OptComma: 92, + ",": 93, + Param: 94, + ParamVar: 95, + Array: 96, + Splat: 97, + SimpleAssignable: 98, + Accessor: 99, + Range: 100, + "?.": 101, + "::": 102, + "?::": 103, + Index: 104, + INDEX_SOAK: 105, + Slice: 106, + "{": 107, + AssignList: 108, + "}": 109, + CLASS: 110, + EXTENDS: 111, + IMPORT: 112, + ImportDefaultSpecifier: 113, + ImportNamespaceSpecifier: 114, + ImportSpecifierList: 115, + ImportSpecifier: 116, + AS: 117, + DEFAULT: 118, + IMPORT_ALL: 119, + EXPORT: 120, + ExportSpecifierList: 121, + EXPORT_ALL: 122, + ExportSpecifier: 123, + OptFuncExist: 124, + FUNC_EXIST: 125, + CALL_START: 126, + CALL_END: 127, + ArgList: 128, + THIS: 129, + "@": 130, + Elisions: 131, + ArgElisionList: 132, + OptElisions: 133, + RangeDots: 134, + "..": 135, + Arg: 136, + ArgElision: 137, + Elision: 138, + SimpleArgs: 139, + TRY: 140, + Catch: 141, + FINALLY: 142, + CATCH: 143, + THROW: 144, + "(": 145, + ")": 146, + WhileLineSource: 147, + WHILE: 148, + WHEN: 149, + UNTIL: 150, + WhileSource: 151, + Loop: 152, + LOOP: 153, + ForBody: 154, + ForLineBody: 155, + FOR: 156, + BY: 157, + ForStart: 158, + ForSource: 159, + ForLineSource: 160, + ForVariables: 161, + OWN: 162, + ForValue: 163, + FORIN: 164, + FOROF: 165, + FORFROM: 166, + SWITCH: 167, + Whens: 168, + ELSE: 169, + When: 170, + LEADING_WHEN: 171, + IfBlock: 172, + IF: 173, + POST_IF: 174, + IfBlockLine: 175, + UNARY: 176, + UNARY_MATH: 177, + "-": 178, + "+": 179, + "--": 180, + "++": 181, + "?": 182, + MATH: 183, + "**": 184, + SHIFT: 185, + COMPARE: 186, + "&": 187, + "^": 188, + "|": 189, + "&&": 190, + "||": 191, + "BIN?": 192, + RELATION: 193, + COMPOUND_ASSIGN: 194, + $accept: 0, + $end: 1, + }, + terminals_: { + 2: "error", + 6: "TERMINATOR", + 14: "STATEMENT", + 32: "YIELD", + 33: "FROM", + 35: "INDENT", + 36: "OUTDENT", + 38: "IDENTIFIER", + 39: "CSX_TAG", + 41: "PROPERTY", + 43: "NUMBER", + 45: "STRING", + 46: "STRING_START", + 47: "STRING_END", + 49: "REGEX", + 50: "REGEX_START", + 52: "REGEX_END", + 54: "JS", + 55: "UNDEFINED", + 56: "NULL", + 57: "BOOL", + 58: "INFINITY", + 59: "NAN", + 61: "=", + 65: ":", + 68: "[", + 69: "]", + 70: "...", + 77: "SUPER", + 80: ".", + 81: "INDEX_START", + 83: "INDEX_END", + 84: "RETURN", + 85: "AWAIT", + 86: "PARAM_START", + 88: "PARAM_END", + 90: "->", + 91: "=>", + 93: ",", + 101: "?.", + 102: "::", + 103: "?::", + 105: "INDEX_SOAK", + 107: "{", + 109: "}", + 110: "CLASS", + 111: "EXTENDS", + 112: "IMPORT", + 117: "AS", + 118: "DEFAULT", + 119: "IMPORT_ALL", + 120: "EXPORT", + 122: "EXPORT_ALL", + 125: "FUNC_EXIST", + 126: "CALL_START", + 127: "CALL_END", + 129: "THIS", + 130: "@", + 135: "..", + 140: "TRY", + 142: "FINALLY", + 143: "CATCH", + 144: "THROW", + 145: "(", + 146: ")", + 148: "WHILE", + 149: "WHEN", + 150: "UNTIL", + 153: "LOOP", + 156: "FOR", + 157: "BY", + 162: "OWN", + 164: "FORIN", + 165: "FOROF", + 166: "FORFROM", + 167: "SWITCH", + 169: "ELSE", + 171: "LEADING_WHEN", + 173: "IF", + 174: "POST_IF", + 176: "UNARY", + 177: "UNARY_MATH", + 178: "-", + 179: "+", + 180: "--", + 181: "++", + 182: "?", + 183: "MATH", + 184: "**", + 185: "SHIFT", + 186: "COMPARE", + 187: "&", + 188: "^", + 189: "|", + 190: "&&", + 191: "||", + 192: "BIN?", + 193: "RELATION", + 194: "COMPOUND_ASSIGN", + }, + productions_: [ + 0, + [3, 0], + [3, 1], + [4, 1], + [4, 3], + [4, 2], + [5, 1], + [5, 1], + [5, 1], + [5, 1], + [10, 1], + [10, 1], + [9, 1], + [9, 1], + [9, 1], + [9, 1], + [7, 1], + [7, 1], + [7, 1], + [7, 1], + [7, 1], + [7, 1], + [7, 1], + [7, 1], + [7, 1], + [7, 1], + [7, 1], + [7, 1], + [8, 1], + [8, 1], + [8, 1], + [28, 1], + [28, 2], + [28, 3], + [34, 2], + [34, 3], + [37, 1], + [37, 1], + [40, 1], + [42, 1], + [42, 1], + [44, 1], + [44, 3], + [48, 1], + [48, 3], + [53, 1], + [53, 1], + [53, 1], + [53, 1], + [53, 1], + [53, 1], + [53, 1], + [53, 1], + [20, 3], + [20, 4], + [20, 5], + [62, 1], + [62, 1], + [62, 3], + [62, 5], + [62, 3], + [62, 5], + [66, 1], + [66, 1], + [66, 1], + [66, 3], + [63, 1], + [63, 1], + [64, 2], + [64, 2], + [64, 2], + [64, 2], + [71, 1], + [71, 1], + [71, 1], + [71, 1], + [71, 1], + [71, 2], + [71, 2], + [71, 2], + [72, 2], + [72, 2], + [79, 2], + [79, 3], + [13, 2], + [13, 4], + [13, 1], + [11, 3], + [11, 2], + [12, 3], + [12, 2], + [18, 5], + [18, 2], + [29, 5], + [29, 2], + [89, 1], + [89, 1], + [92, 0], + [92, 1], + [87, 0], + [87, 1], + [87, 3], + [87, 4], + [87, 6], + [94, 1], + [94, 2], + [94, 2], + [94, 3], + [94, 1], + [95, 1], + [95, 1], + [95, 1], + [95, 1], + [97, 2], + [97, 2], + [98, 1], + [98, 2], + [98, 2], + [98, 1], + [60, 1], + [60, 1], + [60, 1], + [17, 1], + [17, 1], + [17, 1], + [17, 1], + [17, 1], + [17, 1], + [17, 1], + [75, 3], + [75, 4], + [99, 2], + [99, 2], + [99, 2], + [99, 2], + [99, 1], + [99, 1], + [104, 3], + [104, 2], + [82, 1], + [82, 1], + [73, 4], + [108, 0], + [108, 1], + [108, 3], + [108, 4], + [108, 6], + [26, 1], + [26, 2], + [26, 3], + [26, 4], + [26, 2], + [26, 3], + [26, 4], + [26, 5], + [15, 2], + [15, 4], + [15, 4], + [15, 5], + [15, 7], + [15, 6], + [15, 9], + [115, 1], + [115, 3], + [115, 4], + [115, 4], + [115, 6], + [116, 1], + [116, 3], + [116, 1], + [116, 3], + [113, 1], + [114, 3], + [16, 3], + [16, 5], + [16, 2], + [16, 4], + [16, 5], + [16, 6], + [16, 3], + [16, 5], + [16, 4], + [16, 7], + [121, 1], + [121, 3], + [121, 4], + [121, 4], + [121, 6], + [123, 1], + [123, 3], + [123, 3], + [123, 1], + [123, 3], + [51, 3], + [51, 3], + [51, 3], + [124, 0], + [124, 1], + [78, 2], + [78, 4], + [76, 1], + [76, 1], + [67, 2], + [96, 2], + [96, 3], + [96, 4], + [134, 1], + [134, 1], + [100, 5], + [100, 5], + [106, 3], + [106, 2], + [106, 3], + [106, 2], + [106, 2], + [106, 1], + [128, 1], + [128, 3], + [128, 4], + [128, 4], + [128, 6], + [136, 1], + [136, 1], + [136, 1], + [136, 1], + [132, 1], + [132, 3], + [132, 4], + [132, 4], + [132, 6], + [137, 1], + [137, 2], + [133, 1], + [133, 2], + [131, 1], + [131, 2], + [138, 1], + [139, 1], + [139, 1], + [139, 3], + [139, 3], + [22, 2], + [22, 3], + [22, 4], + [22, 5], + [141, 3], + [141, 3], + [141, 2], + [27, 2], + [27, 4], + [74, 3], + [74, 5], + [147, 2], + [147, 4], + [147, 2], + [147, 4], + [151, 2], + [151, 4], + [151, 4], + [151, 2], + [151, 4], + [151, 4], + [23, 2], + [23, 2], + [23, 2], + [23, 2], + [23, 1], + [152, 2], + [152, 2], + [24, 2], + [24, 2], + [24, 2], + [24, 2], + [154, 2], + [154, 4], + [154, 2], + [155, 4], + [155, 2], + [158, 2], + [158, 3], + [163, 1], + [163, 1], + [163, 1], + [163, 1], + [161, 1], + [161, 3], + [159, 2], + [159, 2], + [159, 4], + [159, 4], + [159, 4], + [159, 4], + [159, 4], + [159, 4], + [159, 6], + [159, 6], + [159, 6], + [159, 6], + [159, 6], + [159, 6], + [159, 6], + [159, 6], + [159, 2], + [159, 4], + [159, 4], + [160, 2], + [160, 2], + [160, 4], + [160, 4], + [160, 4], + [160, 4], + [160, 4], + [160, 4], + [160, 6], + [160, 6], + [160, 6], + [160, 6], + [160, 6], + [160, 6], + [160, 6], + [160, 6], + [160, 2], + [160, 4], + [160, 4], + [25, 5], + [25, 5], + [25, 7], + [25, 7], + [25, 4], + [25, 6], + [168, 1], + [168, 2], + [170, 3], + [170, 4], + [172, 3], + [172, 5], + [21, 1], + [21, 3], + [21, 3], + [21, 3], + [175, 3], + [175, 5], + [30, 1], + [30, 3], + [30, 3], + [30, 3], + [31, 2], + [19, 2], + [19, 2], + [19, 2], + [19, 2], + [19, 2], + [19, 2], + [19, 2], + [19, 2], + [19, 2], + [19, 2], + [19, 3], + [19, 3], + [19, 3], + [19, 3], + [19, 3], + [19, 3], + [19, 3], + [19, 3], + [19, 3], + [19, 3], + [19, 3], + [19, 3], + [19, 3], + [19, 3], + [19, 5], + [19, 4], + ], + performAction: function (e, t, n, r, i, s, o) { + var u = s.length - 1; + switch (i) { + case 1: + return (this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.Block())); + case 2: + return (this.$ = s[u]); + case 3: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(r.Block.wrap([s[u]])); + break; + case 4: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(s[u - 2].push(s[u])); + break; + case 5: + this.$ = s[u - 1]; + break; + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 40: + case 45: + case 47: + case 57: + case 62: + case 63: + case 64: + case 66: + case 67: + case 72: + case 73: + case 74: + case 75: + case 76: + case 97: + case 98: + case 109: + case 110: + case 111: + case 112: + case 118: + case 119: + case 122: + case 127: + case 136: + case 221: + case 222: + case 223: + case 225: + case 237: + case 238: + case 280: + case 281: + case 330: + case 336: + case 342: + this.$ = s[u]; + break; + case 13: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.StatementLiteral(s[u])); + break; + case 31: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )( + new r.Op( + s[u], + new r.Value(new r.Literal("")), + ), + ); + break; + case 32: + case 346: + case 347: + case 348: + case 351: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Op(s[u - 1], s[u])); + break; + case 33: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.Op(s[u - 2].concat(s[u - 1]), s[u])); + break; + case 34: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Block()); + break; + case 35: + case 83: + case 137: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(s[u - 1]); + break; + case 36: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.IdentifierLiteral(s[u])); + break; + case 37: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.CSXTag(s[u])); + break; + case 38: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.PropertyName(s[u])); + break; + case 39: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.NumberLiteral(s[u])); + break; + case 41: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.StringLiteral(s[u])); + break; + case 42: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.StringWithInterpolations(s[u - 1])); + break; + case 43: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.RegexLiteral(s[u])); + break; + case 44: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.RegexWithInterpolations(s[u - 1].args)); + break; + case 46: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.PassthroughLiteral(s[u])); + break; + case 48: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.UndefinedLiteral(s[u])); + break; + case 49: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.NullLiteral(s[u])); + break; + case 50: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.BooleanLiteral(s[u])); + break; + case 51: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.InfinityLiteral(s[u])); + break; + case 52: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.NaNLiteral(s[u])); + break; + case 53: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.Assign(s[u - 2], s[u])); + break; + case 54: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )(new r.Assign(s[u - 3], s[u])); + break; + case 55: + this.$ = r.addDataToNode( + r, + o[u - 4], + o[u], + )(new r.Assign(s[u - 4], s[u - 1])); + break; + case 56: + case 115: + case 120: + case 121: + case 123: + case 124: + case 125: + case 126: + case 128: + case 282: + case 283: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.Value(s[u])); + break; + case 58: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )( + new r.Assign( + r.addDataToNode( + r, + o[u - 2], + )(new r.Value(s[u - 2])), + s[u], + "object", + { + operatorToken: r.addDataToNode( + r, + o[u - 1], + )(new r.Literal(s[u - 1])), + }, + ), + ); + break; + case 59: + this.$ = r.addDataToNode( + r, + o[u - 4], + o[u], + )( + new r.Assign( + r.addDataToNode( + r, + o[u - 4], + )(new r.Value(s[u - 4])), + s[u - 1], + "object", + { + operatorToken: r.addDataToNode( + r, + o[u - 3], + )(new r.Literal(s[u - 3])), + }, + ), + ); + break; + case 60: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )( + new r.Assign( + r.addDataToNode( + r, + o[u - 2], + )(new r.Value(s[u - 2])), + s[u], + null, + { + operatorToken: r.addDataToNode( + r, + o[u - 1], + )(new r.Literal(s[u - 1])), + }, + ), + ); + break; + case 61: + this.$ = r.addDataToNode( + r, + o[u - 4], + o[u], + )( + new r.Assign( + r.addDataToNode( + r, + o[u - 4], + )(new r.Value(s[u - 4])), + s[u - 1], + null, + { + operatorToken: r.addDataToNode( + r, + o[u - 3], + )(new r.Literal(s[u - 3])), + }, + ), + ); + break; + case 65: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )( + new r.Value( + new r.ComputedPropertyName(s[u - 1]), + ), + ); + break; + case 68: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Splat(new r.Value(s[u - 1]))); + break; + case 69: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Splat(new r.Value(s[u]))); + break; + case 70: + case 113: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Splat(s[u - 1])); + break; + case 71: + case 114: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Splat(s[u])); + break; + case 77: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )( + new r.SuperCall( + r.addDataToNode( + r, + o[u - 1], + )(new r.Super()), + s[u], + !1, + s[u - 1], + ), + ); + break; + case 78: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Call(new r.Value(s[u - 1]), s[u])); + break; + case 79: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Call(s[u - 1], s[u])); + break; + case 80: + case 81: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Value(s[u - 1]).add(s[u])); + break; + case 82: + case 131: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Access(s[u])); + break; + case 84: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Return(s[u])); + break; + case 85: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )(new r.Return(new r.Value(s[u - 1]))); + break; + case 86: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.Return()); + break; + case 87: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.YieldReturn(s[u])); + break; + case 88: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.YieldReturn()); + break; + case 89: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.AwaitReturn(s[u])); + break; + case 90: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.AwaitReturn()); + break; + case 91: + this.$ = r.addDataToNode( + r, + o[u - 4], + o[u], + )( + new r.Code( + s[u - 3], + s[u], + s[u - 1], + r.addDataToNode( + r, + o[u - 4], + )(new r.Literal(s[u - 4])), + ), + ); + break; + case 92: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Code([], s[u], s[u - 1])); + break; + case 93: + this.$ = r.addDataToNode( + r, + o[u - 4], + o[u], + )( + new r.Code( + s[u - 3], + r.addDataToNode( + r, + o[u], + )(r.Block.wrap([s[u]])), + s[u - 1], + r.addDataToNode( + r, + o[u - 4], + )(new r.Literal(s[u - 4])), + ), + ); + break; + case 94: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )( + new r.Code( + [], + r.addDataToNode( + r, + o[u], + )(r.Block.wrap([s[u]])), + s[u - 1], + ), + ); + break; + case 95: + case 96: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.FuncGlyph(s[u])); + break; + case 99: + case 142: + case 232: + this.$ = r.addDataToNode(r, o[u], o[u])([]); + break; + case 100: + case 143: + case 162: + case 183: + case 216: + case 230: + case 234: + case 284: + this.$ = r.addDataToNode(r, o[u], o[u])([s[u]]); + break; + case 101: + case 144: + case 163: + case 184: + case 217: + case 226: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(s[u - 2].concat(s[u])); + break; + case 102: + case 145: + case 164: + case 185: + case 218: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )(s[u - 3].concat(s[u])); + break; + case 103: + case 146: + case 166: + case 187: + case 220: + this.$ = r.addDataToNode( + r, + o[u - 5], + o[u], + )(s[u - 5].concat(s[u - 2])); + break; + case 104: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.Param(s[u])); + break; + case 105: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Param(s[u - 1], null, !0)); + break; + case 106: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Param(s[u], null, !0)); + break; + case 107: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.Param(s[u - 2], s[u])); + break; + case 108: + case 224: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.Expansion()); + break; + case 116: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(s[u - 1].add(s[u])); + break; + case 117: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Value(s[u - 1]).add(s[u])); + break; + case 129: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )( + new r.Super( + r.addDataToNode( + r, + o[u], + )(new r.Access(s[u])), + [], + !1, + s[u - 2], + ), + ); + break; + case 130: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )( + new r.Super( + r.addDataToNode( + r, + o[u - 1], + )(new r.Index(s[u - 1])), + [], + !1, + s[u - 3], + ), + ); + break; + case 132: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Access(s[u], "soak")); + break; + case 133: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )([ + r.addDataToNode( + r, + o[u - 1], + )( + new r.Access( + new r.PropertyName("prototype"), + ), + ), + r.addDataToNode( + r, + o[u], + )(new r.Access(s[u])), + ]); + break; + case 134: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )([ + r.addDataToNode( + r, + o[u - 1], + )( + new r.Access( + new r.PropertyName("prototype"), + "soak", + ), + ), + r.addDataToNode( + r, + o[u], + )(new r.Access(s[u])), + ]); + break; + case 135: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )( + new r.Access( + new r.PropertyName("prototype"), + ), + ); + break; + case 138: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(r.extend(s[u], { soak: !0 })); + break; + case 139: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.Index(s[u])); + break; + case 140: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.Slice(s[u])); + break; + case 141: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )(new r.Obj(s[u - 2], s[u - 3].generated)); + break; + case 147: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.Class()); + break; + case 148: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Class(null, null, s[u])); + break; + case 149: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.Class(null, s[u])); + break; + case 150: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )(new r.Class(null, s[u - 1], s[u])); + break; + case 151: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Class(s[u])); + break; + case 152: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.Class(s[u - 1], null, s[u])); + break; + case 153: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )(new r.Class(s[u - 2], s[u])); + break; + case 154: + this.$ = r.addDataToNode( + r, + o[u - 4], + o[u], + )(new r.Class(s[u - 3], s[u - 1], s[u])); + break; + case 155: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.ImportDeclaration(null, s[u])); + break; + case 156: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )( + new r.ImportDeclaration( + new r.ImportClause(s[u - 2], null), + s[u], + ), + ); + break; + case 157: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )( + new r.ImportDeclaration( + new r.ImportClause(null, s[u - 2]), + s[u], + ), + ); + break; + case 158: + this.$ = r.addDataToNode( + r, + o[u - 4], + o[u], + )( + new r.ImportDeclaration( + new r.ImportClause( + null, + new r.ImportSpecifierList([]), + ), + s[u], + ), + ); + break; + case 159: + this.$ = r.addDataToNode( + r, + o[u - 6], + o[u], + )( + new r.ImportDeclaration( + new r.ImportClause( + null, + new r.ImportSpecifierList(s[u - 4]), + ), + s[u], + ), + ); + break; + case 160: + this.$ = r.addDataToNode( + r, + o[u - 5], + o[u], + )( + new r.ImportDeclaration( + new r.ImportClause(s[u - 4], s[u - 2]), + s[u], + ), + ); + break; + case 161: + this.$ = r.addDataToNode( + r, + o[u - 8], + o[u], + )( + new r.ImportDeclaration( + new r.ImportClause( + s[u - 7], + new r.ImportSpecifierList(s[u - 4]), + ), + s[u], + ), + ); + break; + case 165: + case 186: + case 199: + case 219: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )(s[u - 2]); + break; + case 167: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.ImportSpecifier(s[u])); + break; + case 168: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.ImportSpecifier(s[u - 2], s[u])); + break; + case 169: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.ImportSpecifier(new r.Literal(s[u]))); + break; + case 170: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )( + new r.ImportSpecifier( + new r.Literal(s[u - 2]), + s[u], + ), + ); + break; + case 171: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.ImportDefaultSpecifier(s[u])); + break; + case 172: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )( + new r.ImportNamespaceSpecifier( + new r.Literal(s[u - 2]), + s[u], + ), + ); + break; + case 173: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )( + new r.ExportNamedDeclaration( + new r.ExportSpecifierList([]), + ), + ); + break; + case 174: + this.$ = r.addDataToNode( + r, + o[u - 4], + o[u], + )( + new r.ExportNamedDeclaration( + new r.ExportSpecifierList(s[u - 2]), + ), + ); + break; + case 175: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.ExportNamedDeclaration(s[u])); + break; + case 176: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )( + new r.ExportNamedDeclaration( + new r.Assign(s[u - 2], s[u], null, { + moduleDeclaration: "export", + }), + ), + ); + break; + case 177: + this.$ = r.addDataToNode( + r, + o[u - 4], + o[u], + )( + new r.ExportNamedDeclaration( + new r.Assign(s[u - 3], s[u], null, { + moduleDeclaration: "export", + }), + ), + ); + break; + case 178: + this.$ = r.addDataToNode( + r, + o[u - 5], + o[u], + )( + new r.ExportNamedDeclaration( + new r.Assign(s[u - 4], s[u - 1], null, { + moduleDeclaration: "export", + }), + ), + ); + break; + case 179: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.ExportDefaultDeclaration(s[u])); + break; + case 180: + this.$ = r.addDataToNode( + r, + o[u - 4], + o[u], + )( + new r.ExportDefaultDeclaration( + new r.Value(s[u - 1]), + ), + ); + break; + case 181: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )( + new r.ExportAllDeclaration( + new r.Literal(s[u - 2]), + s[u], + ), + ); + break; + case 182: + this.$ = r.addDataToNode( + r, + o[u - 6], + o[u], + )( + new r.ExportNamedDeclaration( + new r.ExportSpecifierList(s[u - 4]), + s[u], + ), + ); + break; + case 188: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.ExportSpecifier(s[u])); + break; + case 189: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.ExportSpecifier(s[u - 2], s[u])); + break; + case 190: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )( + new r.ExportSpecifier( + s[u - 2], + new r.Literal(s[u]), + ), + ); + break; + case 191: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.ExportSpecifier(new r.Literal(s[u]))); + break; + case 192: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )( + new r.ExportSpecifier( + new r.Literal(s[u - 2]), + s[u], + ), + ); + break; + case 193: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )( + new r.TaggedTemplateCall( + s[u - 2], + s[u], + s[u - 1], + ), + ); + break; + case 194: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.Call(s[u - 2], s[u], s[u - 1])); + break; + case 195: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )( + new r.SuperCall( + r.addDataToNode( + r, + o[u - 2], + )(new r.Super()), + s[u], + s[u - 1], + s[u - 2], + ), + ); + break; + case 196: + this.$ = r.addDataToNode(r, o[u], o[u])(!1); + break; + case 197: + this.$ = r.addDataToNode(r, o[u], o[u])(!0); + break; + case 198: + this.$ = r.addDataToNode(r, o[u - 1], o[u])([]); + break; + case 200: + case 201: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.Value(new r.ThisLiteral(s[u]))); + break; + case 202: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )( + new r.Value( + r.addDataToNode( + r, + o[u - 1], + )(new r.ThisLiteral(s[u - 1])), + [ + r.addDataToNode( + r, + o[u], + )(new r.Access(s[u])), + ], + "this", + ), + ); + break; + case 203: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Arr([])); + break; + case 204: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.Arr(s[u - 1])); + break; + case 205: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )(new r.Arr([].concat(s[u - 2], s[u - 1]))); + break; + case 206: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )("inclusive"); + break; + case 207: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )("exclusive"); + break; + case 208: + case 209: + this.$ = r.addDataToNode( + r, + o[u - 4], + o[u], + )(new r.Range(s[u - 3], s[u - 1], s[u - 2])); + break; + case 210: + case 212: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.Range(s[u - 2], s[u], s[u - 1])); + break; + case 211: + case 213: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Range(s[u - 1], null, s[u])); + break; + case 214: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Range(null, s[u], s[u - 1])); + break; + case 215: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.Range(null, null, s[u])); + break; + case 227: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )(s[u - 3].concat(s[u - 2], s[u])); + break; + case 228: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )(s[u - 2].concat(s[u - 1])); + break; + case 229: + this.$ = r.addDataToNode( + r, + o[u - 5], + o[u], + )( + s[u - 5].concat( + s[u - 4], + s[u - 2], + s[u - 1], + ), + ); + break; + case 231: + case 235: + case 331: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(s[u - 1].concat(s[u])); + break; + case 233: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )([].concat(s[u])); + break; + case 236: + this.$ = r.addDataToNode( + r, + o[u], + o[u], + )(new r.Elision()); + break; + case 239: + case 240: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )([].concat(s[u - 2], s[u])); + break; + case 241: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Try(s[u])); + break; + case 242: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.Try(s[u - 1], s[u][0], s[u][1])); + break; + case 243: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )(new r.Try(s[u - 2], null, null, s[u])); + break; + case 244: + this.$ = r.addDataToNode( + r, + o[u - 4], + o[u], + )( + new r.Try( + s[u - 3], + s[u - 2][0], + s[u - 2][1], + s[u], + ), + ); + break; + case 245: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )([s[u - 1], s[u]]); + break; + case 246: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )([ + r.addDataToNode( + r, + o[u - 1], + )(new r.Value(s[u - 1])), + s[u], + ]); + break; + case 247: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )([null, s[u]]); + break; + case 248: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Throw(s[u])); + break; + case 249: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )(new r.Throw(new r.Value(s[u - 1]))); + break; + case 250: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.Parens(s[u - 1])); + break; + case 251: + this.$ = r.addDataToNode( + r, + o[u - 4], + o[u], + )(new r.Parens(s[u - 2])); + break; + case 252: + case 256: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.While(s[u])); + break; + case 253: + case 257: + case 258: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )(new r.While(s[u - 2], { guard: s[u] })); + break; + case 254: + case 259: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.While(s[u], { invert: !0 })); + break; + case 255: + case 260: + case 261: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )( + new r.While(s[u - 2], { + invert: !0, + guard: s[u], + }), + ); + break; + case 262: + case 263: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(s[u - 1].addBody(s[u])); + break; + case 264: + case 265: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )( + s[u].addBody( + r.addDataToNode( + r, + o[u - 1], + )(r.Block.wrap([s[u - 1]])), + ), + ); + break; + case 266: + this.$ = r.addDataToNode(r, o[u], o[u])(s[u]); + break; + case 267: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )( + new r.While( + r.addDataToNode( + r, + o[u - 1], + )(new r.BooleanLiteral("true")), + ).addBody(s[u]), + ); + break; + case 268: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )( + new r.While( + r.addDataToNode( + r, + o[u - 1], + )(new r.BooleanLiteral("true")), + ).addBody( + r.addDataToNode( + r, + o[u], + )(r.Block.wrap([s[u]])), + ), + ); + break; + case 269: + case 270: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.For(s[u - 1], s[u])); + break; + case 271: + case 272: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.For(s[u], s[u - 1])); + break; + case 273: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )({ + source: r.addDataToNode( + r, + o[u], + )(new r.Value(s[u])), + }); + break; + case 274: + case 276: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )({ + source: r.addDataToNode( + r, + o[u - 2], + )(new r.Value(s[u - 2])), + step: s[u], + }); + break; + case 275: + case 277: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )( + (function () { + return ( + (s[u].own = s[u - 1].own), + (s[u].ownTag = s[u - 1].ownTag), + (s[u].name = s[u - 1][0]), + (s[u].index = s[u - 1][1]), + s[u] + ); + })(), + ); + break; + case 278: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(s[u]); + break; + case 279: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )( + (function () { + return ( + (s[u].own = !0), + (s[u].ownTag = r.addDataToNode( + r, + o[u - 1], + )(new r.Literal(s[u - 1]))), + s[u] + ); + })(), + ); + break; + case 285: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )([s[u - 2], s[u]]); + break; + case 286: + case 305: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )({ source: s[u] }); + break; + case 287: + case 306: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )({ source: s[u], object: !0 }); + break; + case 288: + case 289: + case 307: + case 308: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )({ source: s[u - 2], guard: s[u] }); + break; + case 290: + case 291: + case 309: + case 310: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )({ + source: s[u - 2], + guard: s[u], + object: !0, + }); + break; + case 292: + case 293: + case 311: + case 312: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )({ source: s[u - 2], step: s[u] }); + break; + case 294: + case 295: + case 296: + case 297: + case 313: + case 314: + case 315: + case 316: + this.$ = r.addDataToNode( + r, + o[u - 5], + o[u], + )({ + source: s[u - 4], + guard: s[u - 2], + step: s[u], + }); + break; + case 298: + case 299: + case 300: + case 301: + case 317: + case 318: + case 319: + case 320: + this.$ = r.addDataToNode( + r, + o[u - 5], + o[u], + )({ + source: s[u - 4], + step: s[u - 2], + guard: s[u], + }); + break; + case 302: + case 321: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )({ source: s[u], from: !0 }); + break; + case 303: + case 304: + case 322: + case 323: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )({ source: s[u - 2], guard: s[u], from: !0 }); + break; + case 324: + case 325: + this.$ = r.addDataToNode( + r, + o[u - 4], + o[u], + )(new r.Switch(s[u - 3], s[u - 1])); + break; + case 326: + case 327: + this.$ = r.addDataToNode( + r, + o[u - 6], + o[u], + )(new r.Switch(s[u - 5], s[u - 3], s[u - 1])); + break; + case 328: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )(new r.Switch(null, s[u - 1])); + break; + case 329: + this.$ = r.addDataToNode( + r, + o[u - 5], + o[u], + )(new r.Switch(null, s[u - 3], s[u - 1])); + break; + case 332: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )([[s[u - 1], s[u]]]); + break; + case 333: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )([[s[u - 2], s[u - 1]]]); + break; + case 334: + case 340: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.If(s[u - 1], s[u], { type: s[u - 2] })); + break; + case 335: + case 341: + this.$ = r.addDataToNode( + r, + o[u - 4], + o[u], + )( + s[u - 4].addElse( + r.addDataToNode( + r, + o[u - 2], + o[u], + )( + new r.If(s[u - 1], s[u], { + type: s[u - 2], + }), + ), + ), + ); + break; + case 337: + case 343: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(s[u - 2].addElse(s[u])); + break; + case 338: + case 339: + case 344: + case 345: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )( + new r.If( + s[u], + r.addDataToNode( + r, + o[u - 2], + )(r.Block.wrap([s[u - 2]])), + { type: s[u - 1], statement: !0 }, + ), + ); + break; + case 349: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Op("-", s[u])); + break; + case 350: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Op("+", s[u])); + break; + case 352: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Op("--", s[u])); + break; + case 353: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Op("++", s[u])); + break; + case 354: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Op("--", s[u - 1], null, !0)); + break; + case 355: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Op("++", s[u - 1], null, !0)); + break; + case 356: + this.$ = r.addDataToNode( + r, + o[u - 1], + o[u], + )(new r.Existence(s[u - 1])); + break; + case 357: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.Op("+", s[u - 2], s[u])); + break; + case 358: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.Op("-", s[u - 2], s[u])); + break; + case 359: + case 360: + case 361: + case 362: + case 363: + case 364: + case 365: + case 366: + case 367: + case 368: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.Op(s[u - 1], s[u - 2], s[u])); + break; + case 369: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )( + (function () { + return "!" === s[u - 1].charAt(0) + ? new r.Op( + s[u - 1].slice(1), + s[u - 2], + s[u], + ).invert() + : new r.Op( + s[u - 1], + s[u - 2], + s[u], + ); + })(), + ); + break; + case 370: + this.$ = r.addDataToNode( + r, + o[u - 2], + o[u], + )(new r.Assign(s[u - 2], s[u], s[u - 1])); + break; + case 371: + this.$ = r.addDataToNode( + r, + o[u - 4], + o[u], + )(new r.Assign(s[u - 4], s[u - 1], s[u - 3])); + break; + case 372: + this.$ = r.addDataToNode( + r, + o[u - 3], + o[u], + )(new r.Assign(s[u - 3], s[u], s[u - 2])); + } + }, + table: [ + { + 1: [2, 1], + 3: 1, + 4: 2, + 5: 3, + 7: 4, + 8: 5, + 9: 6, + 10: 7, + 11: 27, + 12: 28, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: r, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: w, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { 1: [3] }, + { 1: [2, 2], 6: X }, + t(V, [2, 3]), + t($, [2, 6], { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t($, [2, 7]), + t($, [2, 8], { + 158: 116, + 151: 118, + 154: 119, + 148: J, + 150: K, + 156: Q, + 174: ht, + }), + t($, [2, 9]), + t(pt, [2, 16], { + 124: 120, + 99: 121, + 104: 127, + 45: dt, + 46: dt, + 126: dt, + 80: vt, + 81: mt, + 101: gt, + 102: yt, + 103: bt, + 105: wt, + 125: Et, + }), + t(pt, [2, 17], { + 104: 127, + 99: 130, + 80: vt, + 81: mt, + 101: gt, + 102: yt, + 103: bt, + 105: wt, + }), + t(pt, [2, 18]), + t(pt, [2, 19]), + t(pt, [2, 20]), + t(pt, [2, 21]), + t(pt, [2, 22]), + t(pt, [2, 23]), + t(pt, [2, 24]), + t(pt, [2, 25]), + t(pt, [2, 26]), + t(pt, [2, 27]), + t($, [2, 28]), + t($, [2, 29]), + t($, [2, 30]), + t(St, [2, 12]), + t(St, [2, 13]), + t(St, [2, 14]), + t(St, [2, 15]), + t($, [2, 10]), + t($, [2, 11]), + t(xt, Tt, { 61: [1, 131] }), + t(xt, [2, 123]), + t(xt, [2, 124]), + t(xt, [2, 125]), + t(xt, Nt), + t(xt, [2, 127]), + t(xt, [2, 128]), + t(Ct, kt, { + 87: 132, + 94: 133, + 95: 134, + 37: 136, + 67: 137, + 96: 138, + 73: 139, + 38: i, + 39: s, + 68: Lt, + 70: At, + 107: T, + 130: Ot, + }), + { + 5: 143, + 7: 4, + 8: 5, + 9: 6, + 10: 7, + 11: 27, + 12: 28, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: r, + 34: 142, + 35: Mt, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: w, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 145, + 8: 146, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 150, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 156, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 157, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 158, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: [1, 159], + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 17: 161, + 18: 162, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 163, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 160, + 100: 32, + 107: T, + 129: L, + 130: A, + 145: _, + }, + { + 17: 161, + 18: 162, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 163, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 164, + 100: 32, + 107: T, + 129: L, + 130: A, + 145: _, + }, + t(jt, Ft, { + 180: [1, 165], + 181: [1, 166], + 194: [1, 167], + }), + t(pt, [2, 336], { 169: [1, 168] }), + { 34: 169, 35: Mt }, + { 34: 170, 35: Mt }, + { 34: 171, 35: Mt }, + t(pt, [2, 266]), + { 34: 172, 35: Mt }, + { 34: 173, 35: Mt }, + { + 7: 174, + 8: 175, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 35: [1, 176], + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(It, [2, 147], { + 53: 30, + 74: 31, + 100: 32, + 51: 33, + 76: 34, + 75: 35, + 96: 61, + 73: 62, + 42: 63, + 48: 65, + 37: 78, + 67: 79, + 44: 88, + 89: 152, + 17: 161, + 18: 162, + 60: 163, + 34: 177, + 98: 179, + 35: Mt, + 38: i, + 39: s, + 43: o, + 45: u, + 46: a, + 49: f, + 50: l, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 68: g, + 77: y, + 86: Pt, + 90: S, + 91: x, + 107: T, + 111: [1, 178], + 129: L, + 130: A, + 145: _, + }), + { + 7: 180, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 35: [1, 181], + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t( + [ + 1, 6, 35, 36, 47, 69, 70, 93, 127, 135, 146, + 148, 149, 150, 156, 157, 174, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, + ], + qt, + { + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 13: 23, + 15: 25, + 16: 26, + 60: 29, + 53: 30, + 74: 31, + 100: 32, + 51: 33, + 76: 34, + 75: 35, + 98: 45, + 172: 46, + 151: 48, + 147: 49, + 152: 50, + 154: 51, + 155: 52, + 96: 61, + 73: 62, + 42: 63, + 48: 65, + 37: 78, + 67: 79, + 158: 85, + 44: 88, + 89: 152, + 9: 154, + 7: 182, + 14: n, + 32: _t, + 33: Rt, + 38: i, + 39: s, + 43: o, + 45: u, + 46: a, + 49: f, + 50: l, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 68: g, + 77: y, + 84: [1, 184], + 85: Dt, + 86: Pt, + 90: S, + 91: x, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 153: H, + 167: j, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + ), + t($, [2, 342], { 169: [1, 185] }), + t( + [ + 1, 6, 36, 47, 69, 70, 93, 127, 135, 146, 148, + 149, 150, 156, 157, 174, + ], + Ut, + { + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 13: 23, + 15: 25, + 16: 26, + 60: 29, + 53: 30, + 74: 31, + 100: 32, + 51: 33, + 76: 34, + 75: 35, + 98: 45, + 172: 46, + 151: 48, + 147: 49, + 152: 50, + 154: 51, + 155: 52, + 96: 61, + 73: 62, + 42: 63, + 48: 65, + 37: 78, + 67: 79, + 158: 85, + 44: 88, + 89: 152, + 9: 154, + 7: 186, + 14: n, + 32: _t, + 35: zt, + 38: i, + 39: s, + 43: o, + 45: u, + 46: a, + 49: f, + 50: l, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 68: g, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 90: S, + 91: x, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 153: H, + 167: j, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + ), + { + 37: 192, + 38: i, + 39: s, + 44: 188, + 45: u, + 46: a, + 107: [1, 191], + 113: 189, + 114: 190, + 119: Wt, + }, + { + 26: 195, + 37: 196, + 38: i, + 39: s, + 107: [1, 194], + 110: N, + 118: [1, 197], + 122: [1, 198], + }, + t(jt, [2, 120]), + t(jt, [2, 121]), + t(xt, [2, 45]), + t(xt, [2, 46]), + t(xt, [2, 47]), + t(xt, [2, 48]), + t(xt, [2, 49]), + t(xt, [2, 50]), + t(xt, [2, 51]), + t(xt, [2, 52]), + { + 4: 199, + 5: 3, + 7: 4, + 8: 5, + 9: 6, + 10: 7, + 11: 27, + 12: 28, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: r, + 35: [1, 200], + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: w, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 201, + 8: 202, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 35: Xt, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 69: Vt, + 70: $t, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 93: Jt, + 96: 61, + 97: 211, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 131: 204, + 132: 205, + 136: 210, + 137: 207, + 138: 206, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { 80: Kt, 81: Qt, 124: 213, 125: Et, 126: dt }, + t(xt, [2, 200]), + t(xt, [2, 201], { 40: 216, 41: Gt }), + t(Yt, [2, 95]), + t(Yt, [2, 96]), + t(Zt, [2, 115]), + t(Zt, [2, 118]), + { + 7: 218, + 8: 219, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 220, + 8: 221, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 222, + 8: 223, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 225, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 34: 224, + 35: Mt, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 37: 230, + 38: i, + 39: s, + 67: 231, + 68: g, + 73: 233, + 96: 232, + 100: 226, + 107: T, + 130: Ot, + 161: 227, + 162: en, + 163: 229, + }, + { + 159: 234, + 160: 235, + 164: [1, 236], + 165: [1, 237], + 166: [1, 238], + }, + t([6, 35, 93, 109], tn, { + 44: 88, + 108: 239, + 62: 240, + 63: 241, + 64: 242, + 66: 243, + 42: 244, + 71: 246, + 37: 247, + 40: 248, + 67: 249, + 72: 251, + 73: 252, + 74: 253, + 75: 254, + 76: 255, + 38: i, + 39: s, + 41: Gt, + 43: o, + 45: u, + 46: a, + 68: nn, + 70: rn, + 77: sn, + 107: T, + 129: L, + 130: A, + 145: _, + }), + t(on, [2, 39]), + t(on, [2, 40]), + t(xt, [2, 43]), + { + 17: 161, + 18: 162, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 257, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 163, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 258, + 100: 32, + 107: T, + 129: L, + 130: A, + 145: _, + }, + t(un, [2, 36]), + t(un, [2, 37]), + t(an, [2, 41]), + { + 4: 259, + 5: 3, + 7: 4, + 8: 5, + 9: 6, + 10: 7, + 11: 27, + 12: 28, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: r, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: w, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(V, [2, 5], { + 7: 4, + 8: 5, + 9: 6, + 10: 7, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 13: 23, + 15: 25, + 16: 26, + 11: 27, + 12: 28, + 60: 29, + 53: 30, + 74: 31, + 100: 32, + 51: 33, + 76: 34, + 75: 35, + 89: 37, + 98: 45, + 172: 46, + 151: 48, + 147: 49, + 152: 50, + 154: 51, + 155: 52, + 175: 57, + 96: 61, + 73: 62, + 42: 63, + 48: 65, + 37: 78, + 67: 79, + 158: 85, + 44: 88, + 5: 260, + 14: n, + 32: r, + 38: i, + 39: s, + 43: o, + 45: u, + 46: a, + 49: f, + 50: l, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 68: g, + 77: y, + 84: b, + 85: w, + 86: E, + 90: S, + 91: x, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 148: D, + 150: P, + 153: H, + 156: B, + 167: j, + 173: F, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }), + t(pt, [2, 356]), + { + 7: 261, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 262, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 263, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 264, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 265, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 266, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 267, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 268, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 269, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 270, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 271, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 272, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 273, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 274, + 8: 275, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(pt, [2, 265]), + t(pt, [2, 270]), + { + 7: 220, + 8: 276, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 222, + 8: 277, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 37: 230, + 38: i, + 39: s, + 67: 231, + 68: g, + 73: 233, + 96: 232, + 100: 278, + 107: T, + 130: Ot, + 161: 227, + 162: en, + 163: 229, + }, + { + 159: 234, + 164: [1, 279], + 165: [1, 280], + 166: [1, 281], + }, + { + 7: 282, + 8: 283, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(pt, [2, 264]), + t(pt, [2, 269]), + { 44: 284, 45: u, 46: a, 78: 285, 126: fn }, + t(Zt, [2, 116]), + t(ln, [2, 197]), + { 40: 287, 41: Gt }, + { 40: 288, 41: Gt }, + t(Zt, [2, 135], { 40: 289, 41: Gt }), + { 40: 290, 41: Gt }, + t(Zt, [2, 136]), + { + 7: 292, + 8: 294, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 70: cn, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 82: 291, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 106: 293, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 134: 295, + 135: hn, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { 81: mt, 104: 298, 105: wt }, + t(Zt, [2, 117]), + { + 6: [1, 300], + 7: 299, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 35: [1, 301], + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(pn, dn, { 92: 304, 88: [1, 302], 93: vn }), + t(mn, [2, 100]), + t(mn, [2, 104], { 61: [1, 306], 70: [1, 305] }), + t(mn, [2, 108], { + 37: 136, + 67: 137, + 96: 138, + 73: 139, + 95: 307, + 38: i, + 39: s, + 68: Lt, + 107: T, + 130: Ot, + }), + t(gn, [2, 109]), + t(gn, [2, 110]), + t(gn, [2, 111]), + t(gn, [2, 112]), + { 40: 216, 41: Gt }, + { + 7: 308, + 8: 309, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 35: Xt, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 69: Vt, + 70: $t, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 93: Jt, + 96: 61, + 97: 211, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 131: 204, + 132: 205, + 136: 210, + 137: 207, + 138: 206, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(yn, [2, 92]), + t($, [2, 94]), + { + 4: 311, + 5: 3, + 7: 4, + 8: 5, + 9: 6, + 10: 7, + 11: 27, + 12: 28, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: r, + 36: [1, 310], + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: w, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(bn, wn, { 151: 111, 154: 112, 158: 116, 182: et }), + t($, [2, 346]), + { + 7: 158, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 148: J, + 150: K, + 151: 118, + 154: 119, + 156: Q, + 158: 116, + 174: ht, + }, + t( + [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, + 135, 146, 148, 149, 150, 156, 157, 174, 182, + 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, + ], + qt, + { + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 13: 23, + 15: 25, + 16: 26, + 60: 29, + 53: 30, + 74: 31, + 100: 32, + 51: 33, + 76: 34, + 75: 35, + 98: 45, + 172: 46, + 151: 48, + 147: 49, + 152: 50, + 154: 51, + 155: 52, + 96: 61, + 73: 62, + 42: 63, + 48: 65, + 37: 78, + 67: 79, + 158: 85, + 44: 88, + 89: 152, + 9: 154, + 7: 182, + 14: n, + 32: _t, + 33: Rt, + 38: i, + 39: s, + 43: o, + 45: u, + 46: a, + 49: f, + 50: l, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 68: g, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 90: S, + 91: x, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 153: H, + 167: j, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + ), + t(En, [2, 348], { + 151: 111, + 154: 112, + 158: 116, + 182: et, + 184: nt, + }), + t(Ct, kt, { + 94: 133, + 95: 134, + 37: 136, + 67: 137, + 96: 138, + 73: 139, + 87: 313, + 38: i, + 39: s, + 68: Lt, + 70: At, + 107: T, + 130: Ot, + }), + { 34: 142, 35: Mt }, + { + 7: 314, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 148: J, + 150: K, + 151: 118, + 154: 119, + 156: Q, + 158: 116, + 174: [1, 315], + }, + { + 7: 316, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(En, [2, 349], { + 151: 111, + 154: 112, + 158: 116, + 182: et, + 184: nt, + }), + t(En, [2, 350], { + 151: 111, + 154: 112, + 158: 116, + 182: et, + 184: nt, + }), + t(bn, [2, 351], { + 151: 111, + 154: 112, + 158: 116, + 182: et, + }), + t($, [2, 90], { + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 13: 23, + 15: 25, + 16: 26, + 60: 29, + 53: 30, + 74: 31, + 100: 32, + 51: 33, + 76: 34, + 75: 35, + 98: 45, + 172: 46, + 151: 48, + 147: 49, + 152: 50, + 154: 51, + 155: 52, + 96: 61, + 73: 62, + 42: 63, + 48: 65, + 37: 78, + 67: 79, + 158: 85, + 44: 88, + 89: 152, + 9: 154, + 7: 317, + 14: n, + 32: _t, + 38: i, + 39: s, + 43: o, + 45: u, + 46: a, + 49: f, + 50: l, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 68: g, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 90: S, + 91: x, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 148: Ut, + 150: Ut, + 156: Ut, + 174: Ut, + 153: H, + 167: j, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }), + t(pt, [2, 352], { + 45: Ft, + 46: Ft, + 80: Ft, + 81: Ft, + 101: Ft, + 102: Ft, + 103: Ft, + 105: Ft, + 125: Ft, + 126: Ft, + }), + t(ln, dt, { + 124: 120, + 99: 121, + 104: 127, + 80: vt, + 81: mt, + 101: gt, + 102: yt, + 103: bt, + 105: wt, + 125: Et, + }), + { + 80: vt, + 81: mt, + 99: 130, + 101: gt, + 102: yt, + 103: bt, + 104: 127, + 105: wt, + }, + t(Sn, Tt), + t(pt, [2, 353], { + 45: Ft, + 46: Ft, + 80: Ft, + 81: Ft, + 101: Ft, + 102: Ft, + 103: Ft, + 105: Ft, + 125: Ft, + 126: Ft, + }), + t(pt, [2, 354]), + t(pt, [2, 355]), + { + 6: [1, 320], + 7: 318, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 35: [1, 319], + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { 34: 321, 35: Mt, 173: [1, 322] }, + t(pt, [2, 241], { + 141: 323, + 142: [1, 324], + 143: [1, 325], + }), + t(pt, [2, 262]), + t(pt, [2, 263]), + t(pt, [2, 271]), + t(pt, [2, 272]), + { + 35: [1, 326], + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [1, 327] }, + { 168: 328, 170: 329, 171: xn }, + t(pt, [2, 148]), + { + 7: 331, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(It, [2, 151], { + 34: 332, + 35: Mt, + 45: Ft, + 46: Ft, + 80: Ft, + 81: Ft, + 101: Ft, + 102: Ft, + 103: Ft, + 105: Ft, + 125: Ft, + 126: Ft, + 111: [1, 333], + }), + t(Tn, [2, 248], { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { 73: 334, 107: T }, + t(Tn, [2, 32], { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { + 7: 335, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t( + [1, 6, 36, 47, 69, 70, 93, 127, 135, 146, 149, 157], + [2, 88], + { + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 13: 23, + 15: 25, + 16: 26, + 60: 29, + 53: 30, + 74: 31, + 100: 32, + 51: 33, + 76: 34, + 75: 35, + 98: 45, + 172: 46, + 151: 48, + 147: 49, + 152: 50, + 154: 51, + 155: 52, + 96: 61, + 73: 62, + 42: 63, + 48: 65, + 37: 78, + 67: 79, + 158: 85, + 44: 88, + 89: 152, + 9: 154, + 7: 336, + 14: n, + 32: _t, + 35: zt, + 38: i, + 39: s, + 43: o, + 45: u, + 46: a, + 49: f, + 50: l, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 68: g, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 90: S, + 91: x, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 148: Ut, + 150: Ut, + 156: Ut, + 174: Ut, + 153: H, + 167: j, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + ), + { 34: 337, 35: Mt, 173: [1, 338] }, + t(St, Nn, { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { 73: 339, 107: T }, + t(St, [2, 155]), + { 33: [1, 340], 93: [1, 341] }, + { 33: [1, 342] }, + { + 35: Cn, + 37: 347, + 38: i, + 39: s, + 109: [1, 343], + 115: 344, + 116: 345, + 118: kn, + }, + t([33, 93], [2, 171]), + { 117: [1, 349] }, + { + 35: Ln, + 37: 354, + 38: i, + 39: s, + 109: [1, 350], + 118: An, + 121: 351, + 123: 352, + }, + t(St, [2, 175]), + { 61: [1, 356] }, + { + 7: 357, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 35: [1, 358], + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { 33: [1, 359] }, + { 6: X, 146: [1, 360] }, + { + 4: 361, + 5: 3, + 7: 4, + 8: 5, + 9: 6, + 10: 7, + 11: 27, + 12: 28, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: r, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: w, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(On, Mn, { + 151: 111, + 154: 112, + 158: 116, + 134: 362, + 70: [1, 363], + 135: hn, + 148: J, + 150: K, + 156: Q, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(On, _n, { 134: 364, 70: cn, 135: hn }), + t(Dn, [2, 203]), + { + 7: 308, + 8: 309, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 69: [1, 365], + 70: $t, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 93: Jt, + 96: 61, + 97: 211, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 136: 367, + 138: 366, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t([6, 35, 69], dn, { 133: 368, 92: 370, 93: Pn }), + t(Hn, [2, 234]), + t(Bn, [2, 225]), + { + 7: 308, + 8: 309, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 35: Xt, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 70: $t, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 93: Jt, + 96: 61, + 97: 211, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 131: 372, + 132: 371, + 136: 210, + 137: 207, + 138: 206, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(Hn, [2, 236]), + t(Bn, [2, 230]), + t(jn, [2, 223]), + t(jn, [2, 224], { + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 13: 23, + 15: 25, + 16: 26, + 60: 29, + 53: 30, + 74: 31, + 100: 32, + 51: 33, + 76: 34, + 75: 35, + 98: 45, + 172: 46, + 151: 48, + 147: 49, + 152: 50, + 154: 51, + 155: 52, + 96: 61, + 73: 62, + 42: 63, + 48: 65, + 37: 78, + 67: 79, + 158: 85, + 44: 88, + 89: 152, + 9: 154, + 7: 373, + 14: n, + 32: _t, + 38: i, + 39: s, + 43: o, + 45: u, + 46: a, + 49: f, + 50: l, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 68: g, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 90: S, + 91: x, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 148: D, + 150: P, + 153: H, + 156: B, + 167: j, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }), + { 78: 374, 126: fn }, + { 40: 375, 41: Gt }, + { + 7: 376, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(Fn, [2, 202]), + t(Fn, [2, 38]), + { + 34: 377, + 35: Mt, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 34: 378, 35: Mt }, + t(In, [2, 256], { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 149: [1, 379], + 150: K, + 156: Q, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { 35: [2, 252], 149: [1, 380] }, + t(In, [2, 259], { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 149: [1, 381], + 150: K, + 156: Q, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { 35: [2, 254], 149: [1, 382] }, + t(pt, [2, 267]), + t(qn, [2, 268], { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { 35: Rn, 157: [1, 383] }, + t(Un, [2, 278]), + { + 37: 230, + 38: i, + 39: s, + 67: 231, + 68: Lt, + 73: 233, + 96: 232, + 107: T, + 130: Ot, + 161: 384, + 163: 229, + }, + t(Un, [2, 284], { 93: [1, 385] }), + t(zn, [2, 280]), + t(zn, [2, 281]), + t(zn, [2, 282]), + t(zn, [2, 283]), + t(pt, [2, 275]), + { 35: [2, 277] }, + { + 7: 386, + 8: 387, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 388, + 8: 389, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 390, + 8: 391, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(Wn, dn, { 92: 392, 93: Xn }), + t(Vn, [2, 143]), + t(Vn, [2, 56], { 65: [1, 394] }), + t(Vn, [2, 57]), + t($n, [2, 66], { + 78: 397, + 79: 398, + 61: [1, 395], + 70: [1, 396], + 80: Jn, + 81: Kn, + 126: fn, + }), + t($n, [2, 67]), + { + 37: 247, + 38: i, + 39: s, + 40: 248, + 41: Gt, + 66: 401, + 67: 249, + 68: nn, + 71: 402, + 72: 251, + 73: 252, + 74: 253, + 75: 254, + 76: 255, + 77: sn, + 107: T, + 129: L, + 130: A, + 145: _, + }, + { + 70: [1, 403], + 78: 404, + 79: 405, + 80: Jn, + 81: Kn, + 126: fn, + }, + t(Qn, [2, 62]), + t(Qn, [2, 63]), + t(Qn, [2, 64]), + { + 7: 406, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(Gn, [2, 72]), + t(Gn, [2, 73]), + t(Gn, [2, 74]), + t(Gn, [2, 75]), + t(Gn, [2, 76]), + { 78: 407, 80: Kt, 81: Qt, 126: fn }, + t(Sn, Nt, { 52: [1, 408] }), + t(Sn, Ft), + { 6: X, 47: [1, 409] }, + t(V, [2, 4]), + t(Yn, [2, 357], { + 151: 111, + 154: 112, + 158: 116, + 182: et, + 183: tt, + 184: nt, + }), + t(Yn, [2, 358], { + 151: 111, + 154: 112, + 158: 116, + 182: et, + 183: tt, + 184: nt, + }), + t(En, [2, 359], { + 151: 111, + 154: 112, + 158: 116, + 182: et, + 184: nt, + }), + t(En, [2, 360], { + 151: 111, + 154: 112, + 158: 116, + 182: et, + 184: nt, + }), + t( + [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, + 135, 146, 148, 149, 150, 156, 157, 174, 185, + 186, 187, 188, 189, 190, 191, 192, 193, + ], + [2, 361], + { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + }, + ), + t( + [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, + 135, 146, 148, 149, 150, 156, 157, 174, 186, + 187, 188, 189, 190, 191, 192, + ], + [2, 362], + { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 193: ct, + }, + ), + t( + [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, + 135, 146, 148, 149, 150, 156, 157, 174, 187, + 188, 189, 190, 191, 192, + ], + [2, 363], + { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 193: ct, + }, + ), + t( + [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, + 135, 146, 148, 149, 150, 156, 157, 174, 188, + 189, 190, 191, 192, + ], + [2, 364], + { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 193: ct, + }, + ), + t( + [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, + 135, 146, 148, 149, 150, 156, 157, 174, 189, + 190, 191, 192, + ], + [2, 365], + { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 193: ct, + }, + ), + t( + [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, + 135, 146, 148, 149, 150, 156, 157, 174, 190, + 191, 192, + ], + [2, 366], + { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 193: ct, + }, + ), + t( + [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, + 135, 146, 148, 149, 150, 156, 157, 174, 191, + 192, + ], + [2, 367], + { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 193: ct, + }, + ), + t( + [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, + 135, 146, 148, 149, 150, 156, 157, 174, 192, + ], + [2, 368], + { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 193: ct, + }, + ), + t( + [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, + 135, 146, 148, 149, 150, 156, 157, 174, 186, + 187, 188, 189, 190, 191, 192, 193, + ], + [2, 369], + { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + }, + ), + t(qn, Zn, { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t($, [2, 345]), + { 149: [1, 410] }, + { 149: [1, 411] }, + t( + [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, + 135, 146, 148, 149, 150, 156, 174, 178, 179, + 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 192, 193, + ], + Rn, + { 157: [1, 412] }, + ), + { + 7: 413, + 8: 414, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 415, + 8: 416, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 417, + 8: 418, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(qn, er, { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t($, [2, 344]), + t(tr, [2, 193]), + t(tr, [2, 194]), + { + 7: 308, + 8: 309, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 35: nr, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 70: $t, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 97: 211, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 127: [1, 419], + 128: 420, + 129: L, + 130: A, + 136: 421, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(Zt, [2, 131]), + t(Zt, [2, 132]), + t(Zt, [2, 133]), + t(Zt, [2, 134]), + { 83: [1, 423] }, + { + 70: cn, + 83: [2, 139], + 134: 424, + 135: hn, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 83: [2, 140] }, + { 70: cn, 134: 425, 135: hn }, + { + 7: 426, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 83: [2, 215], + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(rr, [2, 206]), + t(rr, ir), + t(Zt, [2, 138]), + t(Tn, [2, 53], { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { + 7: 427, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 428, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { 89: 429, 90: S, 91: x }, + t(sr, or, { + 95: 134, + 37: 136, + 67: 137, + 96: 138, + 73: 139, + 94: 430, + 38: i, + 39: s, + 68: Lt, + 70: At, + 107: T, + 130: Ot, + }), + { 6: ur, 35: ar }, + t(mn, [2, 105]), + { + 7: 433, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(mn, [2, 106]), + t(jn, Mn, { + 151: 111, + 154: 112, + 158: 116, + 70: [1, 434], + 148: J, + 150: K, + 156: Q, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(jn, _n), + t(fr, [2, 34]), + { 6: X, 36: [1, 435] }, + { + 7: 436, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(pn, dn, { 92: 304, 88: [1, 437], 93: vn }), + t(bn, wn, { 151: 111, 154: 112, 158: 116, 182: et }), + { + 7: 438, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 34: 377, + 35: Mt, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + t($, [2, 89], { + 151: 111, + 154: 112, + 158: 116, + 148: Nn, + 150: Nn, + 156: Nn, + 174: Nn, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(Tn, [2, 370], { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { + 7: 439, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 440, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(pt, [2, 337]), + { + 7: 441, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(pt, [2, 242], { 142: [1, 442] }), + { 34: 443, 35: Mt }, + { + 34: 446, + 35: Mt, + 37: 444, + 38: i, + 39: s, + 73: 445, + 107: T, + }, + { 168: 447, 170: 329, 171: xn }, + { 168: 448, 170: 329, 171: xn }, + { 36: [1, 449], 169: [1, 450], 170: 451, 171: xn }, + t(cr, [2, 330]), + { + 7: 453, + 8: 454, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 139: 452, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(hr, [2, 149], { + 151: 111, + 154: 112, + 158: 116, + 34: 455, + 35: Mt, + 148: J, + 150: K, + 156: Q, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(pt, [2, 152]), + { + 7: 456, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { 36: [1, 457] }, + t(Tn, [2, 33], { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t($, [2, 87], { + 151: 111, + 154: 112, + 158: 116, + 148: Nn, + 150: Nn, + 156: Nn, + 174: Nn, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t($, [2, 343]), + { + 7: 459, + 8: 458, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { 36: [1, 460] }, + { 44: 461, 45: u, 46: a }, + { 107: [1, 463], 114: 462, 119: Wt }, + { 44: 464, 45: u, 46: a }, + { 33: [1, 465] }, + t(Wn, dn, { 92: 466, 93: pr }), + t(Vn, [2, 162]), + { + 35: Cn, + 37: 347, + 38: i, + 39: s, + 115: 468, + 116: 345, + 118: kn, + }, + t(Vn, [2, 167], { 117: [1, 469] }), + t(Vn, [2, 169], { 117: [1, 470] }), + { 37: 471, 38: i, 39: s }, + t(St, [2, 173]), + t(Wn, dn, { 92: 472, 93: dr }), + t(Vn, [2, 183]), + { + 35: Ln, + 37: 354, + 38: i, + 39: s, + 118: An, + 121: 474, + 123: 352, + }, + t(Vn, [2, 188], { 117: [1, 475] }), + t(Vn, [2, 191], { 117: [1, 476] }), + { + 6: [1, 478], + 7: 477, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 35: [1, 479], + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(vr, [2, 179], { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { 73: 480, 107: T }, + { 44: 481, 45: u, 46: a }, + t(xt, [2, 250]), + { 6: X, 36: [1, 482] }, + { + 7: 483, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t( + [ + 14, 32, 38, 39, 43, 45, 46, 49, 50, 54, 55, 56, + 57, 58, 59, 68, 77, 84, 85, 86, 90, 91, 107, + 110, 112, 120, 129, 130, 140, 144, 145, 148, + 150, 153, 156, 167, 173, 176, 177, 178, 179, + 180, 181, + ], + ir, + { 6: mr, 35: mr, 69: mr, 93: mr }, + ), + { + 7: 484, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(Dn, [2, 204]), + t(Hn, [2, 235]), + t(Bn, [2, 231]), + { 6: gr, 35: yr, 69: [1, 485] }, + t(br, or, { + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 13: 23, + 15: 25, + 16: 26, + 60: 29, + 53: 30, + 74: 31, + 100: 32, + 51: 33, + 76: 34, + 75: 35, + 89: 37, + 98: 45, + 172: 46, + 151: 48, + 147: 49, + 152: 50, + 154: 51, + 155: 52, + 175: 57, + 96: 61, + 73: 62, + 42: 63, + 48: 65, + 37: 78, + 67: 79, + 158: 85, + 44: 88, + 9: 148, + 138: 206, + 136: 210, + 97: 211, + 7: 308, + 8: 309, + 137: 488, + 131: 489, + 14: n, + 32: _t, + 38: i, + 39: s, + 43: o, + 45: u, + 46: a, + 49: f, + 50: l, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 68: g, + 70: $t, + 77: y, + 84: b, + 85: Dt, + 86: E, + 90: S, + 91: x, + 93: Jt, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 148: D, + 150: P, + 153: H, + 156: B, + 167: j, + 173: F, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }), + t(br, [2, 232]), + t(sr, dn, { 92: 370, 133: 490, 93: Pn }), + { + 7: 308, + 8: 309, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 70: $t, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 93: Jt, + 96: 61, + 97: 211, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 136: 367, + 138: 366, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(jn, [2, 114], { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(tr, [2, 195]), + t(xt, [2, 129]), + { + 83: [1, 491], + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + t(wr, [2, 334]), + t(Er, [2, 340]), + { + 7: 492, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 493, + 8: 494, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 495, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 496, + 8: 497, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 498, + 8: 499, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(Un, [2, 279]), + { + 37: 230, + 38: i, + 39: s, + 67: 231, + 68: Lt, + 73: 233, + 96: 232, + 107: T, + 130: Ot, + 163: 500, + }, + { + 35: Sr, + 148: J, + 149: [1, 501], + 150: K, + 151: 111, + 154: 112, + 156: Q, + 157: [1, 502], + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 305], 149: [1, 503], 157: [1, 504] }, + { + 35: xr, + 148: J, + 149: [1, 505], + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 306], 149: [1, 506] }, + { + 35: Tr, + 148: J, + 149: [1, 507], + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 321], 149: [1, 508] }, + { 6: Nr, 35: Cr, 109: [1, 509] }, + t(kr, or, { + 44: 88, + 63: 241, + 64: 242, + 66: 243, + 42: 244, + 71: 246, + 37: 247, + 40: 248, + 67: 249, + 72: 251, + 73: 252, + 74: 253, + 75: 254, + 76: 255, + 62: 512, + 38: i, + 39: s, + 41: Gt, + 43: o, + 45: u, + 46: a, + 68: nn, + 70: rn, + 77: sn, + 107: T, + 129: L, + 130: A, + 145: _, + }), + { + 7: 513, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 35: [1, 514], + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 515, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 35: [1, 516], + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(Vn, [2, 68]), + t(Gn, [2, 78]), + t(Gn, [2, 80]), + { 40: 517, 41: Gt }, + { + 7: 292, + 8: 294, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 70: cn, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 82: 518, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 106: 293, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 134: 295, + 135: hn, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(Vn, [2, 69], { + 78: 397, + 79: 398, + 80: Jn, + 81: Kn, + 126: fn, + }), + t(Vn, [2, 71], { + 78: 404, + 79: 405, + 80: Jn, + 81: Kn, + 126: fn, + }), + t(Vn, [2, 70]), + t(Gn, [2, 79]), + t(Gn, [2, 81]), + { + 69: [1, 519], + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + t(Gn, [2, 77]), + t(xt, [2, 44]), + t(an, [2, 42]), + { + 7: 520, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 521, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 522, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t( + [ + 1, 6, 35, 36, 47, 69, 70, 83, 88, 93, 109, 127, + 135, 146, 148, 150, 156, 174, + ], + Sr, + { + 151: 111, + 154: 112, + 158: 116, + 149: [1, 523], + 157: [1, 524], + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + ), + { 149: [1, 525], 157: [1, 526] }, + t(Lr, xr, { + 151: 111, + 154: 112, + 158: 116, + 149: [1, 527], + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { 149: [1, 528] }, + t(Lr, Tr, { + 151: 111, + 154: 112, + 158: 116, + 149: [1, 529], + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { 149: [1, 530] }, + t(tr, [2, 198]), + t([6, 35, 127], dn, { 92: 531, 93: Ar }), + t(Or, [2, 216]), + { + 7: 308, + 8: 309, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 35: nr, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 70: $t, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 97: 211, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 128: 533, + 129: L, + 130: A, + 136: 421, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(Zt, [2, 137]), + { + 7: 534, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 83: [2, 211], + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 535, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 83: [2, 213], + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 83: [2, 214], + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + t(Tn, [2, 54], { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { + 36: [1, 536], + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { + 5: 538, + 7: 4, + 8: 5, + 9: 6, + 10: 7, + 11: 27, + 12: 28, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: r, + 34: 537, + 35: Mt, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: w, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(mn, [2, 101]), + { + 37: 136, + 38: i, + 39: s, + 67: 137, + 68: Lt, + 70: At, + 73: 139, + 94: 539, + 95: 134, + 96: 138, + 107: T, + 130: Ot, + }, + t(Mr, kt, { + 94: 133, + 95: 134, + 37: 136, + 67: 137, + 96: 138, + 73: 139, + 87: 540, + 38: i, + 39: s, + 68: Lt, + 70: At, + 107: T, + 130: Ot, + }), + t(mn, [2, 107], { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(jn, mr), + t(fr, [2, 35]), + t(qn, Zn, { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { 89: 541, 90: S, 91: x }, + t(qn, er, { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { + 36: [1, 542], + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + t(Tn, [2, 372], { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { + 34: 543, + 35: Mt, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 34: 544, 35: Mt }, + t(pt, [2, 243]), + { 34: 545, 35: Mt }, + { 34: 546, 35: Mt }, + t(_r, [2, 247]), + { 36: [1, 547], 169: [1, 548], 170: 451, 171: xn }, + { 36: [1, 549], 169: [1, 550], 170: 451, 171: xn }, + t(pt, [2, 328]), + { 34: 551, 35: Mt }, + t(cr, [2, 331]), + { 34: 552, 35: Mt, 93: [1, 553] }, + t(Dr, [2, 237], { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(Dr, [2, 238]), + t(pt, [2, 150]), + t(hr, [2, 153], { + 151: 111, + 154: 112, + 158: 116, + 34: 554, + 35: Mt, + 148: J, + 150: K, + 156: Q, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(pt, [2, 249]), + { 34: 555, 35: Mt }, + { + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + t(St, [2, 85]), + t(St, [2, 156]), + { 33: [1, 556] }, + { + 35: Cn, + 37: 347, + 38: i, + 39: s, + 115: 557, + 116: 345, + 118: kn, + }, + t(St, [2, 157]), + { 44: 558, 45: u, 46: a }, + { 6: Pr, 35: Hr, 109: [1, 559] }, + t(kr, or, { 37: 347, 116: 562, 38: i, 39: s, 118: kn }), + t(sr, dn, { 92: 563, 93: pr }), + { 37: 564, 38: i, 39: s }, + { 37: 565, 38: i, 39: s }, + { 33: [2, 172] }, + { 6: Br, 35: jr, 109: [1, 566] }, + t(kr, or, { 37: 354, 123: 569, 38: i, 39: s, 118: An }), + t(sr, dn, { 92: 570, 93: dr }), + { 37: 571, 38: i, 39: s, 118: [1, 572] }, + { 37: 573, 38: i, 39: s }, + t(vr, [2, 176], { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { + 7: 574, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 575, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { 36: [1, 576] }, + t(St, [2, 181]), + { 146: [1, 577] }, + { + 69: [1, 578], + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { + 69: [1, 579], + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + t(Dn, [2, 205]), + { + 7: 308, + 8: 309, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 70: $t, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 93: Jt, + 96: 61, + 97: 211, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 131: 372, + 136: 210, + 137: 580, + 138: 206, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 308, + 8: 309, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 35: Xt, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 70: $t, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 93: Jt, + 96: 61, + 97: 211, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 131: 372, + 132: 581, + 136: 210, + 137: 207, + 138: 206, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(Bn, [2, 226]), + t(br, [2, 233], { + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 13: 23, + 15: 25, + 16: 26, + 60: 29, + 53: 30, + 74: 31, + 100: 32, + 51: 33, + 76: 34, + 75: 35, + 89: 37, + 98: 45, + 172: 46, + 151: 48, + 147: 49, + 152: 50, + 154: 51, + 155: 52, + 175: 57, + 96: 61, + 73: 62, + 42: 63, + 48: 65, + 37: 78, + 67: 79, + 158: 85, + 44: 88, + 9: 148, + 97: 211, + 7: 308, + 8: 309, + 138: 366, + 136: 367, + 14: n, + 32: _t, + 38: i, + 39: s, + 43: o, + 45: u, + 46: a, + 49: f, + 50: l, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 68: g, + 70: $t, + 77: y, + 84: b, + 85: Dt, + 86: E, + 90: S, + 91: x, + 93: Jt, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 148: D, + 150: P, + 153: H, + 156: B, + 167: j, + 173: F, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }), + { 6: gr, 35: yr, 36: [1, 582] }, + t(xt, [2, 130]), + t(qn, [2, 257], { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { + 35: Fr, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 253] }, + t(qn, [2, 260], { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { + 35: Ir, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 255] }, + { + 35: qr, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 276] }, + t(Un, [2, 285]), + { + 7: 583, + 8: 584, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 585, + 8: 586, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 587, + 8: 588, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 589, + 8: 590, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 591, + 8: 592, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 593, + 8: 594, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 595, + 8: 596, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 597, + 8: 598, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(Dn, [2, 141]), + { + 37: 247, + 38: i, + 39: s, + 40: 248, + 41: Gt, + 42: 244, + 43: o, + 44: 88, + 45: u, + 46: a, + 62: 599, + 63: 241, + 64: 242, + 66: 243, + 67: 249, + 68: nn, + 70: rn, + 71: 246, + 72: 251, + 73: 252, + 74: 253, + 75: 254, + 76: 255, + 77: sn, + 107: T, + 129: L, + 130: A, + 145: _, + }, + t(Mr, tn, { + 44: 88, + 62: 240, + 63: 241, + 64: 242, + 66: 243, + 42: 244, + 71: 246, + 37: 247, + 40: 248, + 67: 249, + 72: 251, + 73: 252, + 74: 253, + 75: 254, + 76: 255, + 108: 600, + 38: i, + 39: s, + 41: Gt, + 43: o, + 45: u, + 46: a, + 68: nn, + 70: rn, + 77: sn, + 107: T, + 129: L, + 130: A, + 145: _, + }), + t(Vn, [2, 144]), + t(Vn, [2, 58], { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { + 7: 601, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(Vn, [2, 60], { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { + 7: 602, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(Gn, [2, 82]), + { 83: [1, 603] }, + t(Qn, [2, 65]), + t(qn, Fr, { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(qn, Ir, { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(qn, qr, { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { + 7: 604, + 8: 605, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 606, + 8: 607, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 608, + 8: 609, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 610, + 8: 611, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 612, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 613, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 614, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 615, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { 6: Rr, 35: Ur, 127: [1, 616] }, + t([6, 35, 36, 127], or, { + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 13: 23, + 15: 25, + 16: 26, + 60: 29, + 53: 30, + 74: 31, + 100: 32, + 51: 33, + 76: 34, + 75: 35, + 89: 37, + 98: 45, + 172: 46, + 151: 48, + 147: 49, + 152: 50, + 154: 51, + 155: 52, + 175: 57, + 96: 61, + 73: 62, + 42: 63, + 48: 65, + 37: 78, + 67: 79, + 158: 85, + 44: 88, + 9: 148, + 97: 211, + 7: 308, + 8: 309, + 136: 619, + 14: n, + 32: _t, + 38: i, + 39: s, + 43: o, + 45: u, + 46: a, + 49: f, + 50: l, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 68: g, + 70: $t, + 77: y, + 84: b, + 85: Dt, + 86: E, + 90: S, + 91: x, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 148: D, + 150: P, + 153: H, + 156: B, + 167: j, + 173: F, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }), + t(sr, dn, { 92: 620, 93: Ar }), + { + 83: [2, 210], + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { + 83: [2, 212], + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + t(pt, [2, 55]), + t(yn, [2, 91]), + t($, [2, 93]), + t(mn, [2, 102]), + t(sr, dn, { 92: 621, 93: vn }), + { 34: 537, 35: Mt }, + t(pt, [2, 371]), + t(wr, [2, 335]), + t(pt, [2, 244]), + t(_r, [2, 245]), + t(_r, [2, 246]), + t(pt, [2, 324]), + { 34: 622, 35: Mt }, + t(pt, [2, 325]), + { 34: 623, 35: Mt }, + { 36: [1, 624] }, + t(cr, [2, 332], { 6: [1, 625] }), + { + 7: 626, + 8: 627, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(pt, [2, 154]), + t(Er, [2, 341]), + { 44: 628, 45: u, 46: a }, + t(Wn, dn, { 92: 629, 93: pr }), + t(St, [2, 158]), + { 33: [1, 630] }, + { 37: 347, 38: i, 39: s, 116: 631, 118: kn }, + { + 35: Cn, + 37: 347, + 38: i, + 39: s, + 115: 632, + 116: 345, + 118: kn, + }, + t(Vn, [2, 163]), + { 6: Pr, 35: Hr, 36: [1, 633] }, + t(Vn, [2, 168]), + t(Vn, [2, 170]), + t(St, [2, 174], { 33: [1, 634] }), + { 37: 354, 38: i, 39: s, 118: An, 123: 635 }, + { + 35: Ln, + 37: 354, + 38: i, + 39: s, + 118: An, + 121: 636, + 123: 352, + }, + t(Vn, [2, 184]), + { 6: Br, 35: jr, 36: [1, 637] }, + t(Vn, [2, 189]), + t(Vn, [2, 190]), + t(Vn, [2, 192]), + t(vr, [2, 177], { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { + 36: [1, 638], + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + t(St, [2, 180]), + t(xt, [2, 251]), + t(xt, [2, 208]), + t(xt, [2, 209]), + t(Bn, [2, 227]), + t(sr, dn, { 92: 370, 133: 639, 93: Pn }), + t(Bn, [2, 228]), + { + 35: zr, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 157: [1, 640], + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 307], 157: [1, 641] }, + { + 35: Wr, + 148: J, + 149: [1, 642], + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 311], 149: [1, 643] }, + { + 35: Xr, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 157: [1, 644], + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 308], 157: [1, 645] }, + { + 35: Vr, + 148: J, + 149: [1, 646], + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 312], 149: [1, 647] }, + { + 35: $r, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 309] }, + { + 35: Jr, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 310] }, + { + 35: Kr, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 322] }, + { + 35: Qr, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 323] }, + t(Vn, [2, 145]), + t(sr, dn, { 92: 648, 93: Xn }), + { + 36: [1, 649], + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { + 36: [1, 650], + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: lr, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + t(Gn, [2, 83]), + t(Gr, zr, { + 151: 111, + 154: 112, + 158: 116, + 157: [1, 651], + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { 157: [1, 652] }, + t(Lr, Wr, { + 151: 111, + 154: 112, + 158: 116, + 149: [1, 653], + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { 149: [1, 654] }, + t(Gr, Xr, { + 151: 111, + 154: 112, + 158: 116, + 157: [1, 655], + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { 157: [1, 656] }, + t(Lr, Vr, { + 151: 111, + 154: 112, + 158: 116, + 149: [1, 657], + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { 149: [1, 658] }, + t(Tn, $r, { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(Tn, Jr, { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(Tn, Kr, { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(Tn, Qr, { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(tr, [2, 199]), + { + 7: 308, + 8: 309, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 70: $t, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 97: 211, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 136: 659, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 308, + 8: 309, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 35: nr, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 70: $t, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 97: 211, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 128: 660, + 129: L, + 130: A, + 136: 421, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(Or, [2, 217]), + { 6: Rr, 35: Ur, 36: [1, 661] }, + { 6: ur, 35: ar, 36: [1, 662] }, + { 36: [1, 663] }, + { 36: [1, 664] }, + t(pt, [2, 329]), + t(cr, [2, 333]), + t(Dr, [2, 239], { + 151: 111, + 154: 112, + 158: 116, + 148: J, + 150: K, + 156: Q, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(Dr, [2, 240]), + t(St, [2, 160]), + { 6: Pr, 35: Hr, 109: [1, 665] }, + { 44: 666, 45: u, 46: a }, + t(Vn, [2, 164]), + t(sr, dn, { 92: 667, 93: pr }), + t(Vn, [2, 165]), + { 44: 668, 45: u, 46: a }, + t(Vn, [2, 185]), + t(sr, dn, { 92: 669, 93: dr }), + t(Vn, [2, 186]), + t(St, [2, 178]), + { 6: gr, 35: yr, 36: [1, 670] }, + { + 7: 671, + 8: 672, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 673, + 8: 674, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 675, + 8: 676, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 677, + 8: 678, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 679, + 8: 680, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 681, + 8: 682, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 683, + 8: 684, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 685, + 8: 686, + 9: 148, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 29: 20, + 30: 21, + 31: 22, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: E, + 89: 37, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: F, + 175: 57, + 176: I, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { 6: Nr, 35: Cr, 36: [1, 687] }, + t(Vn, [2, 59]), + t(Vn, [2, 61]), + { + 7: 688, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 689, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 690, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 691, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 692, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 693, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 694, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + { + 7: 695, + 9: 154, + 13: 23, + 14: n, + 15: 25, + 16: 26, + 17: 8, + 18: 9, + 19: 10, + 20: 11, + 21: 12, + 22: 13, + 23: 14, + 24: 15, + 25: 16, + 26: 17, + 27: 18, + 28: 19, + 32: _t, + 37: 78, + 38: i, + 39: s, + 42: 63, + 43: o, + 44: 88, + 45: u, + 46: a, + 48: 65, + 49: f, + 50: l, + 51: 33, + 53: 30, + 54: c, + 55: h, + 56: p, + 57: d, + 58: v, + 59: m, + 60: 29, + 67: 79, + 68: g, + 73: 62, + 74: 31, + 75: 35, + 76: 34, + 77: y, + 84: b, + 85: Dt, + 86: Pt, + 89: 152, + 90: S, + 91: x, + 96: 61, + 98: 45, + 100: 32, + 107: T, + 110: N, + 112: C, + 120: k, + 129: L, + 130: A, + 140: O, + 144: M, + 145: _, + 147: 49, + 148: D, + 150: P, + 151: 48, + 152: 50, + 153: H, + 154: 51, + 155: 52, + 156: B, + 158: 85, + 167: j, + 172: 46, + 173: Ht, + 176: Bt, + 177: q, + 178: R, + 179: U, + 180: z, + 181: W, + }, + t(Or, [2, 218]), + t(sr, dn, { 92: 696, 93: Ar }), + t(Or, [2, 219]), + t(mn, [2, 103]), + t(pt, [2, 326]), + t(pt, [2, 327]), + { 33: [1, 697] }, + t(St, [2, 159]), + { 6: Pr, 35: Hr, 36: [1, 698] }, + t(St, [2, 182]), + { 6: Br, 35: jr, 36: [1, 699] }, + t(Bn, [2, 229]), + { + 35: Yr, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 313] }, + { + 35: Zr, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 315] }, + { + 35: ei, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 317] }, + { + 35: ti, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 319] }, + { + 35: ni, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 314] }, + { + 35: ri, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 316] }, + { + 35: ii, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 318] }, + { + 35: si, + 148: J, + 150: K, + 151: 111, + 154: 112, + 156: Q, + 158: 116, + 174: G, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }, + { 35: [2, 320] }, + t(Vn, [2, 146]), + t(Tn, Yr, { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(Tn, Zr, { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(Tn, ei, { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(Tn, ti, { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(Tn, ni, { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(Tn, ri, { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(Tn, ii, { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + t(Tn, si, { + 151: 111, + 154: 112, + 158: 116, + 178: Y, + 179: Z, + 182: et, + 183: tt, + 184: nt, + 185: rt, + 186: it, + 187: st, + 188: ot, + 189: ut, + 190: at, + 191: ft, + 192: lt, + 193: ct, + }), + { 6: Rr, 35: Ur, 36: [1, 700] }, + { 44: 701, 45: u, 46: a }, + t(Vn, [2, 166]), + t(Vn, [2, 187]), + t(Or, [2, 220]), + t(St, [2, 161]), + ], + defaultActions: { + 235: [2, 277], + 293: [2, 140], + 471: [2, 172], + 494: [2, 253], + 497: [2, 255], + 499: [2, 276], + 592: [2, 309], + 594: [2, 310], + 596: [2, 322], + 598: [2, 323], + 672: [2, 313], + 674: [2, 315], + 676: [2, 317], + 678: [2, 319], + 680: [2, 314], + 682: [2, 316], + 684: [2, 318], + 686: [2, 320], + }, + parseError: function (e, t) { + if (!t.recoverable) { + var n = new Error(e); + throw ((n.hash = t), n); + } + this.trace(e); + }, + parse: function (e) { + var t = this, + n = [0], + r = [null], + i = [], + s = this.table, + o = "", + u = 0, + a = 0, + f = 0, + l = 1, + c = i.slice.call(arguments, 1), + h = Object.create(this.lexer), + p = { yy: {} }; + for (var d in this.yy) + Object.prototype.hasOwnProperty.call(this.yy, d) && + (p.yy[d] = this.yy[d]); + h.setInput(e, p.yy), + (p.yy.lexer = h), + (p.yy.parser = this), + "undefined" == typeof h.yylloc && (h.yylloc = {}); + var v = h.yylloc; + i.push(v); + var m = h.options && h.options.ranges; + this.parseError = + "function" == typeof p.yy.parseError + ? p.yy.parseError + : Object.getPrototypeOf(this).parseError; + var g = function () { + var e; + return ( + (e = h.lex() || l), + "number" != typeof e && + (e = t.symbols_[e] || e), + e + ); + }; + for (var y = {}, b, w, E, S, x, T, N, C, k; ; ) { + if ( + ((E = n[n.length - 1]), + this.defaultActions[E] + ? (S = this.defaultActions[E]) + : ((null === b || + "undefined" == typeof b) && + (b = g()), + (S = s[E] && s[E][b])), + "undefined" == typeof S || !S.length || !S[0]) + ) { + var L = ""; + for (T in ((k = []), s[E])) + this.terminals_[T] && + T > 2 && + k.push("'" + this.terminals_[T] + "'"); + (L = h.showPosition + ? "Parse error on line " + + (u + 1) + + ":\n" + + h.showPosition() + + "\nExpecting " + + k.join(", ") + + ", got '" + + (this.terminals_[b] || b) + + "'" + : "Parse error on line " + + (u + 1) + + ": Unexpected " + + (b == l + ? "end of input" + : "'" + + (this.terminals_[b] || b) + + "'")), + this.parseError(L, { + text: h.match, + token: this.terminals_[b] || b, + line: h.yylineno, + loc: v, + expected: k, + }); + } + if (S[0] instanceof Array && 1 < S.length) + throw new Error( + "Parse Error: multiple actions possible at state: " + + E + + ", token: " + + b, + ); + switch (S[0]) { + case 1: + n.push(b), + r.push(h.yytext), + i.push(h.yylloc), + n.push(S[1]), + (b = null), + w + ? ((b = w), (w = null)) + : ((a = h.yyleng), + (o = h.yytext), + (u = h.yylineno), + (v = h.yylloc), + 0 < f && f--); + break; + case 2: + if ( + ((N = this.productions_[S[1]][1]), + (y.$ = r[r.length - N]), + (y._$ = { + first_line: + i[i.length - (N || 1)] + .first_line, + last_line: + i[i.length - 1].last_line, + first_column: + i[i.length - (N || 1)] + .first_column, + last_column: + i[i.length - 1].last_column, + }), + m && + (y._$.range = [ + i[i.length - (N || 1)].range[0], + i[i.length - 1].range[1], + ]), + (x = this.performAction.apply( + y, + [o, a, u, p.yy, S[1], r, i].concat( + c, + ), + )), + "undefined" != typeof x) + ) + return x; + N && + ((n = n.slice(0, 2 * -1 * N)), + (r = r.slice(0, -1 * N)), + (i = i.slice(0, -1 * N))), + n.push(this.productions_[S[1]][0]), + r.push(y.$), + i.push(y._$), + (C = + s[n[n.length - 2]][ + n[n.length - 1] + ]), + n.push(C); + break; + case 3: + return !0; + } + } + return !0; + }, + }; + return (e.prototype = oi), (oi.Parser = e), new e(); + })(); + return ( + "undefined" != typeof require && + "undefined" != typeof e && + ((e.parser = n), + (e.Parser = n.Parser), + (e.parse = function () { + return n.parse.apply(n, arguments); + }), + (e.main = function () {}), + require.main === t && e.main(process.argv.slice(1))), + t.exports + ); + })()), + (require["./scope"] = (function () { + var e = {}; + return ( + function () { + var t = [].indexOf, + n; + e.Scope = n = (function () { + function e(t, n, r, i) { + _classCallCheck(this, e); + var s, o; + (this.parent = t), + (this.expressions = n), + (this.method = r), + (this.referencedVars = i), + (this.variables = [ + { name: "arguments", type: "arguments" }, + ]), + (this.comments = {}), + (this.positions = {}), + this.parent || (this.utilities = {}), + (this.root = + null == + (s = null == (o = this.parent) ? void 0 : o.root) + ? this + : s); + } + return ( + _createClass(e, [ + { + key: "add", + value: function (t, n, r) { + return this.shared && !r + ? this.parent.add(t, n, r) + : Object.prototype.hasOwnProperty.call( + this.positions, + t, + ) + ? (this.variables[ + this.positions[t] + ].type = n) + : (this.positions[t] = + this.variables.push({ + name: t, + type: n, + }) - 1); + }, + }, + { + key: "namedMethod", + value: function () { + var t; + return (null == (t = this.method) + ? void 0 + : t.name) || !this.parent + ? this.method + : this.parent.namedMethod(); + }, + }, + { + key: "find", + value: function (t) { + var n = + 1 < arguments.length && + void 0 !== arguments[1] + ? arguments[1] + : "var"; + return !!this.check(t) || (this.add(t, n), !1); + }, + }, + { + key: "parameter", + value: function (t) { + return this.shared && this.parent.check(t, !0) + ? void 0 + : this.add(t, "param"); + }, + }, + { + key: "check", + value: function (t) { + var n; + return !!( + this.type(t) || + (null == (n = this.parent) + ? void 0 + : n.check(t)) + ); + }, + }, + { + key: "temporary", + value: function (t, n) { + var r = + 2 < arguments.length && + void 0 !== arguments[2] && + arguments[2], + i, + s, + o, + u, + a, + f; + return r + ? ((f = t.charCodeAt(0)), + (s = 122), + (i = s - f), + (u = f + (n % (i + 1))), + (o = _StringfromCharCode(u)), + (a = _Mathfloor(n / (i + 1))), + "" + o + (a || "")) + : "" + t + (n || ""); + }, + }, + { + key: "type", + value: function (t) { + var n, r, i, s; + for ( + i = this.variables, n = 0, r = i.length; + n < r; + n++ + ) + if (((s = i[n]), s.name === t)) + return s.type; + return null; + }, + }, + { + key: "freeVariable", + value: function (n) { + var r = + 1 < arguments.length && + void 0 !== arguments[1] + ? arguments[1] + : {}, + i, + s, + o; + for ( + i = 0; + (o = this.temporary(n, i, r.single)), + !!( + this.check(o) || + 0 <= + t.call( + this.root.referencedVars, + o, + ) + ); + + ) + i++; + return ( + (null == (s = r.reserve) || s) && + this.add(o, "var", !0), + o + ); + }, + }, + { + key: "assign", + value: function (t, n) { + return ( + this.add(t, { value: n, assigned: !0 }, !0), + (this.hasAssignments = !0) + ); + }, + }, + { + key: "hasDeclarations", + value: function () { + return !!this.declaredVariables().length; + }, + }, + { + key: "declaredVariables", + value: function () { + var t; + return function () { + var e, n, r, i; + for ( + r = this.variables, + i = [], + e = 0, + n = r.length; + e < n; + e++ + ) + (t = r[e]), + "var" === t.type && i.push(t.name); + return i; + } + .call(this) + .sort(); + }, + }, + { + key: "assignedVariables", + value: function () { + var t, n, r, i, s; + for ( + r = this.variables, + i = [], + t = 0, + n = r.length; + t < n; + t++ + ) + (s = r[t]), + s.type.assigned && + i.push( + s.name + " = " + s.type.value, + ); + return i; + }, + }, + ]), + e + ); + })(); + }.call(this), + { exports: e }.exports + ); + })()), + (require["./nodes"] = (function () { + var e = {}; + return ( + function () { + var t = [].indexOf, + n = [].splice, + r = [].slice, + i, + s, + o, + u, + a, + f, + l, + c, + h, + p, + d, + v, + m, + g, + y, + b, + w, + E, + S, + x, + T, + N, + C, + k, + L, + A, + O, + M, + _, + D, + P, + H, + B, + j, + F, + I, + q, + R, + U, + z, + W, + X, + V, + $, + J, + K, + Q, + G, + Y, + Z, + et, + tt, + nt, + rt, + it, + st, + ot, + ut, + at, + ft, + lt, + ct, + ht, + pt, + dt, + vt, + mt, + gt, + yt, + bt, + wt, + Et, + St, + xt, + Tt, + Nt, + Ct, + kt, + Lt, + At, + Ot, + Mt, + _t, + Dt, + Pt, + Ht, + Bt, + jt, + Ft, + It, + qt, + Rt, + Ut, + zt, + Wt, + Xt, + Vt, + $t, + Jt, + Kt, + Qt, + Gt, + Yt, + Zt, + en, + tn, + nn, + rn, + sn, + on, + un, + an; + Error.stackTraceLimit = Infinity; + var fn = require("./scope"); + gt = fn.Scope; + var ln = require("./lexer"); + (Qt = ln.isUnassignable), (z = ln.JS_FORBIDDEN); + var cn = require("./helpers"); + (qt = cn.compact), + (Wt = cn.flatten), + (zt = cn.extend), + (Yt = cn.merge), + (Rt = cn.del), + (rn = cn.starts), + (Ut = cn.ends), + (nn = cn.some), + (Ft = cn.addDataToNode), + (It = cn.attachCommentsToNode), + (Gt = cn.locationDataToString), + (sn = cn.throwSyntaxError), + (e.extend = zt), + (e.addDataToNode = Ft), + (Bt = function () { + return !0; + }), + (nt = function () { + return !1; + }), + (kt = function () { + return this; + }), + (tt = function () { + return (this.negated = !this.negated), this; + }), + (e.CodeFragment = v = + (function () { + function e(t, n) { + _classCallCheck(this, e); + var r; + (this.code = "" + n), + (this.type = + (null == t || null == (r = t.constructor) + ? void 0 + : r.name) || "unknown"), + (this.locationData = + null == t ? void 0 : t.locationData), + (this.comments = + null == t ? void 0 : t.comments); + } + return ( + _createClass(e, [ + { + key: "toString", + value: function t() { + return ( + "" + + this.code + + (this.locationData + ? ": " + Gt(this.locationData) + : "") + ); + }, + }, + ]), + e + ); + })()), + (Xt = function (e) { + var t; + return (function () { + var n, r, i; + for (i = [], n = 0, r = e.length; n < r; n++) + (t = e[n]), i.push(t.code); + return i; + })().join(""); + }), + (e.Base = a = + function () { + var e = (function () { + function e() { + _classCallCheck(this, e); + } + return ( + _createClass(e, [ + { + key: "compile", + value: function (t, n) { + return Xt( + this.compileToFragments(t, n), + ); + }, + }, + { + key: "compileWithoutComments", + value: function (t, n) { + var r = + 2 < arguments.length && + void 0 !== arguments[2] + ? arguments[2] + : "compile", + i, + s; + return ( + this.comments && + ((this.ignoreTheseCommentsTemporarily = + this.comments), + delete this.comments), + (s = this.unwrapAll()), + s.comments && + ((s.ignoreTheseCommentsTemporarily = + s.comments), + delete s.comments), + (i = this[r](t, n)), + this + .ignoreTheseCommentsTemporarily && + ((this.comments = + this.ignoreTheseCommentsTemporarily), + delete this + .ignoreTheseCommentsTemporarily), + s.ignoreTheseCommentsTemporarily && + ((s.comments = + s.ignoreTheseCommentsTemporarily), + delete s.ignoreTheseCommentsTemporarily), + i + ); + }, + }, + { + key: "compileNodeWithoutComments", + value: function (t, n) { + return this.compileWithoutComments( + t, + n, + "compileNode", + ); + }, + }, + { + key: "compileToFragments", + value: function (t, n) { + var r, i; + return ( + (t = zt({}, t)), + n && (t.level = n), + (i = + this.unfoldSoak(t) || this), + (i.tab = t.indent), + (r = + t.level !== K && + i.isStatement(t) + ? i.compileClosure(t) + : i.compileNode(t)), + this.compileCommentFragments( + t, + i, + r, + ), + r + ); + }, + }, + { + key: "compileToFragmentsWithoutComments", + value: function (t, n) { + return this.compileWithoutComments( + t, + n, + "compileToFragments", + ); + }, + }, + { + key: "compileClosure", + value: function (t) { + var n, r, s, o, u, a, l, c; + switch ( + ((o = this.jumps()) && + o.error( + "cannot use a pure statement in an expression", + ), + (t.sharedScope = !0), + (s = new d([], f.wrap([this]))), + (n = []), + this.contains(function (e) { + return e instanceof Tt; + }) + ? (s.bound = !0) + : ((r = + this.contains(Jt)) || + this.contains(Kt)) && + ((n = [new At()]), + r + ? ((u = "apply"), + n.push( + new _( + "arguments", + ), + )) + : (u = "call"), + (s = new Pt(s, [ + new i(new ct(u)), + ]))), + (a = new h(s, n).compileNode( + t, + )), + !1) + ) { + case !( + s.isGenerator || + (null == (l = s.base) + ? void 0 + : l.isGenerator) + ): + a.unshift( + this.makeCode( + "(yield* ", + ), + ), + a.push( + this.makeCode(")"), + ); + break; + case !( + s.isAsync || + (null == (c = s.base) + ? void 0 + : c.isAsync) + ): + a.unshift( + this.makeCode( + "(await ", + ), + ), + a.push( + this.makeCode(")"), + ); + } + return a; + }, + }, + { + key: "compileCommentFragments", + value: function (n, r, i) { + var s, o, u, a, f, l, c, h; + if (!r.comments) return i; + for ( + h = function (e) { + var t; + return e.unshift + ? un(i, e) + : (0 !== i.length && + ((t = + i[ + i.length - + 1 + ]), + e.newLine && + "" !== + t.code && + !/\n\s*$/.test( + t.code, + ) && + (e.code = + "\n" + + e.code)), + i.push(e)); + }, + c = r.comments, + f = 0, + l = c.length; + f < l; + f++ + ) + ((u = c[f]), + 0 > + t.call( + this.compiledComments, + u, + )) && + (this.compiledComments.push( + u, + ), + (a = u.here + ? new O(u).compileNode( + n, + ) + : new Q(u).compileNode( + n, + )), + (a.isHereComment && + !a.newLine) || + r.includeCommentFragments() + ? h(a) + : (0 === i.length && + i.push( + this.makeCode( + "", + ), + ), + a.unshift + ? (null == + (s = i[0]) + .precedingComments && + (s.precedingComments = + []), + i[0].precedingComments.push( + a, + )) + : (null == + (o = + i[ + i.length - + 1 + ]) + .followingComments && + (o.followingComments = + []), + i[ + i.length - 1 + ].followingComments.push( + a, + )))); + return i; + }, + }, + { + key: "cache", + value: function (t, n, r) { + var i, s, u; + return ( + (i = + null == r + ? this.shouldCache() + : r(this)), + i + ? ((s = new _( + t.scope.freeVariable( + "ref", + ), + )), + (u = new o(s, this)), + n + ? [ + u.compileToFragments( + t, + n, + ), + [ + this.makeCode( + s.value, + ), + ], + ] + : [u, s]) + : ((s = n + ? this.compileToFragments( + t, + n, + ) + : this), + [s, s]) + ); + }, + }, + { + key: "hoist", + value: function () { + var t, n, r; + return ( + (this.hoisted = !0), + (r = new M(this)), + (t = this.compileNode), + (n = this.compileToFragments), + (this.compileNode = function ( + e, + ) { + return r.update(t, e); + }), + (this.compileToFragments = + function (e) { + return r.update(n, e); + }), + r + ); + }, + }, + { + key: "cacheToCodeFragments", + value: function (t) { + return [Xt(t[0]), Xt(t[1])]; + }, + }, + { + key: "makeReturn", + value: function (t) { + var n; + return ( + (n = this.unwrapAll()), + t + ? new h( + new G(t + ".push"), + [n], + ) + : new vt(n) + ); + }, + }, + { + key: "contains", + value: function (t) { + var n; + return ( + (n = void 0), + this.traverseChildren( + !1, + function (e) { + if (t(e)) + return (n = e), !1; + }, + ), + n + ); + }, + }, + { + key: "lastNode", + value: function (t) { + return 0 === t.length + ? null + : t[t.length - 1]; + }, + }, + { + key: "toString", + value: function r() { + var e = + 0 < arguments.length && + void 0 !== arguments[0] + ? arguments[0] + : "", + t = + 1 < arguments.length && + void 0 !== arguments[1] + ? arguments[1] + : this.constructor.name, + n; + return ( + (n = "\n" + e + t), + this.soak && (n += "?"), + this.eachChild(function (t) { + return (n += t.toString( + e + Ct, + )); + }), + n + ); + }, + }, + { + key: "eachChild", + value: function (t) { + var n, r, i, s, o, u, a, f; + if (!this.children) return this; + for ( + a = this.children, + i = 0, + o = a.length; + i < o; + i++ + ) + if (((n = a[i]), this[n])) + for ( + f = Wt([this[n]]), + s = 0, + u = f.length; + s < u; + s++ + ) + if ( + ((r = f[s]), + !1 === t(r)) + ) + return this; + return this; + }, + }, + { + key: "traverseChildren", + value: function (t, n) { + return this.eachChild(function (e) { + var r; + if (((r = n(e)), !1 !== r)) + return e.traverseChildren( + t, + n, + ); + }); + }, + }, + { + key: "replaceInContext", + value: function (t, r) { + var i, s, o, u, a, f, l, c, h, p; + if (!this.children) return !1; + for ( + h = this.children, + a = 0, + l = h.length; + a < l; + a++ + ) + if (((i = h[a]), (o = this[i]))) + if (Array.isArray(o)) + for ( + u = f = 0, + c = o.length; + f < c; + u = ++f + ) { + if ( + ((s = o[u]), + t(s)) + ) + return ( + n.apply( + o, + [ + u, + u - + u + + 1, + ].concat( + (p = + r( + s, + this, + )), + ), + ), + p, + !0 + ); + if ( + s.replaceInContext( + t, + r, + ) + ) + return !0; + } + else { + if (t(o)) + return ( + (this[i] = r( + o, + this, + )), + !0 + ); + if ( + o.replaceInContext( + t, + r, + ) + ) + return !0; + } + }, + }, + { + key: "invert", + value: function () { + return new ut("!", this); + }, + }, + { + key: "unwrapAll", + value: function () { + var t; + for ( + t = this; + t !== (t = t.unwrap()); + + ) + continue; + return t; + }, + }, + { + key: "updateLocationDataIfMissing", + value: function (t) { + return this.locationData && + !this.forceUpdateLocation + ? this + : (delete this + .forceUpdateLocation, + (this.locationData = t), + this.eachChild(function (e) { + return e.updateLocationDataIfMissing( + t, + ); + })); + }, + }, + { + key: "error", + value: function (t) { + return sn(t, this.locationData); + }, + }, + { + key: "makeCode", + value: function (t) { + return new v(this, t); + }, + }, + { + key: "wrapInParentheses", + value: function (t) { + return [this.makeCode("(")].concat( + _toConsumableArray(t), + [this.makeCode(")")], + ); + }, + }, + { + key: "wrapInBraces", + value: function (t) { + return [this.makeCode("{")].concat( + _toConsumableArray(t), + [this.makeCode("}")], + ); + }, + }, + { + key: "joinFragmentArrays", + value: function (t, n) { + var r, i, s, o, u; + for ( + r = [], s = o = 0, u = t.length; + o < u; + s = ++o + ) + (i = t[s]), + s && + r.push( + this.makeCode(n), + ), + (r = r.concat(i)); + return r; + }, + }, + ]), + e + ); + })(); + return ( + (e.prototype.children = []), + (e.prototype.isStatement = nt), + (e.prototype.compiledComments = []), + (e.prototype.includeCommentFragments = nt), + (e.prototype.jumps = nt), + (e.prototype.shouldCache = Bt), + (e.prototype.isChainable = nt), + (e.prototype.isAssignable = nt), + (e.prototype.isNumber = nt), + (e.prototype.unwrap = kt), + (e.prototype.unfoldSoak = nt), + (e.prototype.assigns = nt), + e + ); + }.call(this)), + (e.HoistTarget = M = + (function (e) { + function t(e) { + _classCallCheck(this, t); + var n = _possibleConstructorReturn( + this, + (t.__proto__ || Object.getPrototypeOf(t)).call( + this, + ), + ); + return ( + (n.source = e), + (n.options = {}), + (n.targetFragments = { fragments: [] }), + n + ); + } + return ( + _inherits(t, e), + _createClass(t, null, [ + { + key: "expand", + value: function (t) { + var r, i, s, o; + for ( + i = s = t.length - 1; + 0 <= s; + i = s += -1 + ) + (r = t[i]), + r.fragments && + (n.apply( + t, + [i, i - i + 1].concat( + (o = this.expand( + r.fragments, + )), + ), + ), + o); + return t; + }, + }, + ]), + _createClass(t, [ + { + key: "isStatement", + value: function (t) { + return this.source.isStatement(t); + }, + }, + { + key: "update", + value: function (t, n) { + return (this.targetFragments.fragments = + t.call( + this.source, + Yt(n, this.options), + )); + }, + }, + { + key: "compileToFragments", + value: function (t, n) { + return ( + (this.options.indent = t.indent), + (this.options.level = + null == n ? t.level : n), + [this.targetFragments] + ); + }, + }, + { + key: "compileNode", + value: function (t) { + return this.compileToFragments(t); + }, + }, + { + key: "compileClosure", + value: function (t) { + return this.compileToFragments(t); + }, + }, + ]), + t + ); + })(a)), + (e.Block = f = + function () { + var e = (function (e) { + function n(e) { + _classCallCheck(this, n); + var t = _possibleConstructorReturn( + this, + ( + n.__proto__ || Object.getPrototypeOf(n) + ).call(this), + ); + return (t.expressions = qt(Wt(e || []))), t; + } + return ( + _inherits(n, e), + _createClass( + n, + [ + { + key: "push", + value: function (t) { + return ( + this.expressions.push(t), + this + ); + }, + }, + { + key: "pop", + value: function () { + return this.expressions.pop(); + }, + }, + { + key: "unshift", + value: function (t) { + return ( + this.expressions.unshift(t), + this + ); + }, + }, + { + key: "unwrap", + value: function () { + return 1 === + this.expressions.length + ? this.expressions[0] + : this; + }, + }, + { + key: "isEmpty", + value: function () { + return !this.expressions.length; + }, + }, + { + key: "isStatement", + value: function (t) { + var n, r, i, s; + for ( + s = this.expressions, + r = 0, + i = s.length; + r < i; + r++ + ) + if ( + ((n = s[r]), + n.isStatement(t)) + ) + return !0; + return !1; + }, + }, + { + key: "jumps", + value: function (t) { + var n, r, i, s, o; + for ( + o = this.expressions, + r = 0, + s = o.length; + r < s; + r++ + ) + if ( + ((n = o[r]), + (i = n.jumps(t))) + ) + return i; + }, + }, + { + key: "makeReturn", + value: function (t) { + var n, r; + for ( + r = this.expressions.length; + r--; + + ) { + (n = this.expressions[r]), + (this.expressions[r] = + n.makeReturn(t)), + n instanceof vt && + !n.expression && + this.expressions.splice( + r, + 1, + ); + break; + } + return this; + }, + }, + { + key: "compileToFragments", + value: function () { + var t = + 0 < arguments.length && + void 0 !== arguments[0] + ? arguments[0] + : {}, + r = arguments[1]; + return t.scope + ? _get( + n.prototype + .__proto__ || + Object.getPrototypeOf( + n.prototype, + ), + "compileToFragments", + this, + ).call(this, t, r) + : this.compileRoot(t); + }, + }, + { + key: "compileNode", + value: function (t) { + var i, + s, + o, + u, + a, + f, + l, + c, + h, + p; + for ( + this.tab = t.indent, + p = t.level === K, + s = [], + h = this.expressions, + u = a = 0, + l = h.length; + a < l; + u = ++a + ) { + if ( + ((c = h[u]), c.hoisted) + ) { + c.compileToFragments(t); + continue; + } + if ( + ((c = + c.unfoldSoak(t) || + c), + c instanceof n) + ) + s.push( + c.compileNode(t), + ); + else if (p) { + if ( + ((c.front = !0), + (o = + c.compileToFragments( + t, + )), + !c.isStatement(t)) + ) { + o = $t(o, this); + var d = r.call( + o, + -1, + ), + v = + _slicedToArray( + d, + 1, + ); + (f = v[0]), + "" === f.code || + f.isComment || + o.push( + this.makeCode( + ";", + ), + ); + } + s.push(o); + } else + s.push( + c.compileToFragments( + t, + V, + ), + ); + } + return p + ? this.spaced + ? [].concat( + this.joinFragmentArrays( + s, + "\n\n", + ), + this.makeCode( + "\n", + ), + ) + : this.joinFragmentArrays( + s, + "\n", + ) + : ((i = s.length + ? this.joinFragmentArrays( + s, + ", ", + ) + : [ + this.makeCode( + "void 0", + ), + ]), + 1 < s.length && + t.level >= V + ? this.wrapInParentheses( + i, + ) + : i); + }, + }, + { + key: "compileRoot", + value: function (t) { + var n, r, i, s, o, u; + for ( + t.indent = t.bare ? "" : Ct, + t.level = K, + this.spaced = !0, + t.scope = new gt( + null, + this, + null, + null == + (o = + t.referencedVars) + ? [] + : o, + ), + u = t.locals || [], + r = 0, + i = u.length; + r < i; + r++ + ) + (s = u[r]), + t.scope.parameter(s); + return ( + (n = + this.compileWithDeclarations( + t, + )), + M.expand(n), + (n = + this.compileComments( + n, + )), + t.bare + ? n + : [].concat( + this.makeCode( + "(function() {\n", + ), + n, + this.makeCode( + "\n}).call(this);\n", + ), + ) + ); + }, + }, + { + key: "compileWithDeclarations", + value: function (t) { + var n, + r, + i, + s, + o, + u, + a, + f, + l, + c, + h, + p, + d, + v, + m, + g, + y; + for ( + a = [], + d = [], + v = this.expressions, + f = l = 0, + h = v.length; + l < h && + ((u = v[f]), + (u = u.unwrap()), + u instanceof G); + f = ++l + ); + if ( + ((t = Yt(t, { level: K })), + f) + ) { + m = this.expressions.splice( + f, + 9e9, + ); + var b = [this.spaced, !1]; + (y = b[0]), + (this.spaced = b[1]); + var w = [ + this.compileNode(t), + y, + ]; + (a = w[0]), + (this.spaced = w[1]), + (this.expressions = m); + } + d = this.compileNode(t); + var E = t; + if ( + ((g = E.scope), + g.expressions === this) + ) + if ( + ((o = + t.scope.hasDeclarations()), + (n = g.hasAssignments), + o || n) + ) { + if ( + (f && + a.push( + this.makeCode( + "\n", + ), + ), + a.push( + this.makeCode( + this.tab + + "var ", + ), + ), + o) + ) + for ( + i = + g.declaredVariables(), + s = c = 0, + p = + i.length; + c < p; + s = ++c + ) { + if ( + ((r = i[s]), + a.push( + this.makeCode( + r, + ), + ), + Object.prototype.hasOwnProperty.call( + t.scope + .comments, + r, + )) + ) { + var S; + (S = + a).push.apply( + S, + _toConsumableArray( + t + .scope + .comments[ + r + ], + ), + ); + } + s !== + i.length - + 1 && + a.push( + this.makeCode( + ", ", + ), + ); + } + n && + (o && + a.push( + this.makeCode( + ",\n" + + (this + .tab + + Ct), + ), + ), + a.push( + this.makeCode( + g + .assignedVariables() + .join( + ",\n" + + (this + .tab + + Ct), + ), + ), + )), + a.push( + this.makeCode( + ";\n" + + (this + .spaced + ? "\n" + : ""), + ), + ); + } else + a.length && + d.length && + a.push( + this.makeCode( + "\n", + ), + ); + return a.concat(d); + }, + }, + { + key: "compileComments", + value: function (n) { + var r, + i, + s, + o, + u, + a, + f, + l, + c, + h, + p, + d, + v, + m, + g, + y, + b, + w, + E, + S, + x, + T, + N, + C, + k; + for ( + u = f = 0, h = n.length; + f < h; + u = ++f + ) { + if ( + ((s = n[u]), + s.precedingComments) + ) { + for ( + o = "", + E = n.slice( + 0, + u + 1, + ), + l = + E.length - + 1; + 0 <= l; + l += -1 + ) { + if ( + ((g = E[l]), + (a = + /^ {2,}/m.exec( + g.code, + )), + a) + ) { + o = a[0]; + break; + } + if ( + 0 <= + t.call( + g.code, + "\n", + ) + ) + break; + } + for ( + r = + "\n" + + o + + (function () { + var e, + t, + n, + r; + for ( + n = + s.precedingComments, + r = + [], + e = 0, + t = + n.length; + e < t; + e++ + ) + (i = + n[ + e + ]), + i.isHereComment && + i.multiline + ? r.push( + en( + i.code, + o, + !1, + ), + ) + : r.push( + i.code, + ); + return r; + })() + .join( + "\n" + + o, + ) + .replace( + /^(\s*)$/gm, + "", + ), + S = n.slice( + 0, + u + 1, + ), + y = c = + S.length - + 1; + 0 <= c; + y = c += -1 + ) { + if ( + ((g = S[y]), + (v = + g.code.lastIndexOf( + "\n", + )), + -1 === v) + ) + if (0 === y) + (g.code = + "\n" + + g.code), + (v = 0); + else { + if ( + !g.isStringWithInterpolations || + "{" !== + g.code + ) + continue; + (r = + r.slice( + 1, + ) + + "\n"), + (v = 1); + } + delete s.precedingComments, + (g.code = + g.code.slice( + 0, + v, + ) + + r + + g.code.slice( + v, + )); + break; + } + } + if (s.followingComments) { + if ( + ((N = + s + .followingComments[0] + .trail), + (o = ""), + !N || + 1 !== + s + .followingComments + .length) + ) + for ( + m = !1, + x = + n.slice( + u, + ), + b = 0, + p = + x.length; + b < p; + b++ + ) + if ( + ((C = x[b]), + !m) + ) { + if ( + !( + 0 <= + t.call( + C.code, + "\n", + ) + ) + ) + continue; + m = !0; + } else { + if ( + ((a = + /^ {2,}/m.exec( + C.code, + )), + a) + ) { + o = + a[0]; + break; + } + if ( + 0 <= + t.call( + C.code, + "\n", + ) + ) + break; + } + for ( + r = + 1 === u && + /^\s+$/.test( + n[0].code, + ) + ? "" + : N + ? " " + : "\n" + + o, + r += + (function () { + var e, + t, + n, + r; + for ( + n = + s.followingComments, + r = + [], + t = 0, + e = + n.length; + t < + e; + t++ + ) + (i = + n[ + t + ]), + i.isHereComment && + i.multiline + ? r.push( + en( + i.code, + o, + !1, + ), + ) + : r.push( + i.code, + ); + return r; + })() + .join( + "\n" + + o, + ) + .replace( + /^(\s*)$/gm, + "", + ), + T = n.slice(u), + k = w = 0, + d = T.length; + w < d; + k = ++w + ) { + if ( + ((C = T[k]), + (v = + C.code.indexOf( + "\n", + )), + -1 === v) + ) + if ( + k === + n.length - 1 + ) + (C.code += + "\n"), + (v = + C + .code + .length); + else { + if ( + !C.isStringWithInterpolations || + "}" !== + C.code + ) + continue; + (r += "\n"), + (v = 0); + } + delete s.followingComments, + "\n" === + C.code && + (r = + r.replace( + /^\n/, + "", + )), + (C.code = + C.code.slice( + 0, + v, + ) + + r + + C.code.slice( + v, + )); + break; + } + } + } + return n; + }, + }, + ], + [ + { + key: "wrap", + value: function (t) { + return 1 === t.length && + t[0] instanceof n + ? t[0] + : new n(t); + }, + }, + ], + ), + n + ); + })(a); + return (e.prototype.children = ["expressions"]), e; + }.call(this)), + (e.Literal = G = + function () { + var e = (function (e) { + function t(e) { + _classCallCheck(this, t); + var n = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return (n.value = e), n; + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "assigns", + value: function (t) { + return t === this.value; + }, + }, + { + key: "compileNode", + value: function () { + return [this.makeCode(this.value)]; + }, + }, + { + key: "toString", + value: function n() { + return ( + " " + + (this.isStatement() + ? _get( + t.prototype + .__proto__ || + Object.getPrototypeOf( + t.prototype, + ), + "toString", + this, + ).call(this) + : this.constructor.name) + + ": " + + this.value + ); + }, + }, + ]), + t + ); + })(a); + return (e.prototype.shouldCache = nt), e; + }.call(this)), + (e.NumberLiteral = st = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return _inherits(t, e), t; + })(G)), + (e.InfinityLiteral = U = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function () { + return [this.makeCode("2e308")]; + }, + }, + ]), + t + ); + })(st)), + (e.NaNLiteral = rt = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this, "NaN"), + ) + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (t) { + var n; + return ( + (n = [this.makeCode("0/0")]), + t.level >= $ + ? this.wrapInParentheses(n) + : n + ); + }, + }, + ]), + t + ); + })(st)), + (e.StringLiteral = Et = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function () { + var n; + return (n = this.csx + ? [ + this.makeCode( + this.unquote(!0, !0), + ), + ] + : _get( + t.prototype.__proto__ || + Object.getPrototypeOf( + t.prototype, + ), + "compileNode", + this, + ).call(this)); + }, + }, + { + key: "unquote", + value: function () { + var t = + 0 < arguments.length && + void 0 !== arguments[0] && + arguments[0], + n = + 1 < arguments.length && + void 0 !== arguments[1] && + arguments[1], + r; + return ( + (r = this.value.slice(1, -1)), + t && (r = r.replace(/\\"/g, '"')), + n && (r = r.replace(/\\n/g, "\n")), + r + ); + }, + }, + ]), + t + ); + })(G)), + (e.RegexLiteral = pt = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return _inherits(t, e), t; + })(G)), + (e.PassthroughLiteral = lt = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return _inherits(t, e), t; + })(G)), + (e.IdentifierLiteral = _ = + function () { + var e = (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || + Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "eachName", + value: function (t) { + return t(this); + }, + }, + ]), + t + ); + })(G); + return (e.prototype.isAssignable = Bt), e; + }.call(this)), + (e.CSXTag = c = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return _inherits(t, e), t; + })(_)), + (e.PropertyName = ct = + function () { + var e = (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || + Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return _inherits(t, e), t; + })(G); + return (e.prototype.isAssignable = Bt), e; + }.call(this)), + (e.ComputedPropertyName = m = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (t) { + return [this.makeCode("[")].concat( + _toConsumableArray( + this.value.compileToFragments( + t, + V, + ), + ), + [this.makeCode("]")], + ); + }, + }, + ]), + t + ); + })(ct)), + (e.StatementLiteral = wt = + function () { + var e = (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || + Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "jumps", + value: function (t) { + return "break" !== this.value || + (null == t ? void 0 : t.loop) || + (null == t ? void 0 : t.block) + ? "continue" !== this.value || + (null != t && t.loop) + ? void 0 + : this + : this; + }, + }, + { + key: "compileNode", + value: function () { + return [ + this.makeCode( + "" + + this.tab + + this.value + + ";", + ), + ]; + }, + }, + ]), + t + ); + })(G); + return ( + (e.prototype.isStatement = Bt), + (e.prototype.makeReturn = kt), + e + ); + }.call(this)), + (e.ThisLiteral = At = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this, "this"), + ) + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (t) { + var n, r; + return ( + (n = ( + null == (r = t.scope.method) + ? void 0 + : r.bound + ) + ? t.scope.method.context + : this.value), + [this.makeCode(n)] + ); + }, + }, + ]), + t + ); + })(G)), + (e.UndefinedLiteral = Dt = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this, "undefined"), + ) + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (t) { + return [ + this.makeCode( + t.level >= W + ? "(void 0)" + : "void 0", + ), + ]; + }, + }, + ]), + t + ); + })(G)), + (e.NullLiteral = it = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this, "null"), + ) + ); + } + return _inherits(t, e), t; + })(G)), + (e.BooleanLiteral = l = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return _inherits(t, e), t; + })(G)), + (e.Return = vt = + function () { + var e = (function (e) { + function n(e) { + _classCallCheck(this, n); + var t = _possibleConstructorReturn( + this, + ( + n.__proto__ || Object.getPrototypeOf(n) + ).call(this), + ); + return (t.expression = e), t; + } + return ( + _inherits(n, e), + _createClass(n, [ + { + key: "compileToFragments", + value: function (t, r) { + var i, s; + return ( + (i = + null == + (s = this.expression) + ? void 0 + : s.makeReturn()), + !i || i instanceof n + ? _get( + n.prototype + .__proto__ || + Object.getPrototypeOf( + n.prototype, + ), + "compileToFragments", + this, + ).call(this, t, r) + : i.compileToFragments(t, r) + ); + }, + }, + { + key: "compileNode", + value: function (n) { + var r, i, s, o; + if (((r = []), this.expression)) + for ( + r = + this.expression.compileToFragments( + n, + J, + ), + un( + r, + this.makeCode( + this.tab + + "return ", + ), + ), + s = 0, + o = r.length; + s < o; + s++ + ) + if ( + ((i = r[s]), + i.isHereComment && + 0 <= + t.call( + i.code, + "\n", + )) + ) + i.code = en( + i.code, + this.tab, + ); + else { + if (!i.isLineComment) + break; + i.code = + "" + + this.tab + + i.code; + } + else + r.push( + this.makeCode( + this.tab + "return", + ), + ); + return ( + r.push(this.makeCode(";")), r + ); + }, + }, + ]), + n + ); + })(a); + return ( + (e.prototype.children = ["expression"]), + (e.prototype.isStatement = Bt), + (e.prototype.makeReturn = kt), + (e.prototype.jumps = kt), + e + ); + }.call(this)), + (e.YieldReturn = jt = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (n) { + return ( + null == n.scope.parent && + this.error( + "yield can only occur inside functions", + ), + _get( + t.prototype.__proto__ || + Object.getPrototypeOf( + t.prototype, + ), + "compileNode", + this, + ).call(this, n) + ); + }, + }, + ]), + t + ); + })(vt)), + (e.AwaitReturn = u = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (n) { + return ( + null == n.scope.parent && + this.error( + "await can only occur inside functions", + ), + _get( + t.prototype.__proto__ || + Object.getPrototypeOf( + t.prototype, + ), + "compileNode", + this, + ).call(this, n) + ); + }, + }, + ]), + t + ); + })(vt)), + (e.Value = Pt = + function () { + var e = (function (e) { + function t(e, n, r) { + var i = + 3 < arguments.length && + void 0 !== arguments[3] && + arguments[3]; + _classCallCheck(this, t); + var s = _possibleConstructorReturn( + this, + ( + t.__proto__ || + Object.getPrototypeOf(t) + ).call(this), + ), + o, + u; + if (!n && e instanceof t) { + var a; + return ( + (a = e), + _possibleConstructorReturn(s, a) + ); + } + if ( + e instanceof ft && + e.contains(function (e) { + return e instanceof wt; + }) + ) { + var f; + return ( + (f = e.unwrap()), + _possibleConstructorReturn(s, f) + ); + } + return ( + (s.base = e), + (s.properties = n || []), + r && (s[r] = !0), + (s.isDefaultValue = i), + (null == (o = s.base) + ? void 0 + : o.comments) && + s.base instanceof At && + null != + (null == (u = s.properties[0]) + ? void 0 + : u.name) && + Zt(s.base, s.properties[0].name), + s + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "add", + value: function (t) { + return ( + (this.properties = + this.properties.concat(t)), + (this.forceUpdateLocation = !0), + this + ); + }, + }, + { + key: "hasProperties", + value: function () { + return 0 !== this.properties.length; + }, + }, + { + key: "bareLiteral", + value: function (t) { + return ( + !this.properties.length && + this.base instanceof t + ); + }, + }, + { + key: "isArray", + value: function () { + return this.bareLiteral(s); + }, + }, + { + key: "isRange", + value: function () { + return this.bareLiteral(ht); + }, + }, + { + key: "shouldCache", + value: function () { + return ( + this.hasProperties() || + this.base.shouldCache() + ); + }, + }, + { + key: "isAssignable", + value: function () { + return ( + this.hasProperties() || + this.base.isAssignable() + ); + }, + }, + { + key: "isNumber", + value: function () { + return this.bareLiteral(st); + }, + }, + { + key: "isString", + value: function () { + return this.bareLiteral(Et); + }, + }, + { + key: "isRegex", + value: function () { + return this.bareLiteral(pt); + }, + }, + { + key: "isUndefined", + value: function () { + return this.bareLiteral(Dt); + }, + }, + { + key: "isNull", + value: function () { + return this.bareLiteral(it); + }, + }, + { + key: "isBoolean", + value: function () { + return this.bareLiteral(l); + }, + }, + { + key: "isAtomic", + value: function () { + var t, n, r, i; + for ( + i = this.properties.concat( + this.base, + ), + t = 0, + n = i.length; + t < n; + t++ + ) + if ( + ((r = i[t]), + r.soak || r instanceof h) + ) + return !1; + return !0; + }, + }, + { + key: "isNotCallable", + value: function () { + return ( + this.isNumber() || + this.isString() || + this.isRegex() || + this.isArray() || + this.isRange() || + this.isSplice() || + this.isObject() || + this.isUndefined() || + this.isNull() || + this.isBoolean() + ); + }, + }, + { + key: "isStatement", + value: function (t) { + return ( + !this.properties.length && + this.base.isStatement(t) + ); + }, + }, + { + key: "assigns", + value: function (t) { + return ( + !this.properties.length && + this.base.assigns(t) + ); + }, + }, + { + key: "jumps", + value: function (t) { + return ( + !this.properties.length && + this.base.jumps(t) + ); + }, + }, + { + key: "isObject", + value: function (t) { + return ( + !this.properties.length && + this.base instanceof ot && + (!t || this.base.generated) + ); + }, + }, + { + key: "isElision", + value: function () { + return ( + this.base instanceof s && + this.base.hasElision() + ); + }, + }, + { + key: "isSplice", + value: function () { + var t, n, i, s; + return ( + (s = this.properties), + (t = r.call(s, -1)), + (n = _slicedToArray(t, 1)), + (i = n[0]), + t, + i instanceof yt + ); + }, + }, + { + key: "looksStatic", + value: function (t) { + var n; + return ( + (this.this || + this.base instanceof At || + this.base.value === t) && + 1 === this.properties.length && + "prototype" !== + (null == + (n = + this.properties[0].name) + ? void 0 + : n.value) + ); + }, + }, + { + key: "unwrap", + value: function () { + return this.properties.length + ? this + : this.base; + }, + }, + { + key: "cacheReference", + value: function (n) { + var i, s, u, a, f, l, c; + return ((c = this.properties), + (i = r.call(c, -1)), + (s = _slicedToArray(i, 1)), + (f = s[0]), + i, + 2 > this.properties.length && + !this.base.shouldCache() && + (null == f || !f.shouldCache())) + ? [this, this] + : ((u = new t( + this.base, + this.properties.slice( + 0, + -1, + ), + )), + u.shouldCache() && + ((a = new _( + n.scope.freeVariable( + "base", + ), + )), + (u = new t( + new ft(new o(a, u)), + ))), + !f) + ? [u, a] + : (f.shouldCache() && + ((l = new _( + n.scope.freeVariable( + "name", + ), + )), + (f = new R( + new o(l, f.index), + )), + (l = new R(l))), + [ + u.add(f), + new t(a || u.base, [ + l || f, + ]), + ]); + }, + }, + { + key: "compileNode", + value: function (t) { + var n, r, i, s, o; + for ( + this.base.front = this.front, + o = this.properties, + n = + o.length && + null != this.base.cached + ? this.base.cached + : this.base.compileToFragments( + t, + o.length + ? W + : null, + ), + o.length && + mt.test(Xt(n)) && + n.push( + this.makeCode("."), + ), + r = 0, + i = o.length; + r < i; + r++ + ) { + var u; + (s = o[r]), + (u = n).push.apply( + u, + _toConsumableArray( + s.compileToFragments( + t, + ), + ), + ); + } + return n; + }, + }, + { + key: "unfoldSoak", + value: function (n) { + var r = this; + return null == this.unfoldedSoak + ? (this.unfoldedSoak = + (function () { + var e, + i, + s, + u, + a, + f, + l, + c, + h; + if ( + ((s = + r.base.unfoldSoak( + n, + )), + s) + ) { + var p; + return ( + (p = + s.body + .properties).push.apply( + p, + _toConsumableArray( + r.properties, + ), + ), + s + ); + } + for ( + c = r.properties, + i = u = 0, + a = c.length; + u < a; + i = ++u + ) + if ( + ((f = c[i]), + !!f.soak) + ) + return ( + (f.soak = + !1), + (e = + new t( + r.base, + r.properties.slice( + 0, + i, + ), + )), + (h = + new t( + r.base, + r.properties.slice( + i, + ), + )), + e.shouldCache() && + ((l = + new _( + n.scope.freeVariable( + "ref", + ), + )), + (e = + new ft( + new o( + l, + e, + ), + )), + (h.base = + l)), + new D( + new b( + e, + ), + h, + { + soak: !0, + }, + ) + ); + return !1; + })()) + : this.unfoldedSoak; + }, + }, + { + key: "eachName", + value: function (t) { + return this.hasProperties() + ? t(this) + : this.base.isAssignable() + ? this.base.eachName(t) + : this.error( + "tried to assign to unassignable value", + ); + }, + }, + ]), + t + ); + })(a); + return ( + (e.prototype.children = ["base", "properties"]), e + ); + }.call(this)), + (e.HereComment = O = + (function (e) { + function n(e) { + var t = e.content, + r = e.newLine, + i = e.unshift; + _classCallCheck(this, n); + var s = _possibleConstructorReturn( + this, + (n.__proto__ || Object.getPrototypeOf(n)).call( + this, + ), + ); + return ( + (s.content = t), + (s.newLine = r), + (s.unshift = i), + s + ); + } + return ( + _inherits(n, e), + _createClass(n, [ + { + key: "compileNode", + value: function () { + var n, r, i, s, o, u, a, f, l; + if ( + ((f = + 0 <= + t.call(this.content, "\n")), + (r = /\n\s*[#|\*]/.test( + this.content, + )), + r && + (this.content = + this.content.replace( + /^([ \t]*)#(?=\s)/gm, + " *", + )), + f) + ) { + for ( + s = "", + l = + this.content.split( + "\n", + ), + i = 0, + u = l.length; + i < u; + i++ + ) + (a = l[i]), + (o = /^\s*/.exec(a)[0]), + o.length > s.length && + (s = o); + this.content = this.content.replace( + RegExp("^(" + o + ")", "gm"), + "", + ); + } + return ( + (this.content = + "/*" + + this.content + + (r ? " " : "") + + "*/"), + (n = this.makeCode(this.content)), + (n.newLine = this.newLine), + (n.unshift = this.unshift), + (n.multiline = f), + (n.isComment = n.isHereComment = + !0), + n + ); + }, + }, + ]), + n + ); + })(a)), + (e.LineComment = Q = + (function (e) { + function t(e) { + var n = e.content, + r = e.newLine, + i = e.unshift; + _classCallCheck(this, t); + var s = _possibleConstructorReturn( + this, + (t.__proto__ || Object.getPrototypeOf(t)).call( + this, + ), + ); + return ( + (s.content = n), + (s.newLine = r), + (s.unshift = i), + s + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function () { + var t; + return ( + (t = this.makeCode( + /^\s*$/.test(this.content) + ? "" + : "//" + this.content, + )), + (t.newLine = this.newLine), + (t.unshift = this.unshift), + (t.trail = + !this.newLine && !this.unshift), + (t.isComment = t.isLineComment = + !0), + t + ); + }, + }, + ]), + t + ); + })(a)), + (e.Call = h = + function () { + var e = (function (e) { + function t(e) { + var n = + 1 < arguments.length && + void 0 !== arguments[1] + ? arguments[1] + : [], + r = arguments[2], + i = arguments[3]; + _classCallCheck(this, t); + var s = _possibleConstructorReturn( + this, + ( + t.__proto__ || + Object.getPrototypeOf(t) + ).call(this), + ), + o; + return ( + (s.variable = e), + (s.args = n), + (s.soak = r), + (s.token = i), + (s.isNew = !1), + s.variable instanceof Pt && + s.variable.isNotCallable() && + s.variable.error( + "literal is not a function", + ), + (s.csx = s.variable.base instanceof c), + "RegExp" === + (null == (o = s.variable.base) + ? void 0 + : o.value) && + 0 !== s.args.length && + Zt(s.variable, s.args[0]), + s + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "updateLocationDataIfMissing", + value: function (n) { + var r, i; + return ( + this.locationData && + this + .needsUpdatedStartLocation && + ((this.locationData.first_line = + n.first_line), + (this.locationData.first_column = + n.first_column), + (r = + (null == + (i = this.variable) + ? void 0 + : i.base) || + this.variable), + r.needsUpdatedStartLocation && + ((this.variable.locationData.first_line = + n.first_line), + (this.variable.locationData.first_column = + n.first_column), + r.updateLocationDataIfMissing( + n, + )), + delete this + .needsUpdatedStartLocation), + _get( + t.prototype.__proto__ || + Object.getPrototypeOf( + t.prototype, + ), + "updateLocationDataIfMissing", + this, + ).call(this, n) + ); + }, + }, + { + key: "newInstance", + value: function () { + var n, r; + return ( + (n = + (null == (r = this.variable) + ? void 0 + : r.base) || + this.variable), + n instanceof t && !n.isNew + ? n.newInstance() + : (this.isNew = !0), + (this.needsUpdatedStartLocation = + !0), + this + ); + }, + }, + { + key: "unfoldSoak", + value: function (n) { + var r, i, s, o, u, a, f, l; + if (this.soak) { + if (this.variable instanceof xt) + (o = new G( + this.variable.compile( + n, + ), + )), + (l = new Pt(o)), + null == + this.variable + .accessor && + this.variable.error( + "Unsupported reference to 'super'", + ); + else { + if ( + (i = on( + n, + this, + "variable", + )) + ) + return i; + var c = new Pt( + this.variable, + ).cacheReference(n), + h = _slicedToArray( + c, + 2, + ); + (o = h[0]), (l = h[1]); + } + return ( + (l = new t(l, this.args)), + (l.isNew = this.isNew), + (o = new G( + "typeof " + + o.compile(n) + + ' === "function"', + )), + new D(o, new Pt(l), { + soak: !0, + }) + ); + } + for (r = this, a = []; ; ) { + if (r.variable instanceof t) { + a.push(r), (r = r.variable); + continue; + } + if (!(r.variable instanceof Pt)) + break; + if ( + (a.push(r), + !( + (r = + r.variable + .base) instanceof + t + )) + ) + break; + } + for ( + f = a.reverse(), + s = 0, + u = f.length; + s < u; + s++ + ) + (r = f[s]), + i && + (r.variable instanceof t + ? (r.variable = i) + : (r.variable.base = + i)), + (i = on(n, r, "variable")); + return i; + }, + }, + { + key: "compileNode", + value: function (t) { + var n, + r, + s, + o, + u, + a, + f, + l, + c, + h, + p, + v, + m, + g, + y; + if (this.csx) + return this.compileCSX(t); + if ( + (null != (p = this.variable) && + (p.front = this.front), + (f = []), + (y = + (null == + (v = this.variable) || + null == (m = v.properties) + ? void 0 + : m[0]) instanceof i), + (o = function () { + var e, t, n, r; + for ( + n = this.args || [], + r = [], + e = 0, + t = n.length; + e < t; + e++ + ) + (s = n[e]), + s instanceof d && + r.push(s); + return r; + }.call(this)), + 0 < o.length && + y && + !this.variable.base.cached) + ) { + var b = + this.variable.base.cache( + t, + W, + function () { + return !1; + }, + ), + w = _slicedToArray(b, 1); + (a = w[0]), + (this.variable.base.cached = + a); + } + for ( + g = this.args, + u = c = 0, + h = g.length; + c < h; + u = ++c + ) { + var E; + (s = g[u]), + u && + f.push( + this.makeCode(", "), + ), + (E = f).push.apply( + E, + _toConsumableArray( + s.compileToFragments( + t, + V, + ), + ), + ); + } + return ( + (l = []), + this.isNew && + (this.variable instanceof + xt && + this.variable.error( + "Unsupported reference to 'super'", + ), + l.push( + this.makeCode("new "), + )), + (n = l).push.apply( + n, + _toConsumableArray( + this.variable.compileToFragments( + t, + W, + ), + ), + ), + (r = l).push.apply( + r, + [this.makeCode("(")].concat( + _toConsumableArray(f), + [this.makeCode(")")], + ), + ), + l + ); + }, + }, + { + key: "compileCSX", + value: function (t) { + var n = _slicedToArray( + this.args, + 2, + ), + r, + i, + o, + u, + a, + f, + l, + c, + h, + p, + d; + if ( + ((u = n[0]), + (a = n[1]), + (u.base.csx = !0), + null != a && (a.base.csx = !0), + (f = [this.makeCode("<")]), + (r = f).push.apply( + r, + _toConsumableArray( + (d = + this.variable.compileToFragments( + t, + W, + )), + ), + ), + u.base instanceof s) + ) + for ( + p = u.base.objects, + l = 0, + c = p.length; + l < c; + l++ + ) { + var v; + (h = p[l]), + (i = h.base), + (o = + (null == i + ? void 0 + : i.properties) || + []), + ((i instanceof ot || + i instanceof _) && + (!( + i instanceof ot + ) || + i.generated || + (!( + 1 < o.length + ) && + o[0] instanceof + bt))) || + h.error( + 'Unexpected token. Allowed CSX attributes are: id="val", src={source}, {props...} or attribute.', + ), + h.base instanceof ot && + (h.base.csx = !0), + f.push( + this.makeCode(" "), + ), + (v = f).push.apply( + v, + _toConsumableArray( + h.compileToFragments( + t, + J, + ), + ), + ); + } + if (a) { + var m, g; + f.push(this.makeCode(">")), + (m = f).push.apply( + m, + _toConsumableArray( + a.compileNode(t, V), + ), + ), + (g = f).push.apply( + g, + [ + this.makeCode("", + ), + ], + ), + ); + } else f.push(this.makeCode(" />")); + return f; + }, + }, + ]), + t + ); + })(a); + return (e.prototype.children = ["variable", "args"]), e; + }.call(this)), + (e.SuperCall = Tt = + function () { + var e = (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || + Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "isStatement", + value: function (t) { + var n; + return ( + (null == (n = this.expressions) + ? void 0 + : n.length) && t.level === K + ); + }, + }, + { + key: "compileNode", + value: function (n) { + var r, i, s, o; + if ( + null == + (i = this.expressions) || + !i.length + ) + return _get( + t.prototype.__proto__ || + Object.getPrototypeOf( + t.prototype, + ), + "compileNode", + this, + ).call(this, n); + if ( + ((o = new G( + Xt( + _get( + t.prototype + .__proto__ || + Object.getPrototypeOf( + t.prototype, + ), + "compileNode", + this, + ).call(this, n), + ), + )), + (s = new f( + this.expressions.slice(), + )), + n.level > K) + ) { + var u = o.cache(n, null, Bt), + a = _slicedToArray(u, 2); + (o = a[0]), + (r = a[1]), + s.push(r); + } + return ( + s.unshift(o), + s.compileToFragments( + n, + n.level === K ? n.level : V, + ) + ); + }, + }, + ]), + t + ); + })(h); + return ( + (e.prototype.children = h.prototype.children.concat( + ["expressions"], + )), + e + ); + }.call(this)), + (e.Super = xt = + function () { + var e = (function (e) { + function t(e) { + _classCallCheck(this, t); + var n = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return (n.accessor = e), n; + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (t) { + var n, r, i, s, u, a, f, l; + if ( + ((r = t.scope.namedMethod()), + (null == r + ? void 0 + : r.isMethod) || + this.error( + "cannot use super outside of an instance method", + ), + null == r.ctor && + null == this.accessor) + ) { + var c = r; + (i = c.name), + (l = c.variable), + (i.shouldCache() || + (i instanceof R && + i.index.isAssignable())) && + ((s = new _( + t.scope.parent.freeVariable( + "name", + ), + )), + (i.index = new o( + s, + i.index, + ))), + (this.accessor = + null == s + ? i + : new R(s)); + } + return ( + (null == (u = this.accessor) || + null == (a = u.name) + ? void 0 + : a.comments) && + ((f = + this.accessor.name + .comments), + delete this.accessor.name + .comments), + (n = new Pt( + new G("super"), + this.accessor + ? [this.accessor] + : [], + ).compileToFragments(t)), + f && It(f, this.accessor.name), + n + ); + }, + }, + ]), + t + ); + })(a); + return (e.prototype.children = ["accessor"]), e; + }.call(this)), + (e.RegexWithInterpolations = dt = + (function (e) { + function t() { + var e = + 0 < arguments.length && void 0 !== arguments[0] + ? arguments[0] + : []; + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call( + this, + new Pt(new _("RegExp")), + e, + !1, + ), + ) + ); + } + return _inherits(t, e), t; + })(h)), + (e.TaggedTemplateCall = Lt = + (function (e) { + function t(e, n, r) { + return ( + _classCallCheck(this, t), + n instanceof Et && + (n = new St(f.wrap([new Pt(n)]))), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this, e, [n], r), + ) + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (t) { + return this.variable + .compileToFragments(t, W) + .concat( + this.args[0].compileToFragments( + t, + V, + ), + ); + }, + }, + ]), + t + ); + })(h)), + (e.Extends = k = + function () { + var e = (function (e) { + function t(e, n) { + _classCallCheck(this, t); + var r = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return (r.child = e), (r.parent = n), r; + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileToFragments", + value: function (t) { + return new h( + new Pt(new G(an("extend", t))), + [this.child, this.parent], + ).compileToFragments(t); + }, + }, + ]), + t + ); + })(a); + return (e.prototype.children = ["child", "parent"]), e; + }.call(this)), + (e.Access = i = + function () { + var e = (function (e) { + function t(e, n) { + _classCallCheck(this, t); + var r = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return (r.name = e), (r.soak = "soak" === n), r; + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileToFragments", + value: function (t) { + var n, r; + return ( + (n = + this.name.compileToFragments( + t, + )), + (r = this.name.unwrap()), + r instanceof ct + ? [ + this.makeCode("."), + ].concat( + _toConsumableArray(n), + ) + : [ + this.makeCode("["), + ].concat( + _toConsumableArray(n), + [this.makeCode("]")], + ) + ); + }, + }, + ]), + t + ); + })(a); + return ( + (e.prototype.children = ["name"]), + (e.prototype.shouldCache = nt), + e + ); + }.call(this)), + (e.Index = R = + function () { + var e = (function (e) { + function t(e) { + _classCallCheck(this, t); + var n = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return (n.index = e), n; + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileToFragments", + value: function (t) { + return [].concat( + this.makeCode("["), + this.index.compileToFragments( + t, + J, + ), + this.makeCode("]"), + ); + }, + }, + { + key: "shouldCache", + value: function () { + return this.index.shouldCache(); + }, + }, + ]), + t + ); + })(a); + return (e.prototype.children = ["index"]), e; + }.call(this)), + (e.Range = ht = + function () { + var e = (function (e) { + function t(e, n, r) { + _classCallCheck(this, t); + var i = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return ( + (i.from = e), + (i.to = n), + (i.exclusive = "exclusive" === r), + (i.equals = i.exclusive ? "" : "="), + i + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileVariables", + value: function (t) { + var n, r; + (t = Yt(t, { top: !0 })), + (n = Rt(t, "shouldCache")); + var i = this.cacheToCodeFragments( + this.from.cache(t, V, n), + ), + s = _slicedToArray(i, 2); + (this.fromC = s[0]), + (this.fromVar = s[1]); + var o = this.cacheToCodeFragments( + this.to.cache(t, V, n), + ), + u = _slicedToArray(o, 2); + if ( + ((this.toC = u[0]), + (this.toVar = u[1]), + (r = Rt(t, "step"))) + ) { + var a = + this.cacheToCodeFragments( + r.cache(t, V, n), + ), + f = _slicedToArray(a, 2); + (this.step = f[0]), + (this.stepVar = f[1]); + } + return ( + (this.fromNum = + this.from.isNumber() + ? +this.fromVar + : null), + (this.toNum = this.to.isNumber() + ? +this.toVar + : null), + (this.stepNum = ( + null == r + ? void 0 + : r.isNumber() + ) + ? +this.stepVar + : null) + ); + }, + }, + { + key: "compileNode", + value: function (t) { + var n, + r, + i, + s, + o, + u, + a, + f, + l, + c, + h, + p, + d, + v, + m; + if ( + (this.fromVar || + this.compileVariables(t), + !t.index) + ) + return this.compileArray(t); + (a = + null != this.fromNum && + null != this.toNum), + (o = Rt(t, "index")), + (u = Rt(t, "name")), + (c = u && u !== o), + (m = + a && !c + ? "var " + + o + + " = " + + this.fromC + : o + + " = " + + this.fromC), + this.toC !== this.toVar && + (m += ", " + this.toC), + this.step !== this.stepVar && + (m += ", " + this.step), + (l = o + " <" + this.equals), + (s = o + " >" + this.equals); + var g = [this.fromNum, this.toNum]; + return ( + (i = g[0]), + (d = g[1]), + (h = this.stepNum + ? this.stepNum + " !== 0" + : this.stepVar + " !== 0"), + (r = a + ? null == this.step + ? i <= d + ? l + " " + d + : s + " " + d + : ((f = + i + + " <= " + + o + + " && " + + l + + " " + + d), + (v = + i + + " >= " + + o + + " && " + + s + + " " + + d), + i <= d + ? h + " && " + f + : h + " && " + v) + : ((f = + this.fromVar + + " <= " + + o + + " && " + + l + + " " + + this.toVar), + (v = + this.fromVar + + " >= " + + o + + " && " + + s + + " " + + this.toVar), + h + + " && (" + + this.fromVar + + " <= " + + this.toVar + + " ? " + + f + + " : " + + v + + ")")), + (n = this.stepVar + ? this.stepVar + " > 0" + : this.fromVar + + " <= " + + this.toVar), + (p = this.stepVar + ? o + " += " + this.stepVar + : a + ? c + ? i <= d + ? "++" + o + : "--" + o + : i <= d + ? o + "++" + : o + "--" + : c + ? n + + " ? ++" + + o + + " : --" + + o + : n + + " ? " + + o + + "++ : " + + o + + "--"), + c && (m = u + " = " + m), + c && (p = u + " = " + p), + [ + this.makeCode( + m + "; " + r + "; " + p, + ), + ] + ); + }, + }, + { + key: "compileArray", + value: function (t) { + var n, + r, + i, + s, + o, + u, + a, + f, + l, + c, + h, + p, + d; + return ((a = + null != this.fromNum && + null != this.toNum), + a && + 20 >= + _Mathabs( + this.fromNum - + this.toNum, + )) + ? ((c = function () { + for ( + var e = [], + t = (h = + this.fromNum), + n = this.toNum; + h <= n + ? t <= n + : t >= n; + h <= n ? t++ : t-- + ) + e.push(t); + return e; + }.apply(this)), + this.exclusive && c.pop(), + [ + this.makeCode( + "[" + + c.join(", ") + + "]", + ), + ]) + : ((u = this.tab + Ct), + (o = t.scope.freeVariable( + "i", + { + single: !0, + reserve: !1, + }, + )), + (p = t.scope.freeVariable( + "results", + { reserve: !1 }, + )), + (l = + "\n" + + u + + "var " + + p + + " = [];"), + a + ? ((t.index = o), + (r = Xt( + this.compileNode(t), + ))) + : ((d = + o + + " = " + + this.fromC + + (this.toC === + this.toVar + ? "" + : ", " + + this.toC)), + (i = + this.fromVar + + " <= " + + this.toVar), + (r = + "var " + + d + + "; " + + i + + " ? " + + o + + " <" + + this.equals + + " " + + this.toVar + + " : " + + o + + " >" + + this.equals + + " " + + this.toVar + + "; " + + i + + " ? " + + o + + "++ : " + + o + + "--")), + (f = + "{ " + + p + + ".push(" + + o + + "); }\n" + + u + + "return " + + p + + ";\n" + + t.indent), + (s = function (e) { + return null == e + ? void 0 + : e.contains(Jt); + }), + (s(this.from) || + s(this.to)) && + (n = ", arguments"), + [ + this.makeCode( + "(function() {" + + l + + "\n" + + u + + "for (" + + r + + ")" + + f + + "}).apply(this" + + (null == n + ? "" + : n) + + ")", + ), + ]); + }, + }, + ]), + t + ); + })(a); + return (e.prototype.children = ["from", "to"]), e; + }.call(this)), + (e.Slice = yt = + function () { + var e = (function (e) { + function t(e) { + _classCallCheck(this, t); + var n = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return (n.range = e), n; + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (t) { + var n = this.range, + r, + i, + s, + o, + u, + a; + return ( + (u = n.to), + (s = n.from), + (null == s + ? void 0 + : s.shouldCache()) && + (s = new Pt(new ft(s))), + (null == u + ? void 0 + : u.shouldCache()) && + (u = new Pt(new ft(u))), + (o = (null == s + ? void 0 + : s.compileToFragments( + t, + J, + )) || [ + this.makeCode("0"), + ]), + u && + ((r = u.compileToFragments( + t, + J, + )), + (i = Xt(r)), + (this.range.exclusive || + -1 != +i) && + (a = + ", " + + (this.range + .exclusive + ? i + : u.isNumber() + ? "" + + (+i + 1) + : ((r = + u.compileToFragments( + t, + W, + )), + "+" + + Xt(r) + + " + 1 || 9e9")))), + [ + this.makeCode( + ".slice(" + + Xt(o) + + (a || "") + + ")", + ), + ] + ); + }, + }, + ]), + t + ); + })(a); + return (e.prototype.children = ["range"]), e; + }.call(this)), + (e.Obj = ot = + function () { + var e = (function (e) { + function t(e) { + var n = + 1 < arguments.length && + void 0 !== arguments[1] && + arguments[1], + r = + 2 < arguments.length && + void 0 !== arguments[2] && + arguments[2]; + _classCallCheck(this, t); + var i = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return ( + (i.generated = n), + (i.lhs = r), + (i.objects = i.properties = e || []), + i + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "isAssignable", + value: function () { + var t, n, r, i, s; + for ( + s = this.properties, + t = 0, + n = s.length; + t < n; + t++ + ) + if ( + ((i = s[t]), + (r = Qt( + i.unwrapAll().value, + )), + r && i.error(r), + i instanceof o && + "object" === + i.context && + (i = i.value), + !i.isAssignable()) + ) + return !1; + return !0; + }, + }, + { + key: "shouldCache", + value: function () { + return !this.isAssignable(); + }, + }, + { + key: "hasSplat", + value: function () { + var t, n, r, i; + for ( + i = this.properties, + t = 0, + n = i.length; + t < n; + t++ + ) + if ( + ((r = i[t]), + r instanceof bt) + ) + return !0; + return !1; + }, + }, + { + key: "compileNode", + value: function (n) { + var r, + i, + u, + a, + f, + l, + c, + h, + p, + d, + v, + g, + y, + b, + w, + E, + S, + x, + T, + N, + C, + k; + if ( + ((x = this.properties), + this.generated) + ) + for ( + l = 0, g = x.length; + l < g; + l++ + ) + (E = x[l]), + E instanceof Pt && + E.error( + "cannot have an implicit value in an implicit object", + ); + if (this.hasSplat() && !this.csx) + return this.compileSpread(n); + if ( + ((u = n.indent += Ct), + (v = this.lastNode( + this.properties, + )), + this.csx) + ) + return this.compileCSXAttributes( + n, + ); + if (this.lhs) + for ( + h = 0, y = x.length; + h < y; + h++ + ) + if ( + ((S = x[h]), + S instanceof o) + ) { + var L = S; + (k = L.value), + (C = k.unwrapAll()), + C instanceof s || + C instanceof t + ? (C.lhs = !0) + : C instanceof + o && + (C.nestedLhs = + !0); + } + for ( + f = !0, + N = this.properties, + d = 0, + b = N.length; + d < b; + d++ + ) + (S = N[d]), + S instanceof o && + "object" === + S.context && + (f = !1); + for ( + r = [], + r.push( + this.makeCode( + f ? "" : "\n", + ), + ), + i = T = 0, + w = x.length; + T < w; + i = ++T + ) { + var A; + if ( + ((S = x[i]), + (c = + i === x.length - 1 + ? "" + : f + ? ", " + : S === v + ? "\n" + : ",\n"), + (a = f ? "" : u), + (p = + S instanceof o && + "object" === S.context + ? S.variable + : S instanceof o + ? (this.lhs + ? void 0 + : S.operatorToken.error( + "unexpected " + + S + .operatorToken + .value, + ), + S.variable) + : S), + p instanceof Pt && + p.hasProperties() && + (("object" === + S.context || + !p.this) && + p.error( + "invalid object key", + ), + (p = + p.properties[0] + .name), + (S = new o( + p, + S, + "object", + ))), + p === S) + ) + if (S.shouldCache()) { + var O = S.base.cache(n), + M = _slicedToArray( + O, + 2, + ); + (p = M[0]), + (k = M[1]), + p instanceof _ && + (p = new ct( + p.value, + )), + (S = new o( + p, + k, + "object", + )); + } else if ( + p instanceof Pt && + p.base instanceof m + ) + if ( + S.base.value.shouldCache() + ) { + var D = + S.base.value.cache( + n, + ), + P = + _slicedToArray( + D, + 2, + ); + (p = P[0]), + (k = P[1]), + p instanceof + _ && + (p = new m( + p.value, + )), + (S = new o( + p, + k, + "object", + )); + } else + S = new o( + p, + S.base.value, + "object", + ); + else + ("function" == + typeof S.bareLiteral && + S.bareLiteral(_)) || + (S = new o( + S, + S, + "object", + )); + a && r.push(this.makeCode(a)), + (A = r).push.apply( + A, + _toConsumableArray( + S.compileToFragments( + n, + K, + ), + ), + ), + c && + r.push( + this.makeCode(c), + ); + } + return ( + r.push( + this.makeCode( + f + ? "" + : "\n" + this.tab, + ), + ), + (r = this.wrapInBraces(r)), + this.front + ? this.wrapInParentheses(r) + : r + ); + }, + }, + { + key: "assigns", + value: function (t) { + var n, r, i, s; + for ( + s = this.properties, + n = 0, + r = s.length; + n < r; + n++ + ) + if (((i = s[n]), i.assigns(t))) + return !0; + return !1; + }, + }, + { + key: "eachName", + value: function (t) { + var n, r, i, s, u; + for ( + s = this.properties, + u = [], + n = 0, + r = s.length; + n < r; + n++ + ) + (i = s[n]), + i instanceof o && + "object" === + i.context && + (i = i.value), + (i = i.unwrapAll()), + null == i.eachName + ? u.push(void 0) + : u.push(i.eachName(t)); + return u; + }, + }, + { + key: "compileSpread", + value: function (n) { + var r, i, s, o, u, a, f, l, c; + for ( + f = this.properties, + c = [], + a = [], + l = [], + i = function () { + if ( + (a.length && + l.push( + new t(a), + ), + c.length) + ) { + var e; + (e = l).push.apply( + e, + _toConsumableArray( + c, + ), + ); + } + return ( + (c = []), (a = []) + ); + }, + s = 0, + o = f.length; + s < o; + s++ + ) + (u = f[s]), + u instanceof bt + ? (c.push( + new Pt(u.name), + ), + i()) + : a.push(u); + return ( + i(), + l[0] instanceof t || + l.unshift(new t()), + (r = new Pt( + new G(an("_extends", n)), + )), + new h(r, l).compileToFragments( + n, + ) + ); + }, + }, + { + key: "compileCSXAttributes", + value: function (t) { + var n, r, i, s, o, u, a; + for ( + a = this.properties, + n = [], + r = i = 0, + o = a.length; + i < o; + r = ++i + ) { + var f; + (u = a[r]), + (u.csx = !0), + (s = + r === a.length - 1 + ? "" + : " "), + u instanceof bt && + (u = new G( + "{" + + u.compile(t) + + "}", + )), + (f = n).push.apply( + f, + _toConsumableArray( + u.compileToFragments( + t, + K, + ), + ), + ), + n.push(this.makeCode(s)); + } + return this.front + ? this.wrapInParentheses(n) + : n; + }, + }, + ]), + t + ); + })(a); + return (e.prototype.children = ["properties"]), e; + }.call(this)), + (e.Arr = s = + function () { + var e = (function (e) { + function n(e) { + var t = + 1 < arguments.length && + void 0 !== arguments[1] && + arguments[1]; + _classCallCheck(this, n); + var r = _possibleConstructorReturn( + this, + ( + n.__proto__ || Object.getPrototypeOf(n) + ).call(this), + ); + return (r.lhs = t), (r.objects = e || []), r; + } + return ( + _inherits(n, e), + _createClass(n, [ + { + key: "hasElision", + value: function () { + var t, n, r, i; + for ( + i = this.objects, + t = 0, + n = i.length; + t < n; + t++ + ) + if ( + ((r = i[t]), r instanceof g) + ) + return !0; + return !1; + }, + }, + { + key: "isAssignable", + value: function () { + var t, n, r, i, s; + if (!this.objects.length) return !1; + for ( + s = this.objects, + t = n = 0, + r = s.length; + n < r; + t = ++n + ) { + if ( + ((i = s[t]), + i instanceof bt && + t + 1 !== + this.objects.length) + ) + return !1; + if ( + !i.isAssignable() || + (!!i.isAtomic && + !i.isAtomic()) + ) + return !1; + } + return !0; + }, + }, + { + key: "shouldCache", + value: function () { + return !this.isAssignable(); + }, + }, + { + key: "compileNode", + value: function (r) { + var i, + s, + o, + u, + a, + f, + l, + c, + h, + p, + d, + v, + m, + g, + y, + b, + w, + E, + S, + x, + T, + N, + C, + k; + if (!this.objects.length) + return [this.makeCode("[]")]; + for ( + r.indent += Ct, + a = function (e) { + return ( + "," === Xt(e).trim() + ); + }, + x = !1, + i = [], + C = this.objects, + E = h = 0, + v = C.length; + h < v; + E = ++h + ) + (w = C[E]), + (k = w.unwrapAll()), + k.comments && + 0 === + k.comments.filter( + function (e) { + return !e.here; + }, + ).length && + (k.includeCommentFragments = + Bt), + this.lhs && + (k instanceof n || + k instanceof ot) && + (k.lhs = !0); + for ( + s = function () { + var e, t, n, i; + for ( + n = this.objects, + i = [], + e = 0, + t = n.length; + e < t; + e++ + ) + (w = n[e]), + i.push( + w.compileToFragments( + r, + V, + ), + ); + return i; + }.call(this), + S = s.length, + l = !1, + c = p = 0, + m = s.length; + p < m; + c = ++p + ) { + var L; + for ( + f = s[c], + d = 0, + g = f.length; + d < g; + d++ + ) + (o = f[d]), + o.isHereComment + ? (o.code = + o.code.trim()) + : 0 !== c && + !1 === l && + Vt(o) && + (l = !0); + 0 !== c && + x && + (!a(f) || c === S - 1) && + i.push(this.makeCode(", ")), + (x = x || !a(f)), + (L = i).push.apply( + L, + _toConsumableArray(f), + ); + } + if (l || 0 <= t.call(Xt(i), "\n")) { + for ( + u = T = 0, y = i.length; + T < y; + u = ++T + ) + (o = i[u]), + o.isHereComment + ? (o.code = + en( + o.code, + r.indent, + !1, + ) + + "\n" + + r.indent) + : ", " === o.code && + (null == o || + !o.isElision) && + (o.code = + ",\n" + + r.indent); + i.unshift( + this.makeCode( + "[\n" + r.indent, + ), + ), + i.push( + this.makeCode( + "\n" + + this.tab + + "]", + ), + ); + } else { + for ( + N = 0, b = i.length; + N < b; + N++ + ) + (o = i[N]), + o.isHereComment && + (o.code += " "); + i.unshift(this.makeCode("[")), + i.push(this.makeCode("]")); + } + return i; + }, + }, + { + key: "assigns", + value: function (t) { + var n, r, i, s; + for ( + s = this.objects, + n = 0, + r = s.length; + n < r; + n++ + ) + if (((i = s[n]), i.assigns(t))) + return !0; + return !1; + }, + }, + { + key: "eachName", + value: function (t) { + var n, r, i, s, o; + for ( + s = this.objects, + o = [], + n = 0, + r = s.length; + n < r; + n++ + ) + (i = s[n]), + (i = i.unwrapAll()), + o.push(i.eachName(t)); + return o; + }, + }, + ]), + n + ); + })(a); + return (e.prototype.children = ["objects"]), e; + }.call(this)), + (e.Class = p = + function () { + var e = (function (e) { + function s(e, t) { + var n = + 2 < arguments.length && + void 0 !== arguments[2] + ? arguments[2] + : new f(); + _classCallCheck(this, s); + var r = _possibleConstructorReturn( + this, + ( + s.__proto__ || Object.getPrototypeOf(s) + ).call(this), + ); + return ( + (r.variable = e), + (r.parent = t), + (r.body = n), + r + ); + } + return ( + _inherits(s, e), + _createClass(s, [ + { + key: "compileNode", + value: function (t) { + var n, r, i; + if ( + ((this.name = + this.determineName()), + (n = this.walkBody()), + this.parent instanceof Pt && + !this.parent.hasProperties() && + (i = + this.parent.base.value), + (this.hasNameClash = + null != this.name && + this.name === i), + (r = this), + n || this.hasNameClash + ? (r = new y(r, n)) + : null == this.name && + t.level === K && + (r = new ft(r)), + this.boundMethods.length && + this.parent && + (null == this.variable && + (this.variable = new _( + t.scope.freeVariable( + "_class", + ), + )), + null == this.variableRef)) + ) { + var s = this.variable.cache(t), + u = _slicedToArray(s, 2); + (this.variable = u[0]), + (this.variableRef = u[1]); + } + this.variable && + (r = new o( + this.variable, + r, + null, + { + moduleDeclaration: + this + .moduleDeclaration, + }, + )), + (this.compileNode = + this.compileClassDeclaration); + try { + return r.compileToFragments(t); + } finally { + delete this.compileNode; + } + }, + }, + { + key: "compileClassDeclaration", + value: function (t) { + var n, r, i; + if ( + ((this.externalCtor || + this.boundMethods.length) && + null == this.ctor && + (this.ctor = + this.makeDefaultConstructor()), + null != (n = this.ctor) && + (n.noReturn = !0), + this.boundMethods.length && + this.proxyBoundMethods(), + (t.indent += Ct), + (i = []), + i.push(this.makeCode("class ")), + this.name && + i.push( + this.makeCode( + this.name, + ), + ), + null != + (null == (r = this.variable) + ? void 0 + : r.comments) && + this.compileCommentFragments( + t, + this.variable, + i, + ), + this.name && + i.push(this.makeCode(" ")), + this.parent) + ) { + var s; + (s = i).push.apply( + s, + [ + this.makeCode( + "extends ", + ), + ].concat( + _toConsumableArray( + this.parent.compileToFragments( + t, + ), + ), + [this.makeCode(" ")], + ), + ); + } + if ( + (i.push(this.makeCode("{")), + !this.body.isEmpty()) + ) { + var o; + (this.body.spaced = !0), + i.push(this.makeCode("\n")), + (o = i).push.apply( + o, + _toConsumableArray( + this.body.compileToFragments( + t, + K, + ), + ), + ), + i.push( + this.makeCode( + "\n" + this.tab, + ), + ); + } + return ( + i.push(this.makeCode("}")), i + ); + }, + }, + { + key: "determineName", + value: function () { + var n, s, o, u, a, f, l; + return this.variable + ? ((f = + this.variable.properties), + (n = r.call(f, -1)), + (s = _slicedToArray(n, 1)), + (l = s[0]), + n, + (a = l + ? l instanceof i && l.name + : this.variable.base), + a instanceof _ || + a instanceof ct) + ? ((u = a.value), + l || + ((o = Qt(u)), + o && + this.variable.error( + o, + )), + 0 <= t.call(z, u) + ? "_" + u + : u) + : null + : null; + }, + }, + { + key: "walkBody", + value: function () { + var t, + r, + i, + s, + o, + u, + a, + l, + c, + h, + p, + v, + m, + g, + y, + b, + w, + E; + for ( + this.ctor = null, + this.boundMethods = [], + i = null, + l = [], + o = this.body.expressions, + a = 0, + w = o.slice(), + h = 0, + v = w.length; + h < v; + h++ + ) + if ( + ((s = w[h]), + s instanceof Pt && + s.isObject(!0)) + ) { + for ( + y = s.base.properties, + u = [], + r = 0, + E = 0, + b = function () { + if (r > E) + return u.push( + new Pt( + new ot( + y.slice( + E, + r, + ), + !0, + ), + ), + ); + }; + (t = y[r]); + + ) + (c = + this.addInitializerExpression( + t, + )) && + (b(), + u.push(c), + l.push(c), + (E = r + 1)), + r++; + b(), + n.apply( + o, + [ + a, + a - a + 1, + ].concat(u), + ), + u, + (a += u.length); + } else + (c = + this.addInitializerExpression( + s, + )) && + (l.push(c), (o[a] = c)), + (a += 1); + for ( + p = 0, m = l.length; + p < m; + p++ + ) + (g = l[p]), + g instanceof d && + (g.ctor + ? (this.ctor && + g.error( + "Cannot define more than one constructor in a class", + ), + (this.ctor = g)) + : g.isStatic && + g.bound + ? (g.context = + this.name) + : g.bound && + this.boundMethods.push( + g, + )); + if (l.length !== o.length) + return ( + (this.body.expressions = + (function () { + var e, t, n; + for ( + n = [], + e = 0, + t = + l.length; + e < t; + e++ + ) + (s = l[e]), + n.push( + s.hoist(), + ); + return n; + })()), + new f(o) + ); + }, + }, + { + key: "addInitializerExpression", + value: function (t) { + return t.unwrapAll() instanceof lt + ? t + : this.validInitializerMethod(t) + ? this.addInitializerMethod(t) + : null; + }, + }, + { + key: "validInitializerMethod", + value: function (t) { + return ( + t instanceof o && + t.value instanceof d && + (("object" === t.context && + !t.variable.hasProperties()) || + (t.variable.looksStatic( + this.name, + ) && + (this.name || + !t.value.bound))) + ); + }, + }, + { + key: "addInitializerMethod", + value: function (t) { + var n, r, s; + return ( + (s = t.variable), + (n = t.value), + (n.isMethod = !0), + (n.isStatic = s.looksStatic( + this.name, + )), + n.isStatic + ? (n.name = s.properties[0]) + : ((r = s.base), + (n.name = new ( + r.shouldCache() + ? R + : i + )(r)), + n.name.updateLocationDataIfMissing( + r.locationData, + ), + "constructor" === + r.value && + (n.ctor = this.parent + ? "derived" + : "base"), + n.bound && + n.ctor && + n.error( + "Cannot define a constructor as a bound (fat arrow) function", + )), + n + ); + }, + }, + { + key: "makeDefaultConstructor", + value: function () { + var t, n, r; + return ( + (r = this.addInitializerMethod( + new o( + new Pt( + new ct( + "constructor", + ), + ), + new d(), + ), + )), + this.body.unshift(r), + this.parent && + r.body.push( + new Tt(new xt(), [ + new bt( + new _( + "arguments", + ), + ), + ]), + ), + this.externalCtor && + ((n = new Pt( + this.externalCtor, + [ + new i( + new ct("apply"), + ), + ], + )), + (t = [ + new At(), + new _("arguments"), + ]), + r.body.push(new h(n, t)), + r.body.makeReturn()), + r + ); + }, + }, + { + key: "proxyBoundMethods", + value: function () { + var t, n; + return ( + (this.ctor.thisAssignments = + function () { + var e, r, s, u; + for ( + s = + this + .boundMethods, + u = [], + e = 0, + r = s.length; + e < r; + e++ + ) + (t = s[e]), + this.parent && + (t.classVariable = + this.variableRef), + (n = new Pt( + new At(), + [t.name], + )), + u.push( + new o( + n, + new h( + new Pt( + n, + [ + new i( + new ct( + "bind", + ), + ), + ], + ), + [ + new At(), + ], + ), + ), + ); + return u; + }.call(this)), + null + ); + }, + }, + ]), + s + ); + })(a); + return ( + (e.prototype.children = [ + "variable", + "parent", + "body", + ]), + e + ); + }.call(this)), + (e.ExecutableClassBody = y = + function () { + var e = (function (e) { + function t(e) { + var n = + 1 < arguments.length && + void 0 !== arguments[1] + ? arguments[1] + : new f(); + _classCallCheck(this, t); + var r = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return (r.class = e), (r.body = n), r; + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (t) { + var n, + r, + s, + u, + a, + f, + l, + c, + p, + v, + m, + g; + return ( + (l = this.body.jumps()) && + l.error( + "Class bodies cannot contain pure statements", + ), + (s = this.body.contains(Jt)) && + s.error( + "Class bodies shouldn't reference arguments", + ), + (p = []), + (r = [new At()]), + (g = new d(p, this.body)), + (c = new ft( + new h( + new Pt(g, [ + new i( + new ct("call"), + ), + ]), + r, + ), + )), + (this.body.spaced = !0), + (t.classScope = g.makeScope( + t.scope, + )), + (this.name = + null == + (m = this.class.name) + ? t.classScope.freeVariable( + this + .defaultClassVariableName, + ) + : m), + (f = new _(this.name)), + (u = this.walkBody()), + this.setContext(), + this.class.hasNameClash && + ((v = new _( + t.classScope.freeVariable( + "superClass", + ), + )), + g.params.push(new at(v)), + r.push(this.class.parent), + (this.class.parent = v)), + this.externalCtor && + ((a = new _( + t.classScope.freeVariable( + "ctor", + { reserve: !1 }, + ), + )), + (this.class.externalCtor = + a), + (this.externalCtor.variable.base = + a)), + this.name === this.class.name + ? this.body.expressions.unshift( + this.class, + ) + : this.body.expressions.unshift( + new o( + new _(this.name), + this.class, + ), + ), + (n = + this.body + .expressions).unshift.apply( + n, + _toConsumableArray(u), + ), + this.body.push(f), + c.compileToFragments(t) + ); + }, + }, + { + key: "walkBody", + value: function () { + var t = this, + n, + r, + i; + for ( + n = [], i = 0; + (r = + this.body.expressions[i]) && + !!( + r instanceof Pt && + r.isString() + ); + + ) + if (r.hoisted) i++; + else { + var s; + (s = n).push.apply( + s, + _toConsumableArray( + this.body.expressions.splice( + i, + 1, + ), + ), + ); + } + return ( + this.traverseChildren( + !1, + function (e) { + var n, r, i, s, u, a; + if ( + e instanceof p || + e instanceof M + ) + return !1; + if ( + ((n = !0), + e instanceof f) + ) { + for ( + a = + e.expressions, + r = i = 0, + s = + a.length; + i < s; + r = ++i + ) + (u = a[r]), + u instanceof + Pt && + u.isObject( + !0, + ) + ? ((n = + !1), + (e.expressions[ + r + ] = + t.addProperties( + u + .base + .properties, + ))) + : u instanceof + o && + u.variable.looksStatic( + t.name, + ) && + (u.value.isStatic = + !0); + e.expressions = Wt( + e.expressions, + ); + } + return n; + }, + ), + n + ); + }, + }, + { + key: "setContext", + value: function () { + var t = this; + return this.body.traverseChildren( + !1, + function (e) { + return e instanceof At + ? (e.value = t.name) + : e instanceof d && + e.bound && + e.isStatic + ? (e.context = t.name) + : void 0; + }, + ); + }, + }, + { + key: "addProperties", + value: function (t) { + var n, r, s, u, a, f, l; + return ( + (a = function () { + var e, a, c; + for ( + c = [], + e = 0, + a = t.length; + e < a; + e++ + ) + (n = t[e]), + (l = n.variable), + (r = + null == l + ? void 0 + : l.base), + (f = n.value), + delete n.context, + "constructor" === + r.value + ? (f instanceof + d && + r.error( + "constructors must be defined at the top level of a class body", + ), + (n = + this.externalCtor = + new o( + new Pt(), + f, + ))) + : n.variable + .this + ? n.value instanceof + d && + (n.value.isStatic = + !0) + : ((s = new ( + r.shouldCache() + ? R + : i + )(r)), + (u = new i( + new ct( + "prototype", + ), + )), + (l = new Pt( + new At(), + [u, s], + )), + (n.variable = + l)), + c.push(n); + return c; + }.call(this)), + qt(a) + ); + }, + }, + ]), + t + ); + })(a); + return ( + (e.prototype.children = ["class", "body"]), + (e.prototype.defaultClassVariableName = "_Class"), + e + ); + }.call(this)), + (e.ModuleDeclaration = Y = + function () { + var e = (function (e) { + function t(e, n) { + _classCallCheck(this, t); + var r = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return ( + (r.clause = e), + (r.source = n), + r.checkSource(), + r + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "checkSource", + value: function () { + if ( + null != this.source && + this.source instanceof St + ) + return this.source.error( + "the name of the module to be imported from must be an uninterpolated string", + ); + }, + }, + { + key: "checkScope", + value: function (t, n) { + if (0 !== t.indent.length) + return this.error( + n + + " statements must be at top-level scope", + ); + }, + }, + ]), + t + ); + })(a); + return ( + (e.prototype.children = ["clause", "source"]), + (e.prototype.isStatement = Bt), + (e.prototype.jumps = kt), + (e.prototype.makeReturn = kt), + e + ); + }.call(this)), + (e.ImportDeclaration = H = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (t) { + var n, r; + if ( + (this.checkScope(t, "import"), + (t.importedSymbols = []), + (n = []), + n.push( + this.makeCode( + this.tab + "import ", + ), + ), + null != this.clause) + ) { + var i; + (i = n).push.apply( + i, + _toConsumableArray( + this.clause.compileNode(t), + ), + ); + } + return ( + null != + (null == (r = this.source) + ? void 0 + : r.value) && + (null !== this.clause && + n.push( + this.makeCode(" from "), + ), + n.push( + this.makeCode( + this.source.value, + ), + )), + n.push(this.makeCode(";")), + n + ); + }, + }, + ]), + t + ); + })(Y)), + (e.ImportClause = P = + function () { + var e = (function (e) { + function t(e, n) { + _classCallCheck(this, t); + var r = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return ( + (r.defaultBinding = e), + (r.namedImports = n), + r + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (t) { + var n; + if ( + ((n = []), + null != this.defaultBinding) + ) { + var r; + (r = n).push.apply( + r, + _toConsumableArray( + this.defaultBinding.compileNode( + t, + ), + ), + ), + null != this.namedImports && + n.push( + this.makeCode(", "), + ); + } + if (null != this.namedImports) { + var i; + (i = n).push.apply( + i, + _toConsumableArray( + this.namedImports.compileNode( + t, + ), + ), + ); + } + return n; + }, + }, + ]), + t + ); + })(a); + return ( + (e.prototype.children = [ + "defaultBinding", + "namedImports", + ]), + e + ); + }.call(this)), + (e.ExportDeclaration = S = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (t) { + var n, r; + return ( + this.checkScope(t, "export"), + (n = []), + n.push( + this.makeCode( + this.tab + "export ", + ), + ), + this instanceof x && + n.push( + this.makeCode("default "), + ), + !(this instanceof x) && + (this.clause instanceof o || + this.clause instanceof p) && + (this.clause instanceof p && + !this.clause.variable && + this.clause.error( + "anonymous classes cannot be exported", + ), + n.push(this.makeCode("var ")), + (this.clause.moduleDeclaration = + "export")), + (n = + null != this.clause.body && + this.clause.body instanceof f + ? n.concat( + this.clause.compileToFragments( + t, + K, + ), + ) + : n.concat( + this.clause.compileNode( + t, + ), + )), + null != + (null == (r = this.source) + ? void 0 + : r.value) && + n.push( + this.makeCode( + " from " + + this.source.value, + ), + ), + n.push(this.makeCode(";")), + n + ); + }, + }, + ]), + t + ); + })(Y)), + (e.ExportNamedDeclaration = T = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return _inherits(t, e), t; + })(S)), + (e.ExportDefaultDeclaration = x = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return _inherits(t, e), t; + })(S)), + (e.ExportAllDeclaration = E = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return _inherits(t, e), t; + })(S)), + (e.ModuleSpecifierList = et = + function () { + var e = (function (e) { + function t(e) { + _classCallCheck(this, t); + var n = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return (n.specifiers = e), n; + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (t) { + var n, r, i, s, o, u, a; + if ( + ((n = []), + (t.indent += Ct), + (r = function () { + var e, n, r, i; + for ( + r = this.specifiers, + i = [], + e = 0, + n = r.length; + e < n; + e++ + ) + (a = r[e]), + i.push( + a.compileToFragments( + t, + V, + ), + ); + return i; + }.call(this)), + 0 !== this.specifiers.length) + ) { + for ( + n.push( + this.makeCode( + "{\n" + t.indent, + ), + ), + s = o = 0, + u = r.length; + o < u; + s = ++o + ) { + var f; + (i = r[s]), + s && + n.push( + this.makeCode( + ",\n" + + t.indent, + ), + ), + (f = n).push.apply( + f, + _toConsumableArray( + i, + ), + ); + } + n.push(this.makeCode("\n}")); + } else n.push(this.makeCode("{}")); + return n; + }, + }, + ]), + t + ); + })(a); + return (e.prototype.children = ["specifiers"]), e; + }.call(this)), + (e.ImportSpecifierList = I = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return _inherits(t, e), t; + })(et)), + (e.ExportSpecifierList = C = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return _inherits(t, e), t; + })(et)), + (e.ModuleSpecifier = Z = + function () { + var e = (function (e) { + function t(e, n, r) { + _classCallCheck(this, t); + var i = _possibleConstructorReturn( + this, + ( + t.__proto__ || + Object.getPrototypeOf(t) + ).call(this), + ), + s, + o; + if ( + ((i.original = e), + (i.alias = n), + (i.moduleDeclarationType = r), + i.original.comments || + (null == (s = i.alias) + ? void 0 + : s.comments)) + ) { + if ( + ((i.comments = []), i.original.comments) + ) { + var u; + (u = i.comments).push.apply( + u, + _toConsumableArray( + i.original.comments, + ), + ); + } + if ( + null == (o = i.alias) + ? void 0 + : o.comments + ) { + var a; + (a = i.comments).push.apply( + a, + _toConsumableArray( + i.alias.comments, + ), + ); + } + } + return ( + (i.identifier = + null == i.alias + ? i.original.value + : i.alias.value), + i + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (t) { + var n; + return ( + t.scope.find( + this.identifier, + this.moduleDeclarationType, + ), + (n = []), + n.push( + this.makeCode( + this.original.value, + ), + ), + null != this.alias && + n.push( + this.makeCode( + " as " + + this.alias + .value, + ), + ), + n + ); + }, + }, + ]), + t + ); + })(a); + return ( + (e.prototype.children = ["original", "alias"]), e + ); + }.call(this)), + (e.ImportSpecifier = F = + (function (e) { + function n(e, t) { + return ( + _classCallCheck(this, n), + _possibleConstructorReturn( + this, + ( + n.__proto__ || Object.getPrototypeOf(n) + ).call(this, e, t, "import"), + ) + ); + } + return ( + _inherits(n, e), + _createClass(n, [ + { + key: "compileNode", + value: function (r) { + var i; + return ( + ((i = this.identifier), + 0 <= + t.call(r.importedSymbols, i)) || + r.scope.check(this.identifier) + ? this.error( + "'" + + this.identifier + + "' has already been declared", + ) + : r.importedSymbols.push( + this.identifier, + ), + _get( + n.prototype.__proto__ || + Object.getPrototypeOf( + n.prototype, + ), + "compileNode", + this, + ).call(this, r) + ); + }, + }, + ]), + n + ); + })(Z)), + (e.ImportDefaultSpecifier = B = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return _inherits(t, e), t; + })(F)), + (e.ImportNamespaceSpecifier = j = + (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return _inherits(t, e), t; + })(F)), + (e.ExportSpecifier = N = + (function (e) { + function t(e, n) { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this, e, n, "export"), + ) + ); + } + return _inherits(t, e), t; + })(Z)), + (e.Assign = o = + function () { + var e = (function (e) { + function r(e, t, n) { + var i = + 3 < arguments.length && + void 0 !== arguments[3] + ? arguments[3] + : {}; + _classCallCheck(this, r); + var s = _possibleConstructorReturn( + this, + ( + r.__proto__ || Object.getPrototypeOf(r) + ).call(this), + ); + return ( + (s.variable = e), + (s.value = t), + (s.context = n), + (s.param = i.param), + (s.subpattern = i.subpattern), + (s.operatorToken = i.operatorToken), + (s.moduleDeclaration = i.moduleDeclaration), + s + ); + } + return ( + _inherits(r, e), + _createClass(r, [ + { + key: "isStatement", + value: function (n) { + return ( + (null == n + ? void 0 + : n.level) === K && + null != this.context && + (this.moduleDeclaration || + 0 <= + t.call( + this.context, + "?", + )) + ); + }, + }, + { + key: "checkAssignability", + value: function (t, n) { + if ( + Object.prototype.hasOwnProperty.call( + t.scope.positions, + n.value, + ) && + "import" === + t.scope.variables[ + t.scope.positions[ + n.value + ] + ].type + ) + return n.error( + "'" + + n.value + + "' is read-only", + ); + }, + }, + { + key: "assigns", + value: function (t) { + return this[ + "object" === this.context + ? "value" + : "variable" + ].assigns(t); + }, + }, + { + key: "unfoldSoak", + value: function (t) { + return on(t, this, "variable"); + }, + }, + { + key: "compileNode", + value: function (t) { + var r = this, + i, + s, + o, + u, + a, + f, + l, + c, + h, + v, + m, + g, + y, + b, + w; + if ( + ((u = + this.variable instanceof + Pt), + u) + ) { + if ( + ((this.variable.param = + this.param), + this.variable.isArray() || + this.variable.isObject()) + ) { + if ( + ((this.variable.base.lhs = + !0), + (o = + this.variable.contains( + function (e) { + return ( + e instanceof + ot && + e.hasSplat() + ); + }, + )), + !this.variable.isAssignable() || + (this.variable.isArray() && + o)) + ) + return this.compileDestructuring( + t, + ); + if ( + (this.variable.isObject() && + o && + (f = + this.compileObjectDestruct( + t, + )), + f) + ) + return f; + } + if (this.variable.isSplice()) + return this.compileSplice( + t, + ); + if ( + "||=" === + (h = this.context) || + "&&=" === h || + "?=" === h + ) + return this.compileConditional( + t, + ); + if ( + "**=" === + (v = this.context) || + "//=" === v || + "%%=" === v + ) + return this.compileSpecialMath( + t, + ); + } + if ( + (this.context || + ((w = + this.variable.unwrapAll()), + !w.isAssignable() && + this.variable.error( + "'" + + this.variable.compile( + t, + ) + + "' can't be assigned", + ), + w.eachName(function (e) { + var n, i, s; + if ( + "function" != + typeof e.hasProperties || + !e.hasProperties() + ) + return ((s = Qt( + e.value, + )), + s && e.error(s), + r.checkAssignability( + t, + e, + ), + r.moduleDeclaration) + ? t.scope.add( + e.value, + r.moduleDeclaration, + ) + : r.param + ? t.scope.add( + e.value, + "alwaysDeclare" === + r.param + ? "var" + : "param", + ) + : (t.scope.find( + e.value, + ), + e.comments && + !t + .scope + .comments[ + e + .value + ] && + !( + r.value instanceof + p + ) && + e.comments.every( + function ( + e, + ) { + return ( + e.here && + !e.multiline + ); + }, + )) + ? ((i = + new _( + e.value, + )), + (i.comments = + e.comments), + (n = []), + r.compileCommentFragments( + t, + i, + n, + ), + (t.scope.comments[ + e.value + ] = n)) + : void 0; + })), + this.value instanceof d) + ) + if (this.value.isStatic) + this.value.name = + this.variable.properties[0]; + else if ( + 2 <= + (null == + (m = + this.variable + .properties) + ? void 0 + : m.length) + ) { + var E, S, x, T; + (g = + this.variable + .properties), + (E = g), + (S = _toArray(E)), + (l = S.slice(0)), + E, + (x = n.call(l, -2)), + (T = _slicedToArray( + x, + 2, + )), + (c = T[0]), + (a = T[1]), + x, + "prototype" === + (null == + (y = c.name) + ? void 0 + : y.value) && + (this.value.name = + a); + } + return (this.csx && + (this.value.base.csxAttribute = + !0), + (b = this.value.compileToFragments( + t, + V, + )), + (s = + this.variable.compileToFragments( + t, + V, + )), + "object" === this.context) + ? (this.variable.shouldCache() && + (s.unshift( + this.makeCode("["), + ), + s.push( + this.makeCode("]"), + )), + s.concat( + this.makeCode( + this.csx ? "=" : ": ", + ), + b, + )) + : ((i = s.concat( + this.makeCode( + " " + + (this.context || + "=") + + " ", + ), + b, + )), + t.level > V || + (u && + this.variable + .base instanceof ot && + !this.nestedLhs && + !0 !== this.param) + ? this.wrapInParentheses( + i, + ) + : i); + }, + }, + { + key: "compileObjectDestruct", + value: function (t) { + var n, + o, + u, + a, + l, + c, + p, + d, + v, + m, + g, + y; + if ( + ((o = function (e) { + var n; + if (e instanceof r) { + var i = + e.variable.cache( + t, + ), + s = _slicedToArray( + i, + 2, + ); + return ( + (e.variable = s[0]), + (n = s[1]), + n + ); + } + return e; + }), + (u = function (e) { + var n, i; + return ( + (i = o(e)), + (n = + e instanceof r && + e.variable !== i), + n || !i.isAssignable() + ? i + : new G( + "'" + + i.compileWithoutComments( + t, + ) + + "'", + ) + ); + }), + (v = function (n, a) { + var f, + l, + c, + h, + p, + d, + m, + g, + y, + b, + w; + for ( + b = [], + w = void 0, + null == + a.properties && + (a = new Pt(a)), + l = c = 0, + h = n.length; + c < h; + l = ++c + ) + if ( + ((y = n[l]), + (m = d = p = null), + y instanceof r) + ) { + if ( + "function" == + typeof (f = + y.value) + .isObject + ? f.isObject() + : void 0 + ) { + if ( + "object" !== + y.context + ) + continue; + p = + y.value.base + .properties; + } else if ( + y.value instanceof + r && + y.value.variable.isObject() + ) { + p = + y.value + .variable + .base + .properties; + var E = + y.value.value.cache( + t, + ), + S = + _slicedToArray( + E, + 2, + ); + (y.value.value = + S[0]), + (m = S[1]); + } + if (p) { + var x; + (d = new Pt( + a.base, + a.properties.concat( + [ + new i( + o( + y, + ), + ), + ], + ), + )), + m && + (d = + new Pt( + new ut( + "?", + d, + m, + ), + )), + (x = + b).push.apply( + x, + _toConsumableArray( + v( + p, + d, + ), + ), + ); + } + } else + y instanceof bt && + (null != w && + y.error( + "multiple rest elements are disallowed in object destructuring", + ), + (w = l), + b.push({ + name: y.name.unwrapAll(), + source: a, + excludeProps: + new s( + (function () { + var e, + t, + r; + for ( + r = + [], + e = 0, + t = + n.length; + e < + t; + e++ + ) + (g = + n[ + e + ]), + g !== + y && + r.push( + u( + g, + ), + ); + return r; + })(), + ), + })); + return ( + null != w && + n.splice(w, 1), + b + ); + }), + (y = this.value.shouldCache() + ? new _( + t.scope.freeVariable( + "ref", + { reserve: !1 }, + ), + ) + : this.value.base), + (p = v( + this.variable.base + .properties, + y, + )), + !(p && 0 < p.length)) + ) + return !1; + var b = this.value.cache(t), + w = _slicedToArray(b, 2); + for ( + this.value = w[0], + g = w[1], + d = new f([this]), + a = 0, + l = p.length; + a < l; + a++ + ) + (c = p[a]), + (m = new h( + new Pt( + new G( + an( + "objectWithoutKeys", + t, + ), + ), + ), + [ + c.source, + c.excludeProps, + ], + )), + d.push( + new r( + new Pt(c.name), + m, + null, + { + param: this + .param + ? "alwaysDeclare" + : null, + }, + ), + ); + return ( + (n = d.compileToFragments(t)), + t.level === K && + (n.shift(), n.pop()), + n + ); + }, + }, + { + key: "compileDestructuring", + value: function (n) { + var o = this, + u, + a, + f, + l, + c, + p, + d, + v, + m, + y, + b, + E, + S, + x, + T, + N, + C, + k, + L, + A, + O, + M, + D, + P, + H, + B, + j, + F, + I, + q, + U, + z, + W, + X; + if ( + ((U = n.level === K), + (z = this.value), + (O = + this.variable.base.objects), + (M = O.length), + 0 === M) + ) + return ( + (f = + z.compileToFragments( + n, + )), + n.level >= $ + ? this.wrapInParentheses( + f, + ) + : f + ); + var J = O, + Q = _slicedToArray(J, 1); + return ( + (L = Q[0]), + 1 === M && + L instanceof w && + L.error( + "Destructuring assignment has no target", + ), + (I = (function () { + var e, t, n; + for ( + n = [], + E = e = 0, + t = O.length; + e < t; + E = ++e + ) + (L = O[E]), + L instanceof bt && + n.push(E); + return n; + })()), + (v = (function () { + var e, t, n; + for ( + n = [], + E = e = 0, + t = O.length; + e < t; + E = ++e + ) + (L = O[E]), + L instanceof w && + n.push(E); + return n; + })()), + (q = [].concat( + _toConsumableArray(I), + _toConsumableArray(v), + )), + 1 < q.length && + O[q.sort()[1]].error( + "multiple splats/expansions are disallowed in an assignment", + ), + (N = + 0 < + (null == I + ? void 0 + : I.length)), + (x = + 0 < + (null == v + ? void 0 + : v.length)), + (T = this.variable.isObject()), + (S = this.variable.isArray()), + (W = z.compileToFragments( + n, + V, + )), + (X = Xt(W)), + (a = []), + (!(z.unwrap() instanceof _) || + this.variable.assigns(X)) && + ((P = + n.scope.freeVariable( + "ref", + )), + a.push( + [ + this.makeCode( + P + " = ", + ), + ].concat( + _toConsumableArray( + W, + ), + ), + ), + (W = [this.makeCode(P)]), + (X = P)), + (F = function (e) { + return function (t, r) { + var s = + 2 < + arguments.length && + void 0 !== + arguments[2] && + arguments[2], + o, + u; + return ( + (o = [ + new _(t), + new st(r), + ]), + s && + o.push( + new st(s), + ), + (u = new Pt( + new _(an(e, n)), + [ + new i( + new ct( + "call", + ), + ), + ], + )), + new Pt(new h(u, o)) + ); + }; + }), + (l = F("slice")), + (c = F("splice")), + (b = function (e) { + var t, n, r; + for ( + r = [], + E = t = 0, + n = e.length; + t < n; + E = ++t + ) + (L = e[E]), + L.base instanceof + ot && + L.base.hasSplat() && + r.push(E); + return r; + }), + (y = function (e) { + var t, n, i; + for ( + i = [], + E = t = 0, + n = e.length; + t < n; + E = ++t + ) + (L = e[E]), + L instanceof r && + "object" === + L.context && + i.push(E); + return i; + }), + (A = function (e) { + var t, n; + for ( + t = 0, n = e.length; + t < n; + t++ + ) + if ( + ((L = e[t]), + !L.isAssignable()) + ) + return !0; + return !1; + }), + (p = function (e) { + return ( + b(e).length || + y(e).length || + A(e) || + 1 === M + ); + }), + (k = function (e, s, u) { + var f, c, h, p, d, v, m, y; + for ( + v = b(e), + m = [], + E = h = 0, + p = e.length; + h < p; + E = ++h + ) + if ( + ((L = e[E]), + !(L instanceof g)) + ) { + if ( + L instanceof + r && + "object" === + L.context + ) { + var w = L; + if ( + ((c = + w + .variable + .base), + (s = + w.value), + s instanceof + r) + ) { + var S = s; + s = + S.variable; + } + (c = s.this + ? s + .properties[0] + .name + : new ct( + s.unwrap().value, + )), + (f = + c.unwrap() instanceof + ct), + (y = new Pt( + z, + [ + new (f + ? i + : R)( + c, + ), + ], + )); + } else + (s = + (function () { + switch ( + !1 + ) { + case !( + L instanceof + bt + ): + return new Pt( + L.name, + ); + case 0 > + t.call( + v, + E, + ): + return new Pt( + L.base, + ); + default: + return L; + } + })()), + (y = + (function () { + switch ( + !1 + ) { + case !( + L instanceof + bt + ): + return l( + u, + E, + ); + default: + return new Pt( + new G( + u, + ), + [ + new R( + new st( + E, + ), + ), + ], + ); + } + })()); + (d = Qt( + s.unwrap() + .value, + )), + d && s.error(d), + m.push( + a.push( + new r( + s, + y, + null, + { + param: o.param, + subpattern: + !0, + }, + ).compileToFragments( + n, + V, + ), + ), + ); + } + return m; + }), + (u = function (e, t, i) { + var u; + return ( + (t = new Pt( + new s(e, !0), + )), + (u = + i instanceof Pt + ? i + : new Pt( + new G(i), + )), + a.push( + new r(t, u, null, { + param: o.param, + subpattern: !0, + }).compileToFragments( + n, + V, + ), + ) + ); + }), + (D = function (e, t, n) { + return p(e) + ? k(e, t, n) + : u(e, t, n); + }), + q.length + ? ((d = q[0]), + (C = O.slice( + 0, + d + (N ? 1 : 0), + )), + (j = O.slice(d + 1)), + 0 !== C.length && + D(C, W, X), + 0 !== j.length && + ((H = (function () { + switch (!1) { + case !N: + return c( + O[ + d + ].unwrapAll() + .value, + -1 * + j.length, + ); + case !x: + return l( + X, + -1 * + j.length, + ); + } + })()), + p(j) && + ((B = H), + (H = + n.scope.freeVariable( + "ref", + )), + a.push( + [ + this.makeCode( + H + + " = ", + ), + ].concat( + _toConsumableArray( + B.compileToFragments( + n, + V, + ), + ), + ), + )), + D(j, W, H))) + : D(O, W, X), + U || + this.subpattern || + a.push(W), + (m = this.joinFragmentArrays( + a, + ", ", + )), + n.level < V + ? m + : this.wrapInParentheses(m) + ); + }, + }, + { + key: "compileConditional", + value: function (n) { + var i = + this.variable.cacheReference( + n, + ), + s = _slicedToArray(i, 2), + o, + u, + a; + return ( + (u = s[0]), + (a = s[1]), + u.properties.length || + !(u.base instanceof G) || + u.base instanceof At || + n.scope.check( + u.base.value, + ) || + this.variable.error( + 'the variable "' + + u.base.value + + "\" can't be assigned with " + + this.context + + " because it has not been declared before", + ), + 0 <= t.call(this.context, "?") + ? ((n.isExistentialEquals = + !0), + new D(new b(u), a, { + type: "if", + }) + .addElse( + new r( + a, + this.value, + "=", + ), + ) + .compileToFragments( + n, + )) + : ((o = new ut( + this.context.slice( + 0, + -1, + ), + u, + new r( + a, + this.value, + "=", + ), + ).compileToFragments(n)), + n.level <= V + ? o + : this.wrapInParentheses( + o, + )) + ); + }, + }, + { + key: "compileSpecialMath", + value: function (t) { + var n = + this.variable.cacheReference( + t, + ), + i = _slicedToArray(n, 2), + s, + o; + return ( + (s = i[0]), + (o = i[1]), + new r( + s, + new ut( + this.context.slice( + 0, + -1, + ), + o, + this.value, + ), + ).compileToFragments(t) + ); + }, + }, + { + key: "compileSplice", + value: function (t) { + var n = + this.variable.properties.pop(), + r = n.range, + i, + s, + o, + u, + a, + f, + l, + c, + h, + p; + if ( + ((o = r.from), + (l = r.to), + (s = r.exclusive), + (c = this.variable.unwrapAll()), + c.comments && + (Zt(c, this), + delete this.variable + .comments), + (f = this.variable.compile(t)), + o) + ) { + var d = + this.cacheToCodeFragments( + o.cache(t, $), + ), + v = _slicedToArray(d, 2); + (u = v[0]), (a = v[1]); + } else u = a = "0"; + l + ? (null == o + ? void 0 + : o.isNumber()) && + l.isNumber() + ? ((l = l.compile(t) - a), + !s && (l += 1)) + : ((l = + l.compile(t, W) + + " - " + + a), + !s && (l += " + 1")) + : (l = "9e9"); + var m = this.value.cache(t, V), + g = _slicedToArray(m, 2); + return ( + (h = g[0]), + (p = g[1]), + (i = [].concat( + this.makeCode( + an("splice", t) + + ".apply(" + + f + + ", [" + + u + + ", " + + l + + "].concat(", + ), + h, + this.makeCode(")), "), + p, + )), + t.level > K + ? this.wrapInParentheses(i) + : i + ); + }, + }, + { + key: "eachName", + value: function (t) { + return this.variable + .unwrapAll() + .eachName(t); + }, + }, + ]), + r + ); + })(a); + return ( + (e.prototype.children = ["variable", "value"]), + (e.prototype.isAssignable = Bt), + e + ); + }.call(this)), + (e.FuncGlyph = A = + (function (e) { + function t(e) { + _classCallCheck(this, t); + var n = _possibleConstructorReturn( + this, + (t.__proto__ || Object.getPrototypeOf(t)).call( + this, + ), + ); + return (n.glyph = e), n; + } + return _inherits(t, e), t; + })(a)), + (e.Code = d = + function () { + var e = (function (e) { + function n(e, t, r, i) { + _classCallCheck(this, n); + var s = _possibleConstructorReturn( + this, + ( + n.__proto__ || + Object.getPrototypeOf(n) + ).call(this), + ), + o; + return ( + (s.funcGlyph = r), + (s.paramStart = i), + (s.params = e || []), + (s.body = t || new f()), + (s.bound = + "=>" === + (null == (o = s.funcGlyph) + ? void 0 + : o.glyph)), + (s.isGenerator = !1), + (s.isAsync = !1), + (s.isMethod = !1), + s.body.traverseChildren(!1, function (e) { + if ( + (((e instanceof ut && + e.isYield()) || + e instanceof jt) && + (s.isGenerator = !0), + ((e instanceof ut && e.isAwait()) || + e instanceof u) && + (s.isAsync = !0), + s.isGenerator && s.isAsync) + ) + return e.error( + "function can't contain both yield and await", + ); + }), + s + ); + } + return ( + _inherits(n, e), + _createClass(n, [ + { + key: "isStatement", + value: function () { + return this.isMethod; + }, + }, + { + key: "makeScope", + value: function (t) { + return new gt(t, this.body, this); + }, + }, + { + key: "compileNode", + value: function (n) { + var r, + i, + u, + a, + f, + l, + c, + p, + d, + v, + m, + g, + y, + b, + E, + S, + x, + T, + N, + C, + k, + L, + A, + O, + M, + P, + H, + B, + j, + F, + I, + q, + R, + U, + X, + V, + $, + J, + K, + Q, + Y, + Z, + et; + for ( + this.ctor && + (this.isAsync && + this.name.error( + "Class constructor may not be async", + ), + this.isGenerator && + this.name.error( + "Class constructor may not be a generator", + )), + this.bound && + ((null == + (F = n.scope.method) + ? void 0 + : F.bound) && + (this.context = + n.scope.method.context), + !this.context && + (this.context = + "this")), + n.scope = + Rt(n, "classScope") || + this.makeScope(n.scope), + n.scope.shared = Rt( + n, + "sharedScope", + ), + n.indent += Ct, + delete n.bare, + delete n.isExistentialEquals, + H = [], + p = [], + Y = + null == + (I = + null == + (q = + this + .thisAssignments) + ? void 0 + : q.slice()) + ? [] + : I, + B = [], + m = !1, + v = !1, + M = [], + this.eachParamName( + function (e, r, i, s) { + var u, a; + if ( + (0 <= + t.call( + M, + e, + ) && + r.error( + "multiple parameters named '" + + e + + "'", + ), + M.push(e), + r.this) + ) + return ( + (e = + r + .properties[0] + .name + .value), + 0 <= + t.call( + z, + e, + ) && + (e = + "_" + + e), + (a = new _( + n.scope.freeVariable( + e, + { + reserve: + !1, + }, + ), + )), + (u = + i.name instanceof + ot && + s instanceof + o && + "=" === + s + .operatorToken + .value + ? new o( + new _( + e, + ), + a, + "object", + ) + : a), + i.renameParam( + r, + u, + ), + Y.push( + new o( + r, + a, + ), + ) + ); + }, + ), + R = this.params, + g = b = 0, + x = R.length; + b < x; + g = ++b + ) + (O = R[g]), + O.splat || O instanceof w + ? (m + ? O.error( + "only one splat or expansion parameter is allowed per function definition", + ) + : O instanceof + w && + 1 === + this.params + .length && + O.error( + "an expansion parameter cannot be the only parameter in a function definition", + ), + (m = !0), + O.splat + ? (O.name instanceof + s + ? ((Q = + n.scope.freeVariable( + "arg", + )), + H.push( + (j = + new Pt( + new _( + Q, + ), + )), + ), + p.push( + new o( + new Pt( + O.name, + ), + j, + ), + )) + : (H.push( + (j = + O.asReference( + n, + )), + ), + (Q = Xt( + j.compileNodeWithoutComments( + n, + ), + ))), + O.shouldCache() && + p.push( + new o( + new Pt( + O.name, + ), + j, + ), + )) + : ((Q = + n.scope.freeVariable( + "args", + )), + H.push( + new Pt( + new _( + Q, + ), + ), + )), + n.scope.parameter(Q)) + : ((O.shouldCache() || + v) && + ((O.assignedInBody = + !0), + (v = !0), + null == O.value + ? p.push( + new o( + new Pt( + O.name, + ), + O.asReference( + n, + ), + null, + { + param: "alwaysDeclare", + }, + ), + ) + : ((c = + new ut( + "===", + O, + new Dt(), + )), + (y = new o( + new Pt( + O.name, + ), + O.value, + )), + p.push( + new D( + c, + y, + ), + ))), + m + ? (B.push(O), + null != + O.value && + !O.shouldCache() && + ((c = + new ut( + "===", + O, + new Dt(), + )), + (y = new o( + new Pt( + O.name, + ), + O.value, + )), + p.push( + new D( + c, + y, + ), + )), + null != + (null == + (U = O.name) + ? void 0 + : U.value) && + n.scope.add( + O.name + .value, + "var", + !0, + )) + : ((j = + O.shouldCache() + ? O.asReference( + n, + ) + : null == + O.value || + O.assignedInBody + ? O + : new o( + new Pt( + O.name, + ), + O.value, + null, + { + param: !0, + }, + )), + O.name instanceof + s || + O.name instanceof + ot + ? ((O.name.lhs = + !0), + O.name instanceof + ot && + O.name.hasSplat() + ? ((Q = + n.scope.freeVariable( + "arg", + )), + n.scope.parameter( + Q, + ), + (j = + new Pt( + new _( + Q, + ), + )), + p.push( + new o( + new Pt( + O.name, + ), + j, + null, + { + param: "alwaysDeclare", + }, + ), + ), + null != + O.value && + !O.assignedInBody && + (j = + new o( + j, + O.value, + null, + { + param: !0, + }, + ))) + : !O.shouldCache() && + O.name.eachName( + function ( + e, + ) { + return n.scope.parameter( + e.value, + ); + }, + )) + : ((P = + null == + O.value + ? j + : O), + n.scope.parameter( + Xt( + P.compileToFragmentsWithoutComments( + n, + ), + ), + )), + H.push(j))); + if ( + (0 !== B.length && + p.unshift( + new o( + new Pt( + new s( + [ + new bt( + new _( + Q, + ), + ), + ].concat( + _toConsumableArray( + (function () { + var e, + t, + r; + for ( + r = + [], + e = 0, + t = + B.length; + e < + t; + e++ + ) + (O = + B[ + e + ]), + r.push( + O.asReference( + n, + ), + ); + return r; + })(), + ), + ), + ), + ), + new Pt(new _(Q)), + ), + ), + (Z = this.body.isEmpty()), + !this.expandCtorSuper(Y)) + ) { + var tt; + (tt = + this.body + .expressions).unshift.apply( + tt, + _toConsumableArray(Y), + ); + } + for ( + (r = + this.body + .expressions).unshift.apply( + r, + _toConsumableArray(p), + ), + this.isMethod && + this.bound && + !this.isStatic && + this.classVariable && + ((f = new Pt( + new G( + an( + "boundMethodCheck", + n, + ), + ), + )), + this.body.expressions.unshift( + new h(f, [ + new Pt( + new At(), + ), + this + .classVariable, + ]), + )), + Z || + this.noReturn || + this.body.makeReturn(), + this.bound && + this.isGenerator && + ((et = + this.body.contains( + function (e) { + return ( + e instanceof + ut && + "yield" === + e.operator + ); + }, + )), + (et || this).error( + "yield cannot occur inside bound (fat arrow) functions", + )), + L = [], + this.isMethod && + this.isStatic && + L.push("static"), + this.isAsync && + L.push("async"), + this.isMethod || this.bound + ? this.isGenerator && + L.push("*") + : L.push( + "function" + + (this + .isGenerator + ? "*" + : ""), + ), + K = [this.makeCode("(")], + null != + (null == + (X = this.paramStart) + ? void 0 + : X.comments) && + this.compileCommentFragments( + n, + this.paramStart, + K, + ), + g = E = 0, + T = H.length; + E < T; + g = ++E + ) { + var nt; + if ( + ((O = H[g]), + 0 !== g && + K.push( + this.makeCode(", "), + ), + m && + g === H.length - 1 && + K.push( + this.makeCode( + "...", + ), + ), + (J = + n.scope.variables + .length), + (nt = K).push.apply( + nt, + _toConsumableArray( + O.compileToFragments( + n, + ), + ), + ), + J !== + n.scope.variables + .length) + ) { + var rt; + (d = + n.scope.variables.splice( + J, + )), + (rt = + n.scope.parent + .variables).push.apply( + rt, + _toConsumableArray( + d, + ), + ); + } + } + if ( + (K.push(this.makeCode(")")), + null != + (null == + (V = this.funcGlyph) + ? void 0 + : V.comments)) + ) { + for ( + $ = this.funcGlyph.comments, + S = 0, + N = $.length; + S < N; + S++ + ) + (l = $[S]), + (l.unshift = !1); + this.compileCommentFragments( + n, + this.funcGlyph, + K, + ); + } + if ( + (this.body.isEmpty() || + (a = + this.body.compileWithDeclarations( + n, + )), + this.isMethod) + ) { + var it = [ + n.scope, + n.scope.parent, + ]; + (k = it[0]), + (n.scope = it[1]), + (A = + this.name.compileToFragments( + n, + )), + "." === A[0].code && + A.shift(), + (n.scope = k); + } + if ( + ((u = this.joinFragmentArrays( + function () { + var e, t, n; + for ( + n = [], + t = 0, + e = L.length; + t < e; + t++ + ) + (C = L[t]), + n.push( + this.makeCode( + C, + ), + ); + return n; + }.call(this), + " ", + )), + L.length && + A && + u.push(this.makeCode(" ")), + A) + ) { + var st; + (st = u).push.apply( + st, + _toConsumableArray(A), + ); + } + if ( + ((i = u).push.apply( + i, + _toConsumableArray(K), + ), + this.bound && + !this.isMethod && + u.push( + this.makeCode(" =>"), + ), + u.push(this.makeCode(" {")), + null == a ? void 0 : a.length) + ) { + var at; + (at = u).push.apply( + at, + [ + this.makeCode("\n"), + ].concat( + _toConsumableArray(a), + [ + this.makeCode( + "\n" + this.tab, + ), + ], + ), + ); + } + return ( + u.push(this.makeCode("}")), + this.isMethod + ? $t(u, this) + : this.front || n.level >= W + ? this.wrapInParentheses( + u, + ) + : u + ); + }, + }, + { + key: "eachParamName", + value: function (t) { + var n, r, i, s, o; + for ( + s = this.params, + o = [], + n = 0, + r = s.length; + n < r; + n++ + ) + (i = s[n]), + o.push(i.eachName(t)); + return o; + }, + }, + { + key: "traverseChildren", + value: function (t, r) { + if (t) + return _get( + n.prototype.__proto__ || + Object.getPrototypeOf( + n.prototype, + ), + "traverseChildren", + this, + ).call(this, t, r); + }, + }, + { + key: "replaceInContext", + value: function (t, r) { + return ( + !!this.bound && + _get( + n.prototype.__proto__ || + Object.getPrototypeOf( + n.prototype, + ), + "replaceInContext", + this, + ).call(this, t, r) + ); + }, + }, + { + key: "expandCtorSuper", + value: function (t) { + var n = this, + r, + i, + s, + o; + return ( + !!this.ctor && + (this.eachSuperCall( + f.wrap(this.params), + function (e) { + return e.error( + "'super' is not allowed in constructor parameter defaults", + ); + }, + ), + (o = this.eachSuperCall( + this.body, + function (e) { + return ( + "base" === n.ctor && + e.error( + "'super' is only allowed in derived class constructors", + ), + (e.expressions = t) + ); + }, + )), + (r = + t.length && + t.length !== + (null == + (s = + this + .thisAssignments) + ? void 0 + : s.length)), + "derived" === this.ctor && + !o && + r && + ((i = t[0].variable), + i.error( + "Can't use @params in derived class constructors without calling super", + )), + o) + ); + }, + }, + { + key: "eachSuperCall", + value: function (t, r) { + var i = this, + s; + return ( + (s = !1), + t.traverseChildren( + !0, + function (e) { + var t; + return ( + e instanceof Tt + ? (!e.variable + .accessor && + ((t = + e.args.filter( + function ( + e, + ) { + return ( + !( + e instanceof + p + ) && + (!( + e instanceof + n + ) || + e.bound) + ); + }, + )), + f + .wrap( + t, + ) + .traverseChildren( + !0, + function ( + e, + ) { + if ( + e.this + ) + return e.error( + "Can't call super with @params in derived class constructors", + ); + }, + )), + (s = !0), + r(e)) + : e instanceof + At && + "derived" === + i.ctor && + !s && + e.error( + "Can't reference 'this' before calling super in derived class constructors", + ), + !( + e instanceof Tt + ) && + (!( + e instanceof + n + ) || + e.bound) + ); + }, + ), + s + ); + }, + }, + ]), + n + ); + })(a); + return ( + (e.prototype.children = ["params", "body"]), + (e.prototype.jumps = nt), + e + ); + }.call(this)), + (e.Param = at = + function () { + var e = (function (e) { + function n(e, t, r) { + _classCallCheck(this, n); + var i = _possibleConstructorReturn( + this, + ( + n.__proto__ || + Object.getPrototypeOf(n) + ).call(this), + ), + s, + o; + return ( + (i.name = e), + (i.value = t), + (i.splat = r), + (s = Qt(i.name.unwrapAll().value)), + s && i.name.error(s), + i.name instanceof ot && + i.name.generated && + ((o = i.name.objects[0].operatorToken), + o.error("unexpected " + o.value)), + i + ); + } + return ( + _inherits(n, e), + _createClass(n, [ + { + key: "compileToFragments", + value: function (t) { + return this.name.compileToFragments( + t, + V, + ); + }, + }, + { + key: "compileToFragmentsWithoutComments", + value: function (t) { + return this.name.compileToFragmentsWithoutComments( + t, + V, + ); + }, + }, + { + key: "asReference", + value: function (n) { + var r, i; + return this.reference + ? this.reference + : ((i = this.name), + i.this + ? ((r = + i.properties[0].name + .value), + 0 <= t.call(z, r) && + (r = "_" + r), + (i = new _( + n.scope.freeVariable( + r, + ), + ))) + : i.shouldCache() && + (i = new _( + n.scope.freeVariable( + "arg", + ), + )), + (i = new Pt(i)), + i.updateLocationDataIfMissing( + this.locationData, + ), + (this.reference = i)); + }, + }, + { + key: "shouldCache", + value: function () { + return this.name.shouldCache(); + }, + }, + { + key: "eachName", + value: function (t) { + var n = this, + r = + 1 < arguments.length && + void 0 !== arguments[1] + ? arguments[1] + : this.name, + i, + s, + u, + a, + f, + l, + c, + h; + if ( + ((i = function (e) { + var r = + 1 < arguments.length && + void 0 !== arguments[1] + ? arguments[1] + : null; + return t( + "@" + + e.properties[0].name + .value, + e, + n, + r, + ); + }), + r instanceof G) + ) + return t(r.value, r, this); + if (r instanceof Pt) return i(r); + for ( + h = + null == (c = r.objects) + ? [] + : c, + s = 0, + u = h.length; + s < u; + s++ + ) + (l = h[s]), + (a = l), + l instanceof o && + null == l.context && + (l = l.variable), + l instanceof o + ? ((l = + l.value instanceof + o + ? l.value + .variable + : l.value), + this.eachName( + t, + l.unwrap(), + )) + : l instanceof bt + ? ((f = + l.name.unwrap()), + t(f.value, f, this)) + : l instanceof Pt + ? l.isArray() || + l.isObject() + ? this.eachName( + t, + l.base, + ) + : l.this + ? i(l, a) + : t( + l.base + .value, + l.base, + this, + ) + : l instanceof g + ? l + : !( + l instanceof + w + ) && + l.error( + "illegal parameter " + + l.compile(), + ); + }, + }, + { + key: "renameParam", + value: function (t, n) { + var r, i; + return ( + (r = function (e) { + return e === t; + }), + (i = function (e, t) { + var r; + return t instanceof ot + ? ((r = e), + e.this && + (r = + e + .properties[0] + .name), + e.this && + r.value === n.value + ? new Pt(n) + : new o( + new Pt(r), + n, + "object", + )) + : n; + }), + this.replaceInContext(r, i) + ); + }, + }, + ]), + n + ); + })(a); + return (e.prototype.children = ["name", "value"]), e; + }.call(this)), + (e.Splat = bt = + function () { + var e = (function (e) { + function t(e) { + _classCallCheck(this, t); + var n = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return (n.name = e.compile ? e : new G(e)), n; + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "isAssignable", + value: function () { + return ( + this.name.isAssignable() && + (!this.name.isAtomic || + this.name.isAtomic()) + ); + }, + }, + { + key: "assigns", + value: function (t) { + return this.name.assigns(t); + }, + }, + { + key: "compileNode", + value: function (t) { + return [ + this.makeCode("..."), + ].concat( + _toConsumableArray( + this.name.compileToFragments( + t, + $, + ), + ), + ); + }, + }, + { + key: "unwrap", + value: function () { + return this.name; + }, + }, + ]), + t + ); + })(a); + return (e.prototype.children = ["name"]), e; + }.call(this)), + (e.Expansion = w = + function () { + var e = (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || + Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function () { + return this.error( + "Expansion must be used inside a destructuring assignment or parameter list", + ); + }, + }, + { + key: "asReference", + value: function () { + return this; + }, + }, + { key: "eachName", value: function () {} }, + ]), + t + ); + })(a); + return (e.prototype.shouldCache = nt), e; + }.call(this)), + (e.Elision = g = + function () { + var e = (function (e) { + function t() { + return ( + _classCallCheck(this, t), + _possibleConstructorReturn( + this, + ( + t.__proto__ || + Object.getPrototypeOf(t) + ).apply(this, arguments), + ) + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileToFragments", + value: function (n, r) { + var i; + return ( + (i = _get( + t.prototype.__proto__ || + Object.getPrototypeOf( + t.prototype, + ), + "compileToFragments", + this, + ).call(this, n, r)), + (i.isElision = !0), + i + ); + }, + }, + { + key: "compileNode", + value: function () { + return [this.makeCode(", ")]; + }, + }, + { + key: "asReference", + value: function () { + return this; + }, + }, + { key: "eachName", value: function () {} }, + ]), + t + ); + })(a); + return ( + (e.prototype.isAssignable = Bt), + (e.prototype.shouldCache = nt), + e + ); + }.call(this)), + (e.While = Ht = + function () { + var e = (function (e) { + function t(e, n) { + _classCallCheck(this, t); + var r = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return ( + (r.condition = ( + null == n ? void 0 : n.invert + ) + ? e.invert() + : e), + (r.guard = null == n ? void 0 : n.guard), + r + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "makeReturn", + value: function (n) { + return n + ? _get( + t.prototype.__proto__ || + Object.getPrototypeOf( + t.prototype, + ), + "makeReturn", + this, + ).call(this, n) + : ((this.returns = + !this.jumps()), + this); + }, + }, + { + key: "addBody", + value: function (t) { + return (this.body = t), this; + }, + }, + { + key: "jumps", + value: function () { + var t, n, r, i, s; + if ( + ((t = this.body.expressions), + !t.length) + ) + return !1; + for ( + n = 0, i = t.length; + n < i; + n++ + ) + if ( + ((s = t[n]), + (r = s.jumps({ loop: !0 }))) + ) + return r; + return !1; + }, + }, + { + key: "compileNode", + value: function (t) { + var n, r, i, s; + return ( + (t.indent += Ct), + (s = ""), + (r = this.body), + r.isEmpty() + ? (r = this.makeCode("")) + : (this.returns && + (r.makeReturn( + (i = + t.scope.freeVariable( + "results", + )), + ), + (s = + "" + + this.tab + + i + + " = [];\n")), + this.guard && + (1 < + r.expressions.length + ? r.expressions.unshift( + new D( + new ft( + this.guard, + ).invert(), + new wt( + "continue", + ), + ), + ) + : this.guard && + (r = f.wrap([ + new D( + this.guard, + r, + ), + ]))), + (r = [].concat( + this.makeCode("\n"), + r.compileToFragments( + t, + K, + ), + this.makeCode( + "\n" + this.tab, + ), + ))), + (n = [].concat( + this.makeCode( + s + + this.tab + + "while (", + ), + this.condition.compileToFragments( + t, + J, + ), + this.makeCode(") {"), + r, + this.makeCode("}"), + )), + this.returns && + n.push( + this.makeCode( + "\n" + + this.tab + + "return " + + i + + ";", + ), + ), + n + ); + }, + }, + ]), + t + ); + })(a); + return ( + (e.prototype.children = [ + "condition", + "guard", + "body", + ]), + (e.prototype.isStatement = Bt), + e + ); + }.call(this)), + (e.Op = ut = + function () { + var e = (function (e) { + function s(e, t, r, i) { + var o; + _classCallCheck(this, s); + var u = _possibleConstructorReturn( + this, + ( + s.__proto__ || + Object.getPrototypeOf(s) + ).call(this), + ), + a; + if ("in" === e) { + var f; + return ( + (f = new q(t, r)), + _possibleConstructorReturn(u, f) + ); + } + if ("do" === e) { + var l; + return ( + (l = s.prototype.generateDo(t)), + _possibleConstructorReturn(u, l) + ); + } + if ("new" === e) { + if ( + (a = t.unwrap()) instanceof h && + !a.do && + !a.isNew + ) { + var c; + return ( + (c = a.newInstance()), + _possibleConstructorReturn(u, c) + ); + } + ((t instanceof d && t.bound) || t.do) && + (t = new ft(t)); + } + return ( + (u.operator = n[e] || e), + (u.first = t), + (u.second = r), + (u.flip = !!i), + (o = u), + _possibleConstructorReturn(u, o) + ); + } + return ( + _inherits(s, e), + _createClass(s, [ + { + key: "isNumber", + value: function () { + var t; + return ( + this.isUnary() && + ("+" === + (t = this.operator) || + "-" === t) && + this.first instanceof Pt && + this.first.isNumber() + ); + }, + }, + { + key: "isAwait", + value: function () { + return ( + "await" === this.operator + ); + }, + }, + { + key: "isYield", + value: function () { + var t; + return ( + "yield" === + (t = this.operator) || + "yield*" === t + ); + }, + }, + { + key: "isUnary", + value: function () { + return !this.second; + }, + }, + { + key: "shouldCache", + value: function () { + return !this.isNumber(); + }, + }, + { + key: "isChainable", + value: function () { + var t; + return ( + "<" === + (t = this.operator) || + ">" === t || + ">=" === t || + "<=" === t || + "===" === t || + "!==" === t + ); + }, + }, + { + key: "invert", + value: function () { + var t, n, i, o, u; + if ( + this.isChainable() && + this.first.isChainable() + ) { + for ( + t = !0, n = this; + n && n.operator; + + ) + t && + (t = + n.operator in + r), + (n = n.first); + if (!t) + return new ft( + this, + ).invert(); + for ( + n = this; + n && n.operator; + + ) + (n.invert = !n.invert), + (n.operator = + r[n.operator]), + (n = n.first); + return this; + } + return (o = r[this.operator]) + ? ((this.operator = o), + this.first.unwrap() instanceof + s && + this.first.invert(), + this) + : this.second + ? new ft(this).invert() + : "!" === this.operator && + (i = + this.first.unwrap()) instanceof + s && + ("!" === + (u = + i.operator) || + "in" === u || + "instanceof" === + u) + ? i + : new s("!", this); + }, + }, + { + key: "unfoldSoak", + value: function (t) { + var n; + return ( + ("++" === + (n = this.operator) || + "--" === n || + "delete" === n) && + on(t, this, "first") + ); + }, + }, + { + key: "generateDo", + value: function (t) { + var n, r, i, s, u, a, f, l; + for ( + a = [], + r = + t instanceof o && + (f = + t.value.unwrap()) instanceof + d + ? f + : t, + l = r.params || [], + i = 0, + s = l.length; + i < s; + i++ + ) + (u = l[i]), + u.value + ? (a.push(u.value), + delete u.value) + : a.push(u); + return ( + (n = new h(t, a)), + (n.do = !0), + n + ); + }, + }, + { + key: "compileNode", + value: function (t) { + var n, r, i, s, o, u; + if ( + ((r = + this.isChainable() && + this.first.isChainable()), + r || + (this.first.front = + this.front), + "delete" === + this.operator && + t.scope.check( + this.first.unwrapAll() + .value, + ) && + this.error( + "delete operand may not be argument or var", + ), + ("--" === + (o = this.operator) || + "++" === o) && + ((s = Qt( + this.first.unwrapAll() + .value, + )), + s && + this.first.error( + s, + )), + this.isYield() || + this.isAwait()) + ) + return this.compileContinuation( + t, + ); + if (this.isUnary()) + return this.compileUnary(t); + if (r) + return this.compileChain(t); + switch (this.operator) { + case "?": + return this.compileExistence( + t, + this.second + .isDefaultValue, + ); + case "**": + return this.compilePower( + t, + ); + case "//": + return this.compileFloorDivision( + t, + ); + case "%%": + return this.compileModulo( + t, + ); + default: + return ( + (i = + this.first.compileToFragments( + t, + $, + )), + (u = + this.second.compileToFragments( + t, + $, + )), + (n = [].concat( + i, + this.makeCode( + " " + + this + .operator + + " ", + ), + u, + )), + t.level <= $ + ? n + : this.wrapInParentheses( + n, + ) + ); + } + }, + }, + { + key: "compileChain", + value: function (t) { + var n = + this.first.second.cache( + t, + ), + r = _slicedToArray(n, 2), + i, + s, + o; + return ( + (this.first.second = r[0]), + (o = r[1]), + (s = + this.first.compileToFragments( + t, + $, + )), + (i = s.concat( + this.makeCode( + " " + + (this.invert + ? "&&" + : "||") + + " ", + ), + o.compileToFragments(t), + this.makeCode( + " " + + this.operator + + " ", + ), + this.second.compileToFragments( + t, + $, + ), + )), + this.wrapInParentheses(i) + ); + }, + }, + { + key: "compileExistence", + value: function (t, n) { + var r, i; + return ( + this.first.shouldCache() + ? ((i = new _( + t.scope.freeVariable( + "ref", + ), + )), + (r = new ft( + new o( + i, + this.first, + ), + ))) + : ((r = this.first), + (i = r)), + new D(new b(r, n), i, { + type: "if", + }) + .addElse(this.second) + .compileToFragments(t) + ); + }, + }, + { + key: "compileUnary", + value: function (t) { + var n, r, i; + return ((r = []), + (n = this.operator), + r.push([this.makeCode(n)]), + "!" === n && + this.first instanceof b) + ? ((this.first.negated = + !this.first.negated), + this.first.compileToFragments( + t, + )) + : t.level >= W + ? new ft( + this, + ).compileToFragments(t) + : ((i = + "+" === n || + "-" === n), + ("new" === n || + "typeof" === n || + "delete" === n || + (i && + this + .first instanceof + s && + this.first + .operator === + n)) && + r.push([ + this.makeCode( + " ", + ), + ]), + ((i && + this + .first instanceof + s) || + ("new" === n && + this.first.isStatement( + t, + ))) && + (this.first = + new ft( + this.first, + )), + r.push( + this.first.compileToFragments( + t, + $, + ), + ), + this.flip && + r.reverse(), + this.joinFragmentArrays( + r, + "", + )); + }, + }, + { + key: "compileContinuation", + value: function (n) { + var r, i, s, o; + return ( + (i = []), + (r = this.operator), + null == n.scope.parent && + this.error( + this.operator + + " can only occur inside functions", + ), + (null == + (s = n.scope.method) + ? void 0 + : s.bound) && + n.scope.method + .isGenerator && + this.error( + "yield cannot occur inside bound (fat arrow) functions", + ), + 0 <= + t.call( + Object.keys( + this.first, + ), + "expression", + ) && + !(this.first instanceof Ot) + ? null != + this.first + .expression && + i.push( + this.first.expression.compileToFragments( + n, + $, + ), + ) + : (n.level >= J && + i.push([ + this.makeCode( + "(", + ), + ]), + i.push([ + this.makeCode(r), + ]), + "" !== + (null == + (o = + this.first + .base) + ? void 0 + : o.value) && + i.push([ + this.makeCode( + " ", + ), + ]), + i.push( + this.first.compileToFragments( + n, + $, + ), + ), + n.level >= J && + i.push([ + this.makeCode( + ")", + ), + ])), + this.joinFragmentArrays( + i, + "", + ) + ); + }, + }, + { + key: "compilePower", + value: function (t) { + var n; + return ( + (n = new Pt(new _("Math"), [ + new i(new ct("pow")), + ])), + new h(n, [ + this.first, + this.second, + ]).compileToFragments(t) + ); + }, + }, + { + key: "compileFloorDivision", + value: function (t) { + var n, r, o; + return ( + (r = new Pt(new _("Math"), [ + new i(new ct("floor")), + ])), + (o = + this.second.shouldCache() + ? new ft( + this.second, + ) + : this.second), + (n = new s( + "/", + this.first, + o, + )), + new h(r, [ + n, + ]).compileToFragments(t) + ); + }, + }, + { + key: "compileModulo", + value: function (t) { + var n; + return ( + (n = new Pt( + new G(an("modulo", t)), + )), + new h(n, [ + this.first, + this.second, + ]).compileToFragments(t) + ); + }, + }, + { + key: "toString", + value: function u(e) { + return _get( + s.prototype.__proto__ || + Object.getPrototypeOf( + s.prototype, + ), + "toString", + this, + ).call( + this, + e, + this.constructor.name + + " " + + this.operator, + ); + }, + }, + ]), + s + ); + })(a), + n, + r; + return ( + (n = { + "==": "===", + "!=": "!==", + of: "in", + yieldfrom: "yield*", + }), + (r = { "!==": "===", "===": "!==" }), + (e.prototype.children = ["first", "second"]), + e + ); + }.call(this)), + (e.In = q = + function () { + var e = (function (e) { + function t(e, n) { + _classCallCheck(this, t); + var r = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return (r.object = e), (r.array = n), r; + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (t) { + var n, r, i, s, o; + if ( + this.array instanceof Pt && + this.array.isArray() && + this.array.base.objects.length + ) { + for ( + o = this.array.base.objects, + r = 0, + i = o.length; + r < i; + r++ + ) + if ( + ((s = o[r]), + s instanceof bt) + ) { + n = !0; + break; + } + if (!n) + return this.compileOrTest( + t, + ); + } + return this.compileLoopTest(t); + }, + }, + { + key: "compileOrTest", + value: function (t) { + var n = this.object.cache(t, $), + r = _slicedToArray(n, 2), + i, + s, + o, + u, + a, + f, + l, + c, + h, + p; + (h = r[0]), (l = r[1]); + var d = this.negated + ? [" !== ", " && "] + : [" === ", " || "], + v = _slicedToArray(d, 2); + for ( + i = v[0], + s = v[1], + p = [], + c = this.array.base.objects, + o = a = 0, + f = c.length; + a < f; + o = ++a + ) + (u = c[o]), + o && + p.push( + this.makeCode(s), + ), + (p = p.concat( + o ? l : h, + this.makeCode(i), + u.compileToFragments( + t, + W, + ), + )); + return t.level < $ + ? p + : this.wrapInParentheses(p); + }, + }, + { + key: "compileLoopTest", + value: function (t) { + var n = this.object.cache(t, V), + r = _slicedToArray(n, 2), + i, + s, + o; + return ((o = r[0]), + (s = r[1]), + (i = [].concat( + this.makeCode( + an("indexOf", t) + ".call(", + ), + this.array.compileToFragments( + t, + V, + ), + this.makeCode(", "), + s, + this.makeCode( + ") " + + (this.negated + ? "< 0" + : ">= 0"), + ), + )), + Xt(o) === Xt(s)) + ? i + : ((i = o.concat( + this.makeCode(", "), + i, + )), + t.level < V + ? i + : this.wrapInParentheses( + i, + )); + }, + }, + { + key: "toString", + value: function n(e) { + return _get( + t.prototype.__proto__ || + Object.getPrototypeOf( + t.prototype, + ), + "toString", + this, + ).call( + this, + e, + this.constructor.name + + (this.negated ? "!" : ""), + ); + }, + }, + ]), + t + ); + })(a); + return ( + (e.prototype.children = ["object", "array"]), + (e.prototype.invert = tt), + e + ); + }.call(this)), + (e.Try = Mt = + function () { + var e = (function (e) { + function t(e, n, r, i) { + _classCallCheck(this, t); + var s = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return ( + (s.attempt = e), + (s.errorVariable = n), + (s.recovery = r), + (s.ensure = i), + s + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "jumps", + value: function (t) { + var n; + return ( + this.attempt.jumps(t) || + (null == (n = this.recovery) + ? void 0 + : n.jumps(t)) + ); + }, + }, + { + key: "makeReturn", + value: function (t) { + return ( + this.attempt && + (this.attempt = + this.attempt.makeReturn( + t, + )), + this.recovery && + (this.recovery = + this.recovery.makeReturn( + t, + )), + this + ); + }, + }, + { + key: "compileNode", + value: function (t) { + var n, r, i, s, u, a; + return ( + (t.indent += Ct), + (a = + this.attempt.compileToFragments( + t, + K, + )), + (n = this.recovery + ? ((i = + t.scope.freeVariable( + "error", + { reserve: !1 }, + )), + (u = new _(i)), + this.errorVariable + ? ((s = Qt( + this.errorVariable.unwrapAll() + .value, + )), + s + ? this.errorVariable.error( + s, + ) + : void 0, + this.recovery.unshift( + new o( + this.errorVariable, + u, + ), + )) + : void 0, + [].concat( + this.makeCode( + " catch (", + ), + u.compileToFragments( + t, + ), + this.makeCode( + ") {\n", + ), + this.recovery.compileToFragments( + t, + K, + ), + this.makeCode( + "\n" + + this.tab + + "}", + ), + )) + : this.ensure || + this.recovery + ? [] + : ((i = + t.scope.freeVariable( + "error", + { reserve: !1 }, + )), + [ + this.makeCode( + " catch (" + + i + + ") {}", + ), + ])), + (r = this.ensure + ? [].concat( + this.makeCode( + " finally {\n", + ), + this.ensure.compileToFragments( + t, + K, + ), + this.makeCode( + "\n" + + this.tab + + "}", + ), + ) + : []), + [].concat( + this.makeCode( + this.tab + "try {\n", + ), + a, + this.makeCode( + "\n" + this.tab + "}", + ), + n, + r, + ) + ); + }, + }, + ]), + t + ); + })(a); + return ( + (e.prototype.children = [ + "attempt", + "recovery", + "ensure", + ]), + (e.prototype.isStatement = Bt), + e + ); + }.call(this)), + (e.Throw = Ot = + function () { + var e = (function (e) { + function t(e) { + _classCallCheck(this, t); + var n = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return (n.expression = e), n; + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (t) { + var n; + return ( + (n = + this.expression.compileToFragments( + t, + V, + )), + un(n, this.makeCode("throw ")), + n.unshift( + this.makeCode(this.tab), + ), + n.push(this.makeCode(";")), + n + ); + }, + }, + ]), + t + ); + })(a); + return ( + (e.prototype.children = ["expression"]), + (e.prototype.isStatement = Bt), + (e.prototype.jumps = nt), + (e.prototype.makeReturn = kt), + e + ); + }.call(this)), + (e.Existence = b = + function () { + var e = (function (e) { + function n(e) { + var r = + 1 < arguments.length && + void 0 !== arguments[1] && + arguments[1]; + _classCallCheck(this, n); + var i = _possibleConstructorReturn( + this, + ( + n.__proto__ || + Object.getPrototypeOf(n) + ).call(this), + ), + s; + return ( + (i.expression = e), + (i.comparisonTarget = r + ? "undefined" + : "null"), + (s = []), + i.expression.traverseChildren( + !0, + function (e) { + var n, r, i, o; + if (e.comments) { + for ( + o = e.comments, + r = 0, + i = o.length; + r < i; + r++ + ) + (n = o[r]), + 0 > t.call(s, n) && + s.push(n); + return delete e.comments; + } + }, + ), + It(s, i), + Zt(i.expression, i), + i + ); + } + return ( + _inherits(n, e), + _createClass(n, [ + { + key: "compileNode", + value: function (t) { + var n, r, i; + if ( + ((this.expression.front = + this.front), + (i = this.expression.compile( + t, + $, + )), + this.expression.unwrap() instanceof + _ && !t.scope.check(i)) + ) { + var s = this.negated + ? ["===", "||"] + : ["!==", "&&"], + o = _slicedToArray(s, 2); + (n = o[0]), + (r = o[1]), + (i = + "typeof " + + i + + " " + + n + + ' "undefined"' + + ("undefined" === + this.comparisonTarget + ? "" + : " " + + r + + " " + + i + + " " + + n + + " " + + this + .comparisonTarget)); + } else + (n = + "null" === + this.comparisonTarget + ? this.negated + ? "==" + : "!=" + : this.negated + ? "===" + : "!=="), + (i = + i + + " " + + n + + " " + + this.comparisonTarget); + return [ + this.makeCode( + t.level <= X + ? i + : "(" + i + ")", + ), + ]; + }, + }, + ]), + n + ); + })(a); + return ( + (e.prototype.children = ["expression"]), + (e.prototype.invert = tt), + e + ); + }.call(this)), + (e.Parens = ft = + function () { + var e = (function (e) { + function t(e) { + _classCallCheck(this, t); + var n = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return (n.body = e), n; + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "unwrap", + value: function () { + return this.body; + }, + }, + { + key: "shouldCache", + value: function () { + return this.body.shouldCache(); + }, + }, + { + key: "compileNode", + value: function (t) { + var n, r, i, s, o; + return ((r = this.body.unwrap()), + (o = + null == (s = r.comments) + ? void 0 + : s.some(function (e) { + return ( + e.here && + !e.unshift && + !e.newLine + ); + })), + r instanceof Pt && + r.isAtomic() && + !this.csxAttribute && + !o) + ? ((r.front = this.front), + r.compileToFragments(t)) + : ((i = r.compileToFragments( + t, + J, + )), + (n = + t.level < $ && + !o && + (r instanceof ut || + r.unwrap() instanceof + h || + (r instanceof L && + r.returns)) && + (t.level < X || + 3 >= i.length)), + this.csxAttribute + ? this.wrapInBraces(i) + : n + ? i + : this.wrapInParentheses( + i, + )); + }, + }, + ]), + t + ); + })(a); + return (e.prototype.children = ["body"]), e; + }.call(this)), + (e.StringWithInterpolations = St = + function () { + var e = (function (e) { + function t(e) { + _classCallCheck(this, t); + var n = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return (n.body = e), n; + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "unwrap", + value: function () { + return this; + }, + }, + { + key: "shouldCache", + value: function () { + return this.body.shouldCache(); + }, + }, + { + key: "compileNode", + value: function (n) { + var r, i, s, o, u, a, f, l, c; + if (this.csxAttribute) + return ( + (c = new ft( + new t(this.body), + )), + (c.csxAttribute = !0), + c.compileNode(n) + ); + for ( + o = this.body.unwrap(), + s = [], + l = [], + o.traverseChildren( + !1, + function (e) { + var t, + n, + r, + i, + o, + u; + if ( + e instanceof Et + ) { + if ( + e.comments + ) { + var a; + (a = + l).push.apply( + a, + _toConsumableArray( + e.comments, + ), + ), + delete e.comments; + } + return ( + s.push(e), + !0 + ); + } + if ( + e instanceof ft + ) { + if ( + 0 !== + l.length + ) { + for ( + n = 0, + i = + l.length; + n < i; + n++ + ) + (t = + l[ + n + ]), + (t.unshift = + !0), + (t.newLine = + !0); + It(l, e); + } + return ( + s.push(e), + !1 + ); + } + if (e.comments) { + if ( + 0 === + s.length || + s[ + s.length - + 1 + ] instanceof + Et + ) { + var f; + (f = + l).push.apply( + f, + _toConsumableArray( + e.comments, + ), + ); + } else { + for ( + u = + e.comments, + r = 0, + o = + u.length; + r < o; + r++ + ) + (t = + u[ + r + ]), + (t.unshift = + !1), + (t.newLine = + !0); + It( + e.comments, + s[ + s.length - + 1 + ], + ); + } + delete e.comments; + } + return !0; + }, + ), + u = [], + this.csx || + u.push( + this.makeCode("`"), + ), + a = 0, + f = s.length; + a < f; + a++ + ) + if ( + ((i = s[a]), + i instanceof Et) + ) { + var h; + (i.value = i.unquote( + !0, + this.csx, + )), + this.csx || + (i.value = + i.value.replace( + /(\\*)(`|\$\{)/g, + function ( + e, + t, + n, + ) { + return 0 == + t.length % + 2 + ? t + + "\\" + + n + : e; + }, + )), + (h = u).push.apply( + h, + _toConsumableArray( + i.compileToFragments( + n, + ), + ), + ); + } else { + var p; + this.csx || + u.push( + this.makeCode("$"), + ), + (r = + i.compileToFragments( + n, + J, + )), + (!this.isNestedTag(i) || + r.some( + function (e) { + return ( + null != + e.comments + ); + }, + )) && + ((r = + this.wrapInBraces( + r, + )), + (r[0].isStringWithInterpolations = + !0), + (r[ + r.length - 1 + ].isStringWithInterpolations = + !0)), + (p = u).push.apply( + p, + _toConsumableArray( + r, + ), + ); + } + return ( + this.csx || + u.push(this.makeCode("`")), + u + ); + }, + }, + { + key: "isNestedTag", + value: function (t) { + var n, r, i; + return ( + (r = + null == (i = t.body) + ? void 0 + : i.expressions), + (n = + null == r + ? void 0 + : r[0].unwrap()), + this.csx && + r && + 1 === r.length && + n instanceof h && + n.csx + ); + }, + }, + ]), + t + ); + })(a); + return (e.prototype.children = ["body"]), e; + }.call(this)), + (e.For = L = + function () { + var e = (function (e) { + function t(e, n) { + _classCallCheck(this, t); + var r = _possibleConstructorReturn( + this, + ( + t.__proto__ || + Object.getPrototypeOf(t) + ).call(this), + ), + i, + s, + o, + u, + a, + l; + if ( + ((r.source = n.source), + (r.guard = n.guard), + (r.step = n.step), + (r.name = n.name), + (r.index = n.index), + (r.body = f.wrap([e])), + (r.own = null != n.own), + (r.object = null != n.object), + (r.from = null != n.from), + r.from && + r.index && + r.index.error( + "cannot use index with for-from", + ), + r.own && + !r.object && + n.ownTag.error( + "cannot use own with for-" + + (r.from ? "from" : "in"), + ), + r.object) + ) { + var c = [r.index, r.name]; + (r.name = c[0]), (r.index = c[1]); + } + for ( + ((null == (u = r.index) + ? void 0 + : "function" == typeof u.isArray + ? u.isArray() + : void 0) || + (null == (a = r.index) + ? void 0 + : "function" == typeof a.isObject + ? a.isObject() + : void 0)) && + r.index.error( + "index cannot be a pattern matching expression", + ), + r.range = + r.source instanceof Pt && + r.source.base instanceof ht && + !r.source.properties.length && + !r.from, + r.pattern = r.name instanceof Pt, + r.range && + r.index && + r.index.error( + "indexes do not apply to range loops", + ), + r.range && + r.pattern && + r.name.error( + "cannot pattern match over range loops", + ), + r.returns = !1, + l = [ + "source", + "guard", + "step", + "name", + "index", + ], + s = 0, + o = l.length; + s < o; + s++ + ) + ((i = l[s]), !!r[i]) && + (r[i].traverseChildren( + !0, + function (e) { + var t, n, s, o; + if (e.comments) { + for ( + o = e.comments, + n = 0, + s = o.length; + n < s; + n++ + ) + (t = o[n]), + (t.newLine = + t.unshift = + !0); + return Zt(e, r[i]); + } + }, + ), + Zt(r[i], r)); + return r; + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "compileNode", + value: function (t) { + var n, + i, + s, + u, + a, + l, + c, + h, + p, + d, + v, + m, + g, + y, + b, + w, + E, + S, + x, + T, + N, + C, + k, + L, + A, + O, + M, + P, + H, + B, + j, + F, + I, + q, + R; + if ( + ((s = f.wrap([this.body])), + (A = s.expressions), + (n = r.call(A, -1)), + (i = _slicedToArray(n, 1)), + (T = i[0]), + n, + (null == T + ? void 0 + : T.jumps()) instanceof + vt && (this.returns = !1), + (B = this.range + ? this.source.base + : this.source), + (H = t.scope), + this.pattern || + (C = + this.name && + this.name.compile( + t, + V, + )), + (w = + this.index && + this.index.compile(t, V)), + C && !this.pattern && H.find(C), + w && + !( + this.index instanceof Pt + ) && + H.find(w), + this.returns && + (P = + H.freeVariable( + "results", + )), + this.from + ? this.pattern && + (E = H.freeVariable("x", { + single: !0, + })) + : (E = + (this.object && w) || + H.freeVariable("i", { + single: !0, + })), + (S = + ((this.range || + this.from) && + C) || + w || + E), + (x = S === E ? "" : S + " = "), + this.step && !this.range) + ) { + var U = + this.cacheToCodeFragments( + this.step.cache( + t, + V, + tn, + ), + ), + z = _slicedToArray(U, 2); + (j = z[0]), + (I = z[1]), + this.step.isNumber() && + (F = +I); + } + return ( + this.pattern && (C = E), + (R = ""), + (g = ""), + (p = ""), + (y = this.tab + Ct), + this.range + ? (v = B.compileToFragments( + Yt(t, { + index: E, + name: C, + step: this.step, + shouldCache: tn, + }), + )) + : ((q = this.source.compile( + t, + V, + )), + (C || this.own) && + !( + this.source.unwrap() instanceof + _ + ) && + ((p += + "" + + this.tab + + (L = + H.freeVariable( + "ref", + )) + + " = " + + q + + ";\n"), + (q = L)), + C && + !this.pattern && + !this.from && + (k = + C + + " = " + + q + + "[" + + S + + "]"), + !this.object && + !this.from && + (j !== I && + (p += + "" + + this.tab + + j + + ";\n"), + (d = 0 > F), + (!this.step || + null == F || + !d) && + (N = + H.freeVariable( + "len", + )), + (c = + "" + + x + + E + + " = 0, " + + N + + " = " + + q + + ".length"), + (h = + "" + + x + + E + + " = " + + q + + ".length - 1"), + (a = E + " < " + N), + (l = E + " >= 0"), + this.step + ? (null == F + ? ((a = + I + + " > 0 ? " + + a + + " : " + + l), + (c = + "(" + + I + + " > 0 ? (" + + c + + ") : " + + h + + ")")) + : d && + ((a = l), + (c = h)), + (b = + E + + " += " + + I)) + : (b = + "" + + (S === E + ? E + + "++" + : "++" + + E)), + (v = [ + this.makeCode( + c + + "; " + + a + + "; " + + x + + b, + ), + ]))), + this.returns && + ((O = + "" + + this.tab + + P + + " = [];\n"), + (M = + "\n" + + this.tab + + "return " + + P + + ";"), + s.makeReturn(P)), + this.guard && + (1 < s.expressions.length + ? s.expressions.unshift( + new D( + new ft( + this.guard, + ).invert(), + new wt( + "continue", + ), + ), + ) + : this.guard && + (s = f.wrap([ + new D( + this.guard, + s, + ), + ]))), + this.pattern && + s.expressions.unshift( + new o( + this.name, + this.from + ? new _(S) + : new G( + q + + "[" + + S + + "]", + ), + ), + ), + k && (R = "\n" + y + k + ";"), + this.object + ? ((v = [ + this.makeCode( + S + " in " + q, + ), + ]), + this.own && + (g = + "\n" + + y + + "if (!" + + an("hasProp", t) + + ".call(" + + q + + ", " + + S + + ")) continue;")) + : this.from && + (v = [ + this.makeCode( + S + " of " + q, + ), + ]), + (u = s.compileToFragments( + Yt(t, { indent: y }), + K, + )), + u && + 0 < u.length && + (u = [].concat( + this.makeCode("\n"), + u, + this.makeCode("\n"), + )), + (m = [this.makeCode(p)]), + O && m.push(this.makeCode(O)), + (m = m.concat( + this.makeCode(this.tab), + this.makeCode("for ("), + v, + this.makeCode( + ") {" + g + R, + ), + u, + this.makeCode(this.tab), + this.makeCode("}"), + )), + M && m.push(this.makeCode(M)), + m + ); + }, + }, + ]), + t + ); + })(Ht); + return ( + (e.prototype.children = [ + "body", + "source", + "guard", + "step", + ]), + e + ); + }.call(this)), + (e.Switch = Nt = + function () { + var e = (function (e) { + function t(e, n, r) { + _classCallCheck(this, t); + var i = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return ( + (i.subject = e), + (i.cases = n), + (i.otherwise = r), + i + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "jumps", + value: function () { + var t = + 0 < arguments.length && + void 0 !== arguments[0] + ? arguments[0] + : { block: !0 }, + n, + r, + i, + s, + o, + u, + a; + for ( + u = this.cases, + i = 0, + o = u.length; + i < o; + i++ + ) { + var f = _slicedToArray(u[i], 2); + if ( + ((r = f[0]), + (n = f[1]), + (s = n.jumps(t))) + ) + return s; + } + return null == (a = this.otherwise) + ? void 0 + : a.jumps(t); + }, + }, + { + key: "makeReturn", + value: function (t) { + var n, r, i, s, o; + for ( + s = this.cases, + n = 0, + r = s.length; + n < r; + n++ + ) + (i = s[n]), i[1].makeReturn(t); + return ( + t && + (this.otherwise || + (this.otherwise = new f( + [new G("void 0")], + ))), + null != (o = this.otherwise) && + o.makeReturn(t), + this + ); + }, + }, + { + key: "compileNode", + value: function (t) { + var n, + r, + i, + s, + o, + u, + a, + f, + l, + c, + h, + p, + d, + v, + m; + for ( + f = t.indent + Ct, + l = t.indent = f + Ct, + u = [].concat( + this.makeCode( + this.tab + + "switch (", + ), + this.subject + ? this.subject.compileToFragments( + t, + J, + ) + : this.makeCode( + "false", + ), + this.makeCode(") {\n"), + ), + v = this.cases, + a = c = 0, + p = v.length; + c < p; + a = ++c + ) { + var g = _slicedToArray(v[a], 2); + for ( + s = g[0], + n = g[1], + m = Wt([s]), + h = 0, + d = m.length; + h < d; + h++ + ) + (i = m[h]), + this.subject || + (i = i.invert()), + (u = u.concat( + this.makeCode( + f + "case ", + ), + i.compileToFragments( + t, + J, + ), + this.makeCode( + ":\n", + ), + )); + if ( + (0 < + (r = + n.compileToFragments( + t, + K, + )).length && + (u = u.concat( + r, + this.makeCode("\n"), + )), + a === + this.cases.length - 1 && + !this.otherwise) + ) + break; + ((o = this.lastNode( + n.expressions, + )), + !( + o instanceof vt || + o instanceof Ot || + (o instanceof G && + o.jumps() && + "debugger" !== o.value) + )) && + u.push( + i.makeCode( + l + "break;\n", + ), + ); + } + if ( + this.otherwise && + this.otherwise.expressions + .length + ) { + var y; + (y = u).push.apply( + y, + [ + this.makeCode( + f + "default:\n", + ), + ].concat( + _toConsumableArray( + this.otherwise.compileToFragments( + t, + K, + ), + ), + [this.makeCode("\n")], + ), + ); + } + return ( + u.push( + this.makeCode( + this.tab + "}", + ), + ), + u + ); + }, + }, + ]), + t + ); + })(a); + return ( + (e.prototype.children = [ + "subject", + "cases", + "otherwise", + ]), + (e.prototype.isStatement = Bt), + e + ); + }.call(this)), + (e.If = D = + function () { + var e = (function (e) { + function t(e, n) { + var r = + 2 < arguments.length && + void 0 !== arguments[2] + ? arguments[2] + : {}; + _classCallCheck(this, t); + var i = _possibleConstructorReturn( + this, + ( + t.__proto__ || Object.getPrototypeOf(t) + ).call(this), + ); + return ( + (i.body = n), + (i.condition = + "unless" === r.type ? e.invert() : e), + (i.elseBody = null), + (i.isChain = !1), + (i.soak = r.soak), + i.condition.comments && Zt(i.condition, i), + i + ); + } + return ( + _inherits(t, e), + _createClass(t, [ + { + key: "bodyNode", + value: function () { + var t; + return null == (t = this.body) + ? void 0 + : t.unwrap(); + }, + }, + { + key: "elseBodyNode", + value: function () { + var t; + return null == (t = this.elseBody) + ? void 0 + : t.unwrap(); + }, + }, + { + key: "addElse", + value: function (n) { + return ( + this.isChain + ? this.elseBodyNode().addElse( + n, + ) + : ((this.isChain = + n instanceof t), + (this.elseBody = + this.ensureBlock(n)), + this.elseBody.updateLocationDataIfMissing( + n.locationData, + )), + this + ); + }, + }, + { + key: "isStatement", + value: function (t) { + var n; + return ( + (null == t + ? void 0 + : t.level) === K || + this.bodyNode().isStatement( + t, + ) || + (null == + (n = this.elseBodyNode()) + ? void 0 + : n.isStatement(t)) + ); + }, + }, + { + key: "jumps", + value: function (t) { + var n; + return ( + this.body.jumps(t) || + (null == (n = this.elseBody) + ? void 0 + : n.jumps(t)) + ); + }, + }, + { + key: "compileNode", + value: function (t) { + return this.isStatement(t) + ? this.compileStatement(t) + : this.compileExpression(t); + }, + }, + { + key: "makeReturn", + value: function (t) { + return ( + t && + (this.elseBody || + (this.elseBody = new f([ + new G("void 0"), + ]))), + this.body && + (this.body = new f([ + this.body.makeReturn(t), + ])), + this.elseBody && + (this.elseBody = new f([ + this.elseBody.makeReturn( + t, + ), + ])), + this + ); + }, + }, + { + key: "ensureBlock", + value: function (t) { + return t instanceof f + ? t + : new f([t]); + }, + }, + { + key: "compileStatement", + value: function (n) { + var r, i, s, o, u, a, f; + return ((s = Rt(n, "chainChild")), + (u = Rt(n, "isExistentialEquals")), + u) + ? new t( + this.condition.invert(), + this.elseBodyNode(), + { type: "if" }, + ).compileToFragments(n) + : ((f = n.indent + Ct), + (o = + this.condition.compileToFragments( + n, + J, + )), + (i = this.ensureBlock( + this.body, + ).compileToFragments( + Yt(n, { indent: f }), + )), + (a = [].concat( + this.makeCode("if ("), + o, + this.makeCode(") {\n"), + i, + this.makeCode( + "\n" + + this.tab + + "}", + ), + )), + s || + a.unshift( + this.makeCode( + this.tab, + ), + ), + !this.elseBody) + ? a + : ((r = a.concat( + this.makeCode(" else "), + )), + this.isChain + ? ((n.chainChild = !0), + (r = r.concat( + this.elseBody + .unwrap() + .compileToFragments( + n, + K, + ), + ))) + : (r = r.concat( + this.makeCode( + "{\n", + ), + this.elseBody.compileToFragments( + Yt(n, { + indent: f, + }), + K, + ), + this.makeCode( + "\n" + + this.tab + + "}", + ), + )), + r); + }, + }, + { + key: "compileExpression", + value: function (t) { + var n, r, i, s; + return ( + (i = + this.condition.compileToFragments( + t, + X, + )), + (r = + this.bodyNode().compileToFragments( + t, + V, + )), + (n = this.elseBodyNode() + ? this.elseBodyNode().compileToFragments( + t, + V, + ) + : [ + this.makeCode( + "void 0", + ), + ]), + (s = i.concat( + this.makeCode(" ? "), + r, + this.makeCode(" : "), + n, + )), + t.level >= X + ? this.wrapInParentheses(s) + : s + ); + }, + }, + { + key: "unfoldSoak", + value: function () { + return this.soak && this; + }, + }, + ]), + t + ); + })(a); + return ( + (e.prototype.children = [ + "condition", + "body", + "elseBody", + ]), + e + ); + }.call(this)), + (_t = { + modulo: function () { + return "function(a, b) { return (+a % (b = +b) + b) % b; }"; + }, + objectWithoutKeys: function () { + return "function(o, ks) { var res = {}; for (var k in o) ([].indexOf.call(ks, k) < 0 && {}.hasOwnProperty.call(o, k)) && (res[k] = o[k]); return res; }"; + }, + boundMethodCheck: function () { + return "function(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new Error('Bound instance method accessed before binding'); } }"; + }, + _extends: function () { + return "Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }"; + }, + hasProp: function () { + return "{}.hasOwnProperty"; + }, + indexOf: function () { + return "[].indexOf"; + }, + slice: function () { + return "[].slice"; + }, + splice: function () { + return "[].splice"; + }, + }), + (K = 1), + (J = 2), + (V = 3), + (X = 4), + ($ = 5), + (W = 6), + (Ct = " "), + (mt = /^[+-]?\d+$/), + (an = function (e, t) { + var n, r; + return ( + (r = t.scope.root), + e in r.utilities + ? r.utilities[e] + : ((n = r.freeVariable(e)), + r.assign(n, _t[e](t)), + (r.utilities[e] = n)) + ); + }), + (en = function (e, t) { + var n = + !( + 2 < arguments.length && void 0 !== arguments[2] + ) || arguments[2], + r; + return ( + (r = "\n" === e[e.length - 1]), + (e = (n ? t : "") + e.replace(/\n/g, "$&" + t)), + (e = e.replace(/\s+$/, "")), + r && (e += "\n"), + e + ); + }), + ($t = function (e, t) { + var n, r, i, s; + for (r = i = 0, s = e.length; i < s; r = ++i) { + if (((n = e[r]), !n.isHereComment)) { + e.splice(r, 0, t.makeCode("" + t.tab)); + break; + } + n.code = en(n.code, t.tab); + } + return e; + }), + (Vt = function (e) { + var t, n, r, i; + if (!e.comments) return !1; + for (i = e.comments, n = 0, r = i.length; n < r; n++) + if (((t = i[n]), !1 === t.here)) return !0; + return !1; + }), + (Zt = function (e, t) { + if (null != e && e.comments) + return It(e.comments, t), delete e.comments; + }), + (un = function (e, t) { + var n, r, i, s, o; + for (i = !1, r = s = 0, o = e.length; s < o; r = ++s) + if (((n = e[r]), !n.isComment)) { + e.splice(r, 0, t), (i = !0); + break; + } + return i || e.push(t), e; + }), + (Jt = function (e) { + return e instanceof _ && "arguments" === e.value; + }), + (Kt = function (e) { + return e instanceof At || (e instanceof d && e.bound); + }), + (tn = function (e) { + return ( + e.shouldCache() || + ("function" == typeof e.isAssignable + ? e.isAssignable() + : void 0) + ); + }), + (on = function (e, t, n) { + var r; + if ((r = t[n].unfoldSoak(e))) + return (t[n] = r.body), (r.body = new Pt(t)), r; + }); + }.call(this), + { exports: e }.exports + ); + })()), + (require["./sourcemap"] = (function () { + var e = { exports: {} }; + return ( + function () { + var t, n; + (t = (function () { + function e(t) { + _classCallCheck(this, e), + (this.line = t), + (this.columns = []); + } + return ( + _createClass(e, [ + { + key: "add", + value: function (t, n) { + var r = _slicedToArray(n, 2), + i = r[0], + s = r[1], + o = + 2 < arguments.length && + void 0 !== arguments[2] + ? arguments[2] + : {}; + return this.columns[t] && o.noReplace + ? void 0 + : (this.columns[t] = { + line: this.line, + column: t, + sourceLine: i, + sourceColumn: s, + }); + }, + }, + { + key: "sourceLocation", + value: function (t) { + for ( + var n; + !((n = this.columns[t]) || 0 >= t); + + ) + t--; + return n && [n.sourceLine, n.sourceColumn]; + }, + }, + ]), + e + ); + })()), + (n = function () { + var e = (function () { + function e() { + _classCallCheck(this, e), (this.lines = []); + } + return ( + _createClass(e, [ + { + key: "add", + value: function (n, r) { + var i = + 2 < arguments.length && + void 0 !== arguments[2] + ? arguments[2] + : {}, + s = _slicedToArray(r, 2), + o, + u, + f, + l; + return ( + (f = s[0]), + (u = s[1]), + (l = + (o = this.lines)[f] || + (o[f] = new t(f))), + l.add(u, n, i) + ); + }, + }, + { + key: "sourceLocation", + value: function (t) { + for ( + var n = _slicedToArray(t, 2), + r = n[0], + i = n[1], + s; + !( + (s = this.lines[r]) || + 0 >= r + ); + + ) + r--; + return s && s.sourceLocation(i); + }, + }, + { + key: "generate", + value: function () { + var t = + 0 < arguments.length && + void 0 !== arguments[0] + ? arguments[0] + : {}, + n = + 1 < arguments.length && + void 0 !== arguments[1] + ? arguments[1] + : null, + r, + i, + s, + o, + u, + a, + f, + l, + c, + h, + p, + d, + v, + m, + g, + y, + b; + for ( + b = 0, + o = 0, + a = 0, + u = 0, + d = !1, + r = "", + v = this.lines, + h = i = 0, + f = v.length; + i < f; + h = ++i + ) + if (((c = v[h]), c)) + for ( + m = c.columns, + s = 0, + l = m.length; + s < l; + s++ + ) + if (((p = m[s]), !!p)) { + for (; b < p.line; ) + (o = 0), + (d = !1), + (r += ";"), + b++; + d && + ((r += ","), + (d = !1)), + (r += + this.encodeVlq( + p.column - + o, + )), + (o = p.column), + (r += + this.encodeVlq( + 0, + )), + (r += + this.encodeVlq( + p.sourceLine - + a, + )), + (a = + p.sourceLine), + (r += + this.encodeVlq( + p.sourceColumn - + u, + )), + (u = + p.sourceColumn), + (d = !0); + } + return ( + (g = t.sourceFiles + ? t.sourceFiles + : t.filename + ? [t.filename] + : [""]), + (y = { + version: 3, + file: t.generatedFile || "", + sourceRoot: + t.sourceRoot || "", + sources: g, + names: [], + mappings: r, + }), + (t.sourceMap || t.inlineMap) && + (y.sourcesContent = [n]), + y + ); + }, + }, + { + key: "encodeVlq", + value: function (t) { + var n, u, a, f; + for ( + n = "", + a = 0 > t ? 1 : 0, + f = (_Mathabs(t) << 1) + a; + f || !n; + + ) + (u = f & s), + (f >>= i), + f && (u |= r), + (n += this.encodeBase64(u)); + return n; + }, + }, + { + key: "encodeBase64", + value: function (t) { + return ( + n[t] || + (function () { + throw new Error( + "Cannot Base64 encode value: " + + t, + ); + })() + ); + }, + }, + ]), + e + ); + })(), + n, + r, + i, + s; + return ( + (i = 5), + (r = 1 << i), + (s = r - 1), + (n = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"), + e + ); + }.call(this)), + (e.exports = n); + }.call(this), + e.exports + ); + })()), + (require["./coffeescript"] = (function () { + var e = {}; + return ( + function () { + var t = [].indexOf, + n = require("./lexer"), + r, + i, + s, + o, + u, + a, + f, + l, + c, + h, + p, + d, + v, + m, + g; + i = n.Lexer; + var y = require("./parser"); + (d = y.parser), + (c = require("./helpers")), + (s = require("./sourcemap")), + (p = require("../../package.json")), + (e.VERSION = p.version), + (e.FILE_EXTENSIONS = r = + [".coffee", ".litcoffee", ".coffee.md"]), + (e.helpers = c), + (o = function (e) { + switch (!1) { + case "function" != typeof Buffer: + return Buffer.from(e).toString("base64"); + case "function" != typeof btoa: + return btoa( + encodeURIComponent(e).replace( + /%([0-9A-F]{2})/g, + function (e, t) { + return _StringfromCharCode("0x" + t); + }, + ), + ); + default: + throw new Error( + "Unable to base64 encode inline sourcemap.", + ); + } + }), + (g = function (e) { + return function (e) { + var t = + 1 < arguments.length && void 0 !== arguments[1] + ? arguments[1] + : {}, + n; + try { + return r.call(this, e, t); + } catch (r) { + throw ((n = r), "string" != typeof e) + ? n + : c.updateSyntaxError(n, e, t.filename); + } + }; + }), + (m = {}), + (v = {}), + (e.compile = a = + g(function (e) { + var t = + 1 < arguments.length && void 0 !== arguments[1] + ? arguments[1] + : {}, + n, + r, + i, + a, + f, + l, + p, + g, + y, + b, + w, + E, + S, + x, + T, + N, + C, + k, + L, + A, + O, + M, + _, + D, + P; + if ( + ((t = Object.assign({}, t)), + (p = + t.sourceMap || + t.inlineMap || + null == t.filename), + (a = t.filename || ""), + u(a, e), + null == m[a] && (m[a] = []), + m[a].push(e), + p && (x = new s()), + (O = h.tokenize(e, t)), + (t.referencedVars = (function () { + var e, t, n; + for (n = [], e = 0, t = O.length; e < t; e++) + (A = O[e]), + "IDENTIFIER" === A[0] && n.push(A[1]); + return n; + })()), + null == t.bare || !0 !== t.bare) + ) + for (y = 0, E = O.length; y < E; y++) + if ( + ((A = O[y]), + "IMPORT" === (N = A[0]) || "EXPORT" === N) + ) { + t.bare = !0; + break; + } + for ( + l = d.parse(O).compileToFragments(t), + r = 0, + t.header && (r += 1), + t.shiftLine && (r += 1), + n = 0, + w = "", + b = 0, + S = l.length; + b < S; + b++ + ) + (f = l[b]), + p && + (f.locationData && + !/^[;\s]*$/.test(f.code) && + x.add( + [ + f.locationData.first_line, + f.locationData.first_column, + ], + [r, n], + { noReplace: !0 }, + ), + (T = c.count(f.code, "\n")), + (r += T), + T + ? (n = + f.code.length - + (f.code.lastIndexOf("\n") + 1)) + : (n += f.code.length)), + (w += f.code); + if ( + (t.header && + ((g = + "Generated by CoffeeScript " + + this.VERSION), + (w = "// " + g + "\n" + w)), + p && + ((P = x.generate(t, e)), + null == v[a] && (v[a] = []), + v[a].push(x)), + t.transpile) + ) { + if ("object" !== _typeof(t.transpile)) + throw new Error( + "The transpile option must be given an object with options to pass to Babel", + ); + (M = t.transpile.transpile), + delete t.transpile.transpile, + (_ = Object.assign({}, t.transpile)), + P && + null == _.inputSourceMap && + (_.inputSourceMap = P), + (D = M(w, _)), + (w = D.code), + P && D.map && (P = D.map); + } + return ( + t.inlineMap && + ((i = o(JSON.stringify(P))), + (k = + "//# sourceMappingURL=data:application/json;base64," + + i), + (L = + "//# sourceURL=" + + (null == (C = t.filename) + ? "coffeescript" + : C)), + (w = w + "\n" + k + "\n" + L)), + t.sourceMap + ? { + js: w, + sourceMap: x, + v3SourceMap: JSON.stringify(P, null, 2), + } + : w + ); + })), + (e.tokens = g(function (e, t) { + return h.tokenize(e, t); + })), + (e.nodes = g(function (e, t) { + return "string" == typeof e + ? d.parse(h.tokenize(e, t)) + : d.parse(e); + })), + (e.run = + e.eval = + e.register = + function () { + throw new Error( + "require index.coffee, not this file", + ); + }), + (h = new i()), + (d.lexer = { + lex: function () { + var t, n; + if (((n = d.tokens[this.pos++]), n)) { + var r = n, + i = _slicedToArray(r, 3); + (t = i[0]), + (this.yytext = i[1]), + (this.yylloc = i[2]), + (d.errorToken = n.origin || n), + (this.yylineno = this.yylloc.first_line); + } else t = ""; + return t; + }, + setInput: function (t) { + return (d.tokens = t), (this.pos = 0); + }, + upcomingInput: function () { + return ""; + }, + }), + (d.yy = require("./nodes")), + (d.yy.parseError = function (e, t) { + var n = t.token, + r = d, + i, + s, + o, + u, + a; + (u = r.errorToken), (a = r.tokens); + var f = u, + l = _slicedToArray(f, 3); + return ( + (s = l[0]), + (o = l[1]), + (i = l[2]), + (o = (function () { + switch (!1) { + case u !== a[a.length - 1]: + return "end of input"; + case "INDENT" !== s && "OUTDENT" !== s: + return "indentation"; + case "IDENTIFIER" !== s && + "NUMBER" !== s && + "INFINITY" !== s && + "STRING" !== s && + "STRING_START" !== s && + "REGEX" !== s && + "REGEX_START" !== s: + return s + .replace(/_START$/, "") + .toLowerCase(); + default: + return c.nameWhitespaceCharacter(o); + } + })()), + c.throwSyntaxError("unexpected " + o, i) + ); + }), + (f = function (e, t) { + var n, r, i, s, o, u, a, f, l, c, h, p; + return ( + (s = void 0), + (i = ""), + e.isNative() + ? (i = "native") + : (e.isEval() + ? ((s = e.getScriptNameOrSourceURL()), + !s && (i = e.getEvalOrigin() + ", ")) + : (s = e.getFileName()), + s || (s = ""), + (f = e.getLineNumber()), + (r = e.getColumnNumber()), + (c = t(s, f, r)), + (i = c + ? s + ":" + c[0] + ":" + c[1] + : s + ":" + f + ":" + r)), + (o = e.getFunctionName()), + (u = e.isConstructor()), + (a = !e.isToplevel() && !u), + a + ? ((l = e.getMethodName()), + (p = e.getTypeName()), + o + ? ((h = n = ""), + p && o.indexOf(p) && (h = p + "."), + l && + o.indexOf("." + l) !== + o.length - l.length - 1 && + (n = " [as " + l + "]"), + "" + h + o + n + " (" + i + ")") + : p + + "." + + (l || "") + + " (" + + i + + ")") + : u + ? "new " + (o || "") + " (" + i + ")" + : o + ? o + " (" + i + ")" + : i + ); + }), + (l = function (e, n, i) { + var s, o, u, f, l, h; + if ( + "" === e || + ((f = e.slice(e.lastIndexOf("."))), 0 <= t.call(r, f)) + ) { + if ("" !== e && null != v[e]) + return v[e][v[e].length - 1]; + if (null != v[""]) + for ( + l = v[""], o = l.length - 1; + 0 <= o; + o += -1 + ) + if ( + ((u = l[o]), + (h = u.sourceLocation([n - 1, i - 1])), + null != (null == h ? void 0 : h[0]) && + null != h[1]) + ) + return u; + return null == m[e] + ? null + : ((s = a(m[e][m[e].length - 1], { + filename: e, + sourceMap: !0, + literate: c.isLiterate(e), + })), + s.sourceMap); + } + return null; + }), + (Error.prepareStackTrace = function (t, n) { + var r, i, s; + return ( + (s = function (e, t, n) { + var r, i; + return ( + (i = l(e, t, n)), + null != i && + (r = i.sourceLocation([t - 1, n - 1])), + null == r ? null : [r[0] + 1, r[1] + 1] + ); + }), + (i = (function () { + var t, i, o; + for ( + o = [], t = 0, i = n.length; + t < i && + ((r = n[t]), r.getFunction() !== e.run); + t++ + ) + o.push(" at " + f(r, s)); + return o; + })()), + t.toString() + "\n" + i.join("\n") + "\n" + ); + }), + (u = function (e, t) { + var n, r, i, s; + if ( + ((r = t.split(/$/m)[0]), + (s = + null == r + ? void 0 + : r.match(/^#!\s*([^\s]+\s*)(.*)/)), + (n = + null == s || null == (i = s[2]) + ? void 0 + : i.split(/\s/).filter(function (e) { + return "" !== e; + })), + 1 < (null == n ? void 0 : n.length)) + ) + return ( + console.error( + "The script to be run begins with a shebang line with more than one\nargument. This script will fail on platforms such as Linux which only\nallow a single argument.", + ), + console.error( + "The shebang line was: '" + + r + + "' in file '" + + e + + "'", + ), + console.error( + "The arguments were: " + JSON.stringify(n), + ) + ); + }); + }.call(this), + { exports: e }.exports + ); + })()), + (require["./browser"] = (function () { + var exports = {}, + module = { exports: exports }; + return ( + function () { + var indexOf = [].indexOf, + CoffeeScript, + compile, + runScripts; + (CoffeeScript = require("./coffeescript")), + (compile = CoffeeScript.compile), + (CoffeeScript.eval = function (code) { + var options = + 1 < arguments.length && void 0 !== arguments[1] + ? arguments[1] + : {}; + return ( + null == options.bare && (options.bare = !0), + eval(compile(code, options)) + ); + }), + (CoffeeScript.run = function (e) { + var t = + 1 < arguments.length && void 0 !== arguments[1] + ? arguments[1] + : {}; + return ( + (t.bare = !0), + (t.shiftLine = !0), + Function(compile(e, t))() + ); + }), + (module.exports = CoffeeScript), + "undefined" == typeof window || + null === window || + ("undefined" != typeof btoa && + null !== btoa && + "undefined" != typeof JSON && + null !== JSON && + (compile = function (e) { + var t = + 1 < arguments.length && void 0 !== arguments[1] + ? arguments[1] + : {}; + return ( + (t.inlineMap = !0), CoffeeScript.compile(e, t) + ); + }), + (CoffeeScript.load = function (e, t) { + var n = + 2 < arguments.length && void 0 !== arguments[2] + ? arguments[2] + : {}, + r = + 3 < arguments.length && + void 0 !== arguments[3] && + arguments[3], + i; + return ( + (n.sourceFiles = [e]), + (i = window.ActiveXObject + ? new window.ActiveXObject("Microsoft.XMLHTTP") + : new window.XMLHttpRequest()), + i.open("GET", e, !0), + "overrideMimeType" in i && + i.overrideMimeType("text/plain"), + (i.onreadystatechange = function () { + var s, u; + if (4 === i.readyState) { + if (0 !== (u = i.status) && 200 !== u) + throw new Error("Could not load " + e); + if (((s = [i.responseText, n]), !r)) { + var f; + (f = CoffeeScript).run.apply( + f, + _toConsumableArray(s), + ); + } + if (t) return t(s); + } + }), + i.send(null) + ); + }), + (runScripts = function () { + var e, t, n, r, i, s, o, u, a, f; + for ( + f = window.document.getElementsByTagName("script"), + t = [ + "text/coffeescript", + "text/literate-coffeescript", + ], + e = (function () { + var e, n, r, i; + for ( + i = [], e = 0, n = f.length; + e < n; + e++ + ) + (u = f[e]), + ((r = u.type), + 0 <= indexOf.call(t, r)) && + i.push(u); + return i; + })(), + i = 0, + n = function () { + var r; + if (((r = e[i]), r instanceof Array)) { + var s; + return ( + (s = CoffeeScript).run.apply( + s, + _toConsumableArray(r), + ), + i++, + n() + ); + } + }, + r = s = 0, + o = e.length; + s < o; + r = ++s + ) + (a = e[r]), + (function (r, i) { + var s, o; + return ( + (s = { literate: r.type === t[1] }), + (o = + r.src || + r.getAttribute("data-src")), + o + ? ((s.filename = o), + CoffeeScript.load( + o, + function (t) { + return (e[i] = t), n(); + }, + s, + !0, + )) + : ((s.filename = + r.id && "" !== r.id + ? r.id + : "coffeescript" + + (0 === i ? "" : i)), + (s.sourceFiles = ["embedded"]), + (e[i] = [r.innerHTML, s])) + ); + })(a, r); + return n(); + }), + window.addEventListener + ? window.addEventListener( + "DOMContentLoaded", + runScripts, + !1, + ) + : window.attachEvent("onload", runScripts)); + }.call(this), + module.exports + ); + })()), + require["./browser"] + ); + })(); + "function" == typeof define && define.amd + ? define(function () { + return CoffeeScript; + }) + : (root.CoffeeScript = CoffeeScript); + })(this); + }), + define("ace/mode/coffee_worker", [], function (e, t, n) { + "use strict"; + var r = e("../lib/oop"), + i = e("../worker/mirror").Mirror, + s = e("../mode/coffee/coffee"); + window.addEventListener = function () {}; + var o = (t.Worker = function (e) { + i.call(this, e), this.setTimeout(250); + }); + r.inherits(o, i), + function () { + this.onUpdate = function () { + var e = this.doc.getValue(), + t = []; + try { + s.compile(e); + } catch (n) { + var r = n.location; + r && + t.push({ + row: r.first_line, + column: r.first_column, + endRow: r.last_line, + endColumn: r.last_column, + text: n.message, + type: "error", + }); + } + this.sender.emit("annotate", t); + }; + }.call(o.prototype); + }), + define("ace/lib/es5-shim", [], function (e, t, n) { + function r() {} + function w(e) { + try { + return Object.defineProperty(e, "sentinel", {}), "sentinel" in e; + } catch (t) {} + } + function H(e) { + return ( + (e = +e), + e !== e + ? (e = 0) + : e !== 0 && + e !== 1 / 0 && + e !== -1 / 0 && + (e = (e > 0 || -1) * Math.floor(Math.abs(e))), + e + ); + } + function B(e) { + var t = typeof e; + return ( + e === null || + t === "undefined" || + t === "boolean" || + t === "number" || + t === "string" + ); + } + function j(e) { + var t, n, r; + if (B(e)) return e; + n = e.valueOf; + if (typeof n == "function") { + t = n.call(e); + if (B(t)) return t; + } + r = e.toString; + if (typeof r == "function") { + t = r.call(e); + if (B(t)) return t; + } + throw new TypeError(); + } + Function.prototype.bind || + (Function.prototype.bind = function (t) { + var n = this; + if (typeof n != "function") + throw new TypeError("Function.prototype.bind called on incompatible " + n); + var i = u.call(arguments, 1), + s = function () { + if (this instanceof s) { + var e = n.apply(this, i.concat(u.call(arguments))); + return Object(e) === e ? e : this; + } + return n.apply(t, i.concat(u.call(arguments))); + }; + return ( + n.prototype && + ((r.prototype = n.prototype), + (s.prototype = new r()), + (r.prototype = null)), + s + ); + }); + var i = Function.prototype.call, + s = Array.prototype, + o = Object.prototype, + u = s.slice, + a = i.bind(o.toString), + f = i.bind(o.hasOwnProperty), + l, + c, + h, + p, + d; + if ((d = f(o, "__defineGetter__"))) + (l = i.bind(o.__defineGetter__)), + (c = i.bind(o.__defineSetter__)), + (h = i.bind(o.__lookupGetter__)), + (p = i.bind(o.__lookupSetter__)); + if ([1, 2].splice(0).length != 2) + if ( + !(function () { + function e(e) { + var t = new Array(e + 2); + return (t[0] = t[1] = 0), t; + } + var t = [], + n; + t.splice.apply(t, e(20)), + t.splice.apply(t, e(26)), + (n = t.length), + t.splice(5, 0, "XXX"), + n + 1 == t.length; + if (n + 1 == t.length) return !0; + })() + ) + Array.prototype.splice = function (e, t) { + var n = this.length; + e > 0 + ? e > n && (e = n) + : e == void 0 + ? (e = 0) + : e < 0 && (e = Math.max(n + e, 0)), + e + t < n || (t = n - e); + var r = this.slice(e, e + t), + i = u.call(arguments, 2), + s = i.length; + if (e === n) s && this.push.apply(this, i); + else { + var o = Math.min(t, n - e), + a = e + o, + f = a + s - o, + l = n - a, + c = n - o; + if (f < a) for (var h = 0; h < l; ++h) this[f + h] = this[a + h]; + else if (f > a) for (h = l; h--; ) this[f + h] = this[a + h]; + if (s && e === c) (this.length = c), this.push.apply(this, i); + else { + this.length = c + s; + for (h = 0; h < s; ++h) this[e + h] = i[h]; + } + } + return r; + }; + else { + var v = Array.prototype.splice; + Array.prototype.splice = function (e, t) { + return arguments.length + ? v.apply( + this, + [e === void 0 ? 0 : e, t === void 0 ? this.length - e : t].concat( + u.call(arguments, 2), + ), + ) + : []; + }; + } + Array.isArray || + (Array.isArray = function (t) { + return a(t) == "[object Array]"; + }); + var m = Object("a"), + g = m[0] != "a" || !(0 in m); + Array.prototype.forEach || + (Array.prototype.forEach = function (t) { + var n = F(this), + r = g && a(this) == "[object String]" ? this.split("") : n, + i = arguments[1], + s = -1, + o = r.length >>> 0; + if (a(t) != "[object Function]") throw new TypeError(); + while (++s < o) s in r && t.call(i, r[s], s, n); + }), + Array.prototype.map || + (Array.prototype.map = function (t) { + var n = F(this), + r = g && a(this) == "[object String]" ? this.split("") : n, + i = r.length >>> 0, + s = Array(i), + o = arguments[1]; + if (a(t) != "[object Function]") throw new TypeError(t + " is not a function"); + for (var u = 0; u < i; u++) u in r && (s[u] = t.call(o, r[u], u, n)); + return s; + }), + Array.prototype.filter || + (Array.prototype.filter = function (t) { + var n = F(this), + r = g && a(this) == "[object String]" ? this.split("") : n, + i = r.length >>> 0, + s = [], + o, + u = arguments[1]; + if (a(t) != "[object Function]") throw new TypeError(t + " is not a function"); + for (var f = 0; f < i; f++) + f in r && ((o = r[f]), t.call(u, o, f, n) && s.push(o)); + return s; + }), + Array.prototype.every || + (Array.prototype.every = function (t) { + var n = F(this), + r = g && a(this) == "[object String]" ? this.split("") : n, + i = r.length >>> 0, + s = arguments[1]; + if (a(t) != "[object Function]") throw new TypeError(t + " is not a function"); + for (var o = 0; o < i; o++) if (o in r && !t.call(s, r[o], o, n)) return !1; + return !0; + }), + Array.prototype.some || + (Array.prototype.some = function (t) { + var n = F(this), + r = g && a(this) == "[object String]" ? this.split("") : n, + i = r.length >>> 0, + s = arguments[1]; + if (a(t) != "[object Function]") throw new TypeError(t + " is not a function"); + for (var o = 0; o < i; o++) if (o in r && t.call(s, r[o], o, n)) return !0; + return !1; + }), + Array.prototype.reduce || + (Array.prototype.reduce = function (t) { + var n = F(this), + r = g && a(this) == "[object String]" ? this.split("") : n, + i = r.length >>> 0; + if (a(t) != "[object Function]") throw new TypeError(t + " is not a function"); + if (!i && arguments.length == 1) + throw new TypeError("reduce of empty array with no initial value"); + var s = 0, + o; + if (arguments.length >= 2) o = arguments[1]; + else + do { + if (s in r) { + o = r[s++]; + break; + } + if (++s >= i) + throw new TypeError("reduce of empty array with no initial value"); + } while (!0); + for (; s < i; s++) s in r && (o = t.call(void 0, o, r[s], s, n)); + return o; + }), + Array.prototype.reduceRight || + (Array.prototype.reduceRight = function (t) { + var n = F(this), + r = g && a(this) == "[object String]" ? this.split("") : n, + i = r.length >>> 0; + if (a(t) != "[object Function]") throw new TypeError(t + " is not a function"); + if (!i && arguments.length == 1) + throw new TypeError("reduceRight of empty array with no initial value"); + var s, + o = i - 1; + if (arguments.length >= 2) s = arguments[1]; + else + do { + if (o in r) { + s = r[o--]; + break; + } + if (--o < 0) + throw new TypeError( + "reduceRight of empty array with no initial value", + ); + } while (!0); + do o in this && (s = t.call(void 0, s, r[o], o, n)); + while (o--); + return s; + }); + if (!Array.prototype.indexOf || [0, 1].indexOf(1, 2) != -1) + Array.prototype.indexOf = function (t) { + var n = g && a(this) == "[object String]" ? this.split("") : F(this), + r = n.length >>> 0; + if (!r) return -1; + var i = 0; + arguments.length > 1 && (i = H(arguments[1])), + (i = i >= 0 ? i : Math.max(0, r + i)); + for (; i < r; i++) if (i in n && n[i] === t) return i; + return -1; + }; + if (!Array.prototype.lastIndexOf || [0, 1].lastIndexOf(0, -3) != -1) + Array.prototype.lastIndexOf = function (t) { + var n = g && a(this) == "[object String]" ? this.split("") : F(this), + r = n.length >>> 0; + if (!r) return -1; + var i = r - 1; + arguments.length > 1 && (i = Math.min(i, H(arguments[1]))), + (i = i >= 0 ? i : r - Math.abs(i)); + for (; i >= 0; i--) if (i in n && t === n[i]) return i; + return -1; + }; + Object.getPrototypeOf || + (Object.getPrototypeOf = function (t) { + return t.__proto__ || (t.constructor ? t.constructor.prototype : o); + }); + if (!Object.getOwnPropertyDescriptor) { + var y = "Object.getOwnPropertyDescriptor called on a non-object: "; + Object.getOwnPropertyDescriptor = function (t, n) { + if ((typeof t != "object" && typeof t != "function") || t === null) + throw new TypeError(y + t); + if (!f(t, n)) return; + var r, i, s; + r = { enumerable: !0, configurable: !0 }; + if (d) { + var u = t.__proto__; + t.__proto__ = o; + var i = h(t, n), + s = p(t, n); + t.__proto__ = u; + if (i || s) return i && (r.get = i), s && (r.set = s), r; + } + return (r.value = t[n]), r; + }; + } + Object.getOwnPropertyNames || + (Object.getOwnPropertyNames = function (t) { + return Object.keys(t); + }); + if (!Object.create) { + var b; + Object.prototype.__proto__ === null + ? (b = function () { + return { __proto__: null }; + }) + : (b = function () { + var e = {}; + for (var t in e) e[t] = null; + return ( + (e.constructor = + e.hasOwnProperty = + e.propertyIsEnumerable = + e.isPrototypeOf = + e.toLocaleString = + e.toString = + e.valueOf = + e.__proto__ = + null), + e + ); + }), + (Object.create = function (t, n) { + var r; + if (t === null) r = b(); + else { + if (typeof t != "object") + throw new TypeError("typeof prototype[" + typeof t + "] != 'object'"); + var i = function () {}; + (i.prototype = t), (r = new i()), (r.__proto__ = t); + } + return n !== void 0 && Object.defineProperties(r, n), r; + }); + } + if (Object.defineProperty) { + var E = w({}), + S = typeof document == "undefined" || w(document.createElement("div")); + if (!E || !S) var x = Object.defineProperty; + } + if (!Object.defineProperty || x) { + var T = "Property description must be an object: ", + N = "Object.defineProperty called on non-object: ", + C = "getters & setters can not be defined on this javascript engine"; + Object.defineProperty = function (t, n, r) { + if ((typeof t != "object" && typeof t != "function") || t === null) + throw new TypeError(N + t); + if ((typeof r != "object" && typeof r != "function") || r === null) + throw new TypeError(T + r); + if (x) + try { + return x.call(Object, t, n, r); + } catch (i) {} + if (f(r, "value")) + if (d && (h(t, n) || p(t, n))) { + var s = t.__proto__; + (t.__proto__ = o), delete t[n], (t[n] = r.value), (t.__proto__ = s); + } else t[n] = r.value; + else { + if (!d) throw new TypeError(C); + f(r, "get") && l(t, n, r.get), f(r, "set") && c(t, n, r.set); + } + return t; + }; + } + Object.defineProperties || + (Object.defineProperties = function (t, n) { + for (var r in n) f(n, r) && Object.defineProperty(t, r, n[r]); + return t; + }), + Object.seal || + (Object.seal = function (t) { + return t; + }), + Object.freeze || + (Object.freeze = function (t) { + return t; + }); + try { + Object.freeze(function () {}); + } catch (k) { + Object.freeze = (function (t) { + return function (n) { + return typeof n == "function" ? n : t(n); + }; + })(Object.freeze); + } + Object.preventExtensions || + (Object.preventExtensions = function (t) { + return t; + }), + Object.isSealed || + (Object.isSealed = function (t) { + return !1; + }), + Object.isFrozen || + (Object.isFrozen = function (t) { + return !1; + }), + Object.isExtensible || + (Object.isExtensible = function (t) { + if (Object(t) === t) throw new TypeError(); + var n = ""; + while (f(t, n)) n += "?"; + t[n] = !0; + var r = f(t, n); + return delete t[n], r; + }); + if (!Object.keys) { + var L = !0, + A = [ + "toString", + "toLocaleString", + "valueOf", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "constructor", + ], + O = A.length; + for (var M in { toString: null }) L = !1; + Object.keys = function I(e) { + if ((typeof e != "object" && typeof e != "function") || e === null) + throw new TypeError("Object.keys called on a non-object"); + var I = []; + for (var t in e) f(e, t) && I.push(t); + if (L) + for (var n = 0, r = O; n < r; n++) { + var i = A[n]; + f(e, i) && I.push(i); + } + return I; + }; + } + Date.now || + (Date.now = function () { + return new Date().getTime(); + }); + var _ = + " \n\x0b\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\ufeff"; + if (!String.prototype.trim || _.trim()) { + _ = "[" + _ + "]"; + var D = new RegExp("^" + _ + _ + "*"), + P = new RegExp(_ + _ + "*$"); + String.prototype.trim = function () { + return String(this).replace(D, "").replace(P, ""); + }; + } + var F = function (e) { + if (e == null) throw new TypeError("can't convert " + e + " to object"); + return Object(e); + }; + }); diff --git a/web/static/ace/worker-css.js b/web/static/ace/worker-css.js index 3e8f9fc1a..3b015c715 100644 --- a/web/static/ace/worker-css.js +++ b/web/static/ace/worker-css.js @@ -1 +1,7147 @@ -"no use strict";!function(e){function t(e,t){var n=e,r="";while(n){var i=t[n];if(typeof i=="string")return i+r;if(i)return i.location.replace(/\/*$/,"/")+(r||i.main||i.name);if(i===!1)return"";var s=n.lastIndexOf("/");if(s===-1)break;r=n.substr(s)+r,n=n.slice(0,s)}return e}if(typeof e.window!="undefined"&&e.document)return;if(e.require&&e.define)return;e.console||(e.console=function(){var e=Array.prototype.slice.call(arguments,0);postMessage({type:"log",data:e})},e.console.error=e.console.warn=e.console.log=e.console.trace=e.console),e.window=e,e.ace=e,e.onerror=function(e,t,n,r,i){postMessage({type:"error",data:{message:e,data:i.data,file:t,line:n,col:r,stack:i.stack}})},e.normalizeModule=function(t,n){if(n.indexOf("!")!==-1){var r=n.split("!");return e.normalizeModule(t,r[0])+"!"+e.normalizeModule(t,r[1])}if(n.charAt(0)=="."){var i=t.split("/").slice(0,-1).join("/");n=(i?i+"/":"")+n;while(n.indexOf(".")!==-1&&s!=n){var s=n;n=n.replace(/^\.\//,"").replace(/\/\.\//,"/").replace(/[^\/]+\/\.\.\//,"")}}return n},e.require=function(r,i){i||(i=r,r=null);if(!i.charAt)throw new Error("worker.js require() accepts only (parentId, id) as arguments");i=e.normalizeModule(r,i);var s=e.require.modules[i];if(s)return s.initialized||(s.initialized=!0,s.exports=s.factory().exports),s.exports;if(!e.require.tlns)return console.log("unable to load "+i);var o=t(i,e.require.tlns);return o.slice(-3)!=".js"&&(o+=".js"),e.require.id=i,e.require.modules[i]={},importScripts(o),e.require(r,i)},e.require.modules={},e.require.tlns={},e.define=function(t,n,r){arguments.length==2?(r=n,typeof t!="string"&&(n=t,t=e.require.id)):arguments.length==1&&(r=t,n=[],t=e.require.id);if(typeof r!="function"){e.require.modules[t]={exports:r,initialized:!0};return}n.length||(n=["require","exports","module"]);var i=function(n){return e.require(t,n)};e.require.modules[t]={exports:{},factory:function(){var e=this,t=r.apply(this,n.slice(0,r.length).map(function(t){switch(t){case"require":return i;case"exports":return e.exports;case"module":return e;default:return i(t)}}));return t&&(e.exports=t),e}}},e.define.amd={},require.tlns={},e.initBaseUrls=function(t){for(var n in t)require.tlns[n]=t[n]},e.initSender=function(){var n=e.require("ace/lib/event_emitter").EventEmitter,r=e.require("ace/lib/oop"),i=function(){};return function(){r.implement(this,n),this.callback=function(e,t){postMessage({type:"call",id:t,data:e})},this.emit=function(e,t){postMessage({type:"event",name:e,data:t})}}.call(i.prototype),new i};var n=e.main=null,r=e.sender=null;e.onmessage=function(t){var i=t.data;if(i.event&&r)r._signal(i.event,i.data);else if(i.command)if(n[i.command])n[i.command].apply(n,i.args);else{if(!e[i.command])throw new Error("Unknown command:"+i.command);e[i.command].apply(e,i.args)}else if(i.init){e.initBaseUrls(i.tlns),require("ace/lib/es5-shim"),r=e.sender=e.initSender();var s=require(i.module)[i.classname];n=e.main=new s(r)}}}(this),define("ace/lib/oop",[],function(e,t,n){"use strict";t.inherits=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})},t.mixin=function(e,t){for(var n in t)e[n]=t[n];return e},t.implement=function(e,n){t.mixin(e,n)}}),define("ace/lib/lang",[],function(e,t,n){"use strict";t.last=function(e){return e[e.length-1]},t.stringReverse=function(e){return e.split("").reverse().join("")},t.stringRepeat=function(e,t){var n="";while(t>0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\s\s*/,i=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(r,"")},t.stringTrimRight=function(e){return e.replace(i,"")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e=="object"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e=="object"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?tthis.end.column?1:0:ethis.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};else if(this.end.rowt)var r={row:t+1,column:0};else if(this.start.row=0&&t.row=0&&t.column<=e[t.row].length}function s(e,t){t.action!="insert"&&t.action!="remove"&&r(t,"delta.action must be 'insert' or 'remove'"),t.lines instanceof Array||r(t,"delta.lines must be an Array"),(!t.start||!t.end)&&r(t,"delta.start/end must be an present");var n=t.start;i(e,t.start)||r(t,"delta.start must be contained in document");var s=t.end;t.action=="remove"&&!i(e,s)&&r(t,"delta.end must contained in document for 'remove' actions");var o=s.row-n.row,u=s.column-(o==0?n.column:0);(o!=t.lines.length-1||t.lines[o].length!=u)&&r(t,"delta.range must match delta lines")}t.applyDelta=function(e,t,n){var r=t.start.row,i=t.start.column,s=e[r]||"";switch(t.action){case"insert":var o=t.lines;if(o.length===1)e[r]=s.substring(0,i)+t.lines[0]+s.substring(i);else{var u=[r,1].concat(t.lines);e.splice.apply(e,u),e[r]=s.substring(0,i)+e[r],e[r+t.lines.length-1]+=s.substring(i)}break;case"remove":var a=t.end.column,f=t.end.row;r===f?e[r]=s.substring(0,i)+s.substring(a):e.splice(r,f-r+1,s.substring(0,i)+e[f].substring(a))}}}),define("ace/lib/event_emitter",[],function(e,t,n){"use strict";var r={},i=function(){this.propagationStopped=!0},s=function(){this.defaultPrevented=!0};r._emit=r._dispatchEvent=function(e,t){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var n=this._eventRegistry[e]||[],r=this._defaultHandlers[e];if(!n.length&&!r)return;if(typeof t!="object"||!t)t={};t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=i),t.preventDefault||(t.preventDefault=s),n=n.slice();for(var o=0;othis.row)return;var n=t(e,{row:this.row,column:this.column},this.$insertRight);this.setPosition(n.row,n.column,!0)},this.setPosition=function(e,t,n){var r;n?r={row:e,column:t}:r=this.$clipPositionToDocument(e,t);if(this.row==r.row&&this.column==r.column)return;var i={row:this.row,column:this.column};this.row=r.row,this.column=r.column,this._signal("change",{old:i,value:r})},this.detach=function(){this.document.removeEventListener("change",this.$onChange)},this.attach=function(e){this.document=e||this.document,this.document.on("change",this.$onChange)},this.$clipPositionToDocument=function(e,t){var n={};return e>=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),define("ace/document",[],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./apply_delta").applyDelta,s=e("./lib/event_emitter").EventEmitter,o=e("./range").Range,u=e("./anchor").Anchor,a=function(e){this.$lines=[""],e.length===0?this.$lines=[""]:Array.isArray(e)?this.insertMergedLines({row:0,column:0},e):this.insert({row:0,column:0},e)};(function(){r.implement(this,s),this.setValue=function(e){var t=this.getLength()-1;this.remove(new o(0,0,t,this.getLine(t).length)),this.insert({row:0,column:0},e)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(e,t){return new u(this,e,t)},"aaa".split(/a/).length===0?this.$split=function(e){return e.replace(/\r\n|\r/g,"\n").split("\n")}:this.$split=function(e){return e.split(/\r\n|\r|\n/)},this.$detectNewLine=function(e){var t=e.match(/^.*?(\r\n|\r|\n)/m);this.$autoNewLine=t?t[1]:"\n",this._signal("changeNewLineMode")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case"windows":return"\r\n";case"unix":return"\n";default:return this.$autoNewLine||"\n"}},this.$autoNewLine="",this.$newLineMode="auto",this.setNewLineMode=function(e){if(this.$newLineMode===e)return;this.$newLineMode=e,this._signal("changeNewLineMode")},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(e){return e=="\r\n"||e=="\r"||e=="\n"},this.getLine=function(e){return this.$lines[e]||""},this.getLines=function(e,t){return this.$lines.slice(e,t+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(e){return this.getLinesForRange(e).join(this.getNewLineCharacter())},this.getLinesForRange=function(e){var t;if(e.start.row===e.end.row)t=[this.getLine(e.start.row).substring(e.start.column,e.end.column)];else{t=this.getLines(e.start.row,e.end.row),t[0]=(t[0]||"").substring(e.start.column);var n=t.length-1;e.end.row-e.start.row==n&&(t[n]=t[n].substring(0,e.end.column))}return t},this.insertLines=function(e,t){return console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."),this.insertFullLines(e,t)},this.removeLines=function(e,t){return console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."),this.removeFullLines(e,t)},this.insertNewLine=function(e){return console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead."),this.insertMergedLines(e,["",""])},this.insert=function(e,t){return this.getLength()<=1&&this.$detectNewLine(t),this.insertMergedLines(e,this.$split(t))},this.insertInLine=function(e,t){var n=this.clippedPos(e.row,e.column),r=this.pos(e.row,e.column+t.length);return this.applyDelta({start:n,end:r,action:"insert",lines:[t]},!0),this.clonePos(r)},this.clippedPos=function(e,t){var n=this.getLength();e===undefined?e=n:e<0?e=0:e>=n&&(e=n-1,t=undefined);var r=this.getLine(e);return t==undefined&&(t=r.length),t=Math.min(Math.max(t,0),r.length),{row:e,column:t}},this.clonePos=function(e){return{row:e.row,column:e.column}},this.pos=function(e,t){return{row:e,column:t}},this.$clipPosition=function(e){var t=this.getLength();return e.row>=t?(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length):(e.row=Math.max(0,e.row),e.column=Math.min(Math.max(e.column,0),this.getLine(e.row).length)),e},this.insertFullLines=function(e,t){e=Math.min(Math.max(e,0),this.getLength());var n=0;e0,r=t=0&&this.applyDelta({start:this.pos(e,this.getLine(e).length),end:this.pos(e+1,0),action:"remove",lines:["",""]})},this.replace=function(e,t){e instanceof o||(e=o.fromPoints(e.start,e.end));if(t.length===0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);var n;return t?n=this.insert(e.start,t):n=e.start,n},this.applyDeltas=function(e){for(var t=0;t=0;t--)this.revertDelta(e[t])},this.applyDelta=function(e,t){var n=e.action=="insert";if(n?e.lines.length<=1&&!e.lines[0]:!o.comparePoints(e.start,e.end))return;n&&e.lines.length>2e4?this.$splitAndapplyLargeDelta(e,2e4):(i(this.$lines,e,t),this._signal("change",e))},this.$splitAndapplyLargeDelta=function(e,t){var n=e.lines,r=n.length-t+1,i=e.start.row,s=e.start.column;for(var o=0,u=0;o=0&&this._ltIndex-1&&!t[u.type].hide&&(u.channel=t[u.type].channel,this._token=u,this._lt.push(u),this._ltIndexCache.push(this._lt.length-this._ltIndex+i),this._lt.length>5&&this._lt.shift(),this._ltIndexCache.length>5&&this._ltIndexCache.shift(),this._ltIndex=this._lt.length),a=t[u.type],a&&(a.hide||a.channel!==undefined&&e!==a.channel)?this.get(e):u.type},LA:function(e){var t=e,n;if(e>0){if(e>5)throw new Error("Too much lookahead.");while(t)n=this.get(),t--;while(tthis._tokenData.length?"UNKNOWN_TOKEN":this._tokenData[e].name},tokenType:function(e){return this._tokenData[e]||-1},unget:function(){if(!this._ltIndexCache.length)throw new Error("Too much lookahead.");this._ltIndex-=this._ltIndexCache.pop(),this._token=this._lt[this._ltIndex-1]}},parserlib.util={StringReader:t,SyntaxError:n,SyntaxUnit:r,EventTarget:e,TokenStreamBase:i}})(),function(){function Combinator(e,t,n){SyntaxUnit.call(this,e,t,n,Parser.COMBINATOR_TYPE),this.type="unknown",/^\s+$/.test(e)?this.type="descendant":e==">"?this.type="child":e=="+"?this.type="adjacent-sibling":e=="~"&&(this.type="sibling")}function MediaFeature(e,t){SyntaxUnit.call(this,"("+e+(t!==null?":"+t:"")+")",e.startLine,e.startCol,Parser.MEDIA_FEATURE_TYPE),this.name=e,this.value=t}function MediaQuery(e,t,n,r,i){SyntaxUnit.call(this,(e?e+" ":"")+(t?t:"")+(t&&n.length>0?" and ":"")+n.join(" and "),r,i,Parser.MEDIA_QUERY_TYPE),this.modifier=e,this.mediaType=t,this.features=n}function Parser(e){EventTarget.call(this),this.options=e||{},this._tokenStream=null}function PropertyName(e,t,n,r){SyntaxUnit.call(this,e,n,r,Parser.PROPERTY_NAME_TYPE),this.hack=t}function PropertyValue(e,t,n){SyntaxUnit.call(this,e.join(" "),t,n,Parser.PROPERTY_VALUE_TYPE),this.parts=e}function PropertyValueIterator(e){this._i=0,this._parts=e.parts,this._marks=[],this.value=e}function PropertyValuePart(text,line,col){SyntaxUnit.call(this,text,line,col,Parser.PROPERTY_VALUE_PART_TYPE),this.type="unknown";var temp;if(/^([+\-]?[\d\.]+)([a-z]+)$/i.test(text)){this.type="dimension",this.value=+RegExp.$1,this.units=RegExp.$2;switch(this.units.toLowerCase()){case"em":case"rem":case"ex":case"px":case"cm":case"mm":case"in":case"pt":case"pc":case"ch":case"vh":case"vw":case"vmax":case"vmin":this.type="length";break;case"deg":case"rad":case"grad":this.type="angle";break;case"ms":case"s":this.type="time";break;case"hz":case"khz":this.type="frequency";break;case"dpi":case"dpcm":this.type="resolution"}}else/^([+\-]?[\d\.]+)%$/i.test(text)?(this.type="percentage",this.value=+RegExp.$1):/^([+\-]?\d+)$/i.test(text)?(this.type="integer",this.value=+RegExp.$1):/^([+\-]?[\d\.]+)$/i.test(text)?(this.type="number",this.value=+RegExp.$1):/^#([a-f0-9]{3,6})/i.test(text)?(this.type="color",temp=RegExp.$1,temp.length==3?(this.red=parseInt(temp.charAt(0)+temp.charAt(0),16),this.green=parseInt(temp.charAt(1)+temp.charAt(1),16),this.blue=parseInt(temp.charAt(2)+temp.charAt(2),16)):(this.red=parseInt(temp.substring(0,2),16),this.green=parseInt(temp.substring(2,4),16),this.blue=parseInt(temp.substring(4,6),16))):/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/i.test(text)?(this.type="color",this.red=+RegExp.$1,this.green=+RegExp.$2,this.blue=+RegExp.$3):/^rgb\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)?(this.type="color",this.red=+RegExp.$1*255/100,this.green=+RegExp.$2*255/100,this.blue=+RegExp.$3*255/100):/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/i.test(text)?(this.type="color",this.red=+RegExp.$1,this.green=+RegExp.$2,this.blue=+RegExp.$3,this.alpha=+RegExp.$4):/^rgba\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)?(this.type="color",this.red=+RegExp.$1*255/100,this.green=+RegExp.$2*255/100,this.blue=+RegExp.$3*255/100,this.alpha=+RegExp.$4):/^hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)?(this.type="color",this.hue=+RegExp.$1,this.saturation=+RegExp.$2/100,this.lightness=+RegExp.$3/100):/^hsla\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)?(this.type="color",this.hue=+RegExp.$1,this.saturation=+RegExp.$2/100,this.lightness=+RegExp.$3/100,this.alpha=+RegExp.$4):/^url\(["']?([^\)"']+)["']?\)/i.test(text)?(this.type="uri",this.uri=RegExp.$1):/^([^\(]+)\(/i.test(text)?(this.type="function",this.name=RegExp.$1,this.value=text):/^["'][^"']*["']/.test(text)?(this.type="string",this.value=eval(text)):Colors[text.toLowerCase()]?(this.type="color",temp=Colors[text.toLowerCase()].substring(1),this.red=parseInt(temp.substring(0,2),16),this.green=parseInt(temp.substring(2,4),16),this.blue=parseInt(temp.substring(4,6),16)):/^[\,\/]$/.test(text)?(this.type="operator",this.value=text):/^[a-z\-_\u0080-\uFFFF][a-z0-9\-_\u0080-\uFFFF]*$/i.test(text)&&(this.type="identifier",this.value=text)}function Selector(e,t,n){SyntaxUnit.call(this,e.join(" "),t,n,Parser.SELECTOR_TYPE),this.parts=e,this.specificity=Specificity.calculate(this)}function SelectorPart(e,t,n,r,i){SyntaxUnit.call(this,n,r,i,Parser.SELECTOR_PART_TYPE),this.elementName=e,this.modifiers=t}function SelectorSubPart(e,t,n,r){SyntaxUnit.call(this,e,n,r,Parser.SELECTOR_SUB_PART_TYPE),this.type=t,this.args=[]}function Specificity(e,t,n,r){this.a=e,this.b=t,this.c=n,this.d=r}function isHexDigit(e){return e!==null&&h.test(e)}function isDigit(e){return e!==null&&/\d/.test(e)}function isWhitespace(e){return e!==null&&/\s/.test(e)}function isNewLine(e){return e!==null&&nl.test(e)}function isNameStart(e){return e!==null&&/[a-z_\u0080-\uFFFF\\]/i.test(e)}function isNameChar(e){return e!==null&&(isNameStart(e)||/[0-9\-\\]/.test(e))}function isIdentStart(e){return e!==null&&(isNameStart(e)||/\-\\/.test(e))}function mix(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}function TokenStream(e){TokenStreamBase.call(this,e,Tokens)}function ValidationError(e,t,n){this.col=n,this.line=t,this.message=e}var EventTarget=parserlib.util.EventTarget,TokenStreamBase=parserlib.util.TokenStreamBase,StringReader=parserlib.util.StringReader,SyntaxError=parserlib.util.SyntaxError,SyntaxUnit=parserlib.util.SyntaxUnit,Colors={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgrey:"#a9a9a9",darkgreen:"#006400",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",grey:"#808080",green:"#008000",greenyellow:"#adff2f",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgrey:"#d3d3d3",lightgreen:"#90ee90",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370d8",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#d87093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32",activeBorder:"Active window border.",activecaption:"Active window caption.",appworkspace:"Background color of multiple document interface.",background:"Desktop background.",buttonface:"The face background color for 3-D elements that appear 3-D due to one layer of surrounding border.",buttonhighlight:"The color of the border facing the light source for 3-D elements that appear 3-D due to one layer of surrounding border.",buttonshadow:"The color of the border away from the light source for 3-D elements that appear 3-D due to one layer of surrounding border.",buttontext:"Text on push buttons.",captiontext:"Text in caption, size box, and scrollbar arrow box.",graytext:"Grayed (disabled) text. This color is set to #000 if the current display driver does not support a solid gray color.",greytext:"Greyed (disabled) text. This color is set to #000 if the current display driver does not support a solid grey color.",highlight:"Item(s) selected in a control.",highlighttext:"Text of item(s) selected in a control.",inactiveborder:"Inactive window border.",inactivecaption:"Inactive window caption.",inactivecaptiontext:"Color of text in an inactive caption.",infobackground:"Background color for tooltip controls.",infotext:"Text color for tooltip controls.",menu:"Menu background.",menutext:"Text in menus.",scrollbar:"Scroll bar gray area.",threeddarkshadow:"The color of the darker (generally outer) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",threedface:"The face background color for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",threedhighlight:"The color of the lighter (generally outer) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",threedlightshadow:"The color of the darker (generally inner) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",threedshadow:"The color of the lighter (generally inner) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",window:"Window background.",windowframe:"Window frame.",windowtext:"Text in windows."};Combinator.prototype=new SyntaxUnit,Combinator.prototype.constructor=Combinator,MediaFeature.prototype=new SyntaxUnit,MediaFeature.prototype.constructor=MediaFeature,MediaQuery.prototype=new SyntaxUnit,MediaQuery.prototype.constructor=MediaQuery,Parser.DEFAULT_TYPE=0,Parser.COMBINATOR_TYPE=1,Parser.MEDIA_FEATURE_TYPE=2,Parser.MEDIA_QUERY_TYPE=3,Parser.PROPERTY_NAME_TYPE=4,Parser.PROPERTY_VALUE_TYPE=5,Parser.PROPERTY_VALUE_PART_TYPE=6,Parser.SELECTOR_TYPE=7,Parser.SELECTOR_PART_TYPE=8,Parser.SELECTOR_SUB_PART_TYPE=9,Parser.prototype=function(){var e=new EventTarget,t,n={constructor:Parser,DEFAULT_TYPE:0,COMBINATOR_TYPE:1,MEDIA_FEATURE_TYPE:2,MEDIA_QUERY_TYPE:3,PROPERTY_NAME_TYPE:4,PROPERTY_VALUE_TYPE:5,PROPERTY_VALUE_PART_TYPE:6,SELECTOR_TYPE:7,SELECTOR_PART_TYPE:8,SELECTOR_SUB_PART_TYPE:9,_stylesheet:function(){var e=this._tokenStream,t=null,n,r,i;this.fire("startstylesheet"),this._charset(),this._skipCruft();while(e.peek()==Tokens.IMPORT_SYM)this._import(),this._skipCruft();while(e.peek()==Tokens.NAMESPACE_SYM)this._namespace(),this._skipCruft();i=e.peek();while(i>Tokens.EOF){try{switch(i){case Tokens.MEDIA_SYM:this._media(),this._skipCruft();break;case Tokens.PAGE_SYM:this._page(),this._skipCruft();break;case Tokens.FONT_FACE_SYM:this._font_face(),this._skipCruft();break;case Tokens.KEYFRAMES_SYM:this._keyframes(),this._skipCruft();break;case Tokens.VIEWPORT_SYM:this._viewport(),this._skipCruft();break;case Tokens.UNKNOWN_SYM:e.get();if(!!this.options.strict)throw new SyntaxError("Unknown @ rule.",e.LT(0).startLine,e.LT(0).startCol);this.fire({type:"error",error:null,message:"Unknown @ rule: "+e.LT(0).value+".",line:e.LT(0).startLine,col:e.LT(0).startCol}),n=0;while(e.advance([Tokens.LBRACE,Tokens.RBRACE])==Tokens.LBRACE)n++;while(n)e.advance([Tokens.RBRACE]),n--;break;case Tokens.S:this._readWhitespace();break;default:if(!this._ruleset())switch(i){case Tokens.CHARSET_SYM:throw r=e.LT(1),this._charset(!1),new SyntaxError("@charset not allowed here.",r.startLine,r.startCol);case Tokens.IMPORT_SYM:throw r=e.LT(1),this._import(!1),new SyntaxError("@import not allowed here.",r.startLine,r.startCol);case Tokens.NAMESPACE_SYM:throw r=e.LT(1),this._namespace(!1),new SyntaxError("@namespace not allowed here.",r.startLine,r.startCol);default:e.get(),this._unexpectedToken(e.token())}}}catch(s){if(!(s instanceof SyntaxError&&!this.options.strict))throw s;this.fire({type:"error",error:s,message:s.message,line:s.line,col:s.col})}i=e.peek()}i!=Tokens.EOF&&this._unexpectedToken(e.token()),this.fire("endstylesheet")},_charset:function(e){var t=this._tokenStream,n,r,i,s;t.match(Tokens.CHARSET_SYM)&&(i=t.token().startLine,s=t.token().startCol,this._readWhitespace(),t.mustMatch(Tokens.STRING),r=t.token(),n=r.value,this._readWhitespace(),t.mustMatch(Tokens.SEMICOLON),e!==!1&&this.fire({type:"charset",charset:n,line:i,col:s}))},_import:function(e){var t=this._tokenStream,n,r,i,s=[];t.mustMatch(Tokens.IMPORT_SYM),i=t.token(),this._readWhitespace(),t.mustMatch([Tokens.STRING,Tokens.URI]),r=t.token().value.replace(/^(?:url\()?["']?([^"']+?)["']?\)?$/,"$1"),this._readWhitespace(),s=this._media_query_list(),t.mustMatch(Tokens.SEMICOLON),this._readWhitespace(),e!==!1&&this.fire({type:"import",uri:r,media:s,line:i.startLine,col:i.startCol})},_namespace:function(e){var t=this._tokenStream,n,r,i,s;t.mustMatch(Tokens.NAMESPACE_SYM),n=t.token().startLine,r=t.token().startCol,this._readWhitespace(),t.match(Tokens.IDENT)&&(i=t.token().value,this._readWhitespace()),t.mustMatch([Tokens.STRING,Tokens.URI]),s=t.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/,"$1"),this._readWhitespace(),t.mustMatch(Tokens.SEMICOLON),this._readWhitespace(),e!==!1&&this.fire({type:"namespace",prefix:i,uri:s,line:n,col:r})},_media:function(){var e=this._tokenStream,t,n,r;e.mustMatch(Tokens.MEDIA_SYM),t=e.token().startLine,n=e.token().startCol,this._readWhitespace(),r=this._media_query_list(),e.mustMatch(Tokens.LBRACE),this._readWhitespace(),this.fire({type:"startmedia",media:r,line:t,col:n});for(;;)if(e.peek()==Tokens.PAGE_SYM)this._page();else if(e.peek()==Tokens.FONT_FACE_SYM)this._font_face();else if(e.peek()==Tokens.VIEWPORT_SYM)this._viewport();else if(!this._ruleset())break;e.mustMatch(Tokens.RBRACE),this._readWhitespace(),this.fire({type:"endmedia",media:r,line:t,col:n})},_media_query_list:function(){var e=this._tokenStream,t=[];this._readWhitespace(),(e.peek()==Tokens.IDENT||e.peek()==Tokens.LPAREN)&&t.push(this._media_query());while(e.match(Tokens.COMMA))this._readWhitespace(),t.push(this._media_query());return t},_media_query:function(){var e=this._tokenStream,t=null,n=null,r=null,i=[];e.match(Tokens.IDENT)&&(n=e.token().value.toLowerCase(),n!="only"&&n!="not"?(e.unget(),n=null):r=e.token()),this._readWhitespace(),e.peek()==Tokens.IDENT?(t=this._media_type(),r===null&&(r=e.token())):e.peek()==Tokens.LPAREN&&(r===null&&(r=e.LT(1)),i.push(this._media_expression()));if(t===null&&i.length===0)return null;this._readWhitespace();while(e.match(Tokens.IDENT))e.token().value.toLowerCase()!="and"&&this._unexpectedToken(e.token()),this._readWhitespace(),i.push(this._media_expression());return new MediaQuery(n,t,i,r.startLine,r.startCol)},_media_type:function(){return this._media_feature()},_media_expression:function(){var e=this._tokenStream,t=null,n,r=null;return e.mustMatch(Tokens.LPAREN),this._readWhitespace(),t=this._media_feature(),this._readWhitespace(),e.match(Tokens.COLON)&&(this._readWhitespace(),n=e.LT(1),r=this._expression()),e.mustMatch(Tokens.RPAREN),this._readWhitespace(),new MediaFeature(t,r?new SyntaxUnit(r,n.startLine,n.startCol):null)},_media_feature:function(){var e=this._tokenStream;return e.mustMatch(Tokens.IDENT),SyntaxUnit.fromToken(e.token())},_page:function(){var e=this._tokenStream,t,n,r=null,i=null;e.mustMatch(Tokens.PAGE_SYM),t=e.token().startLine,n=e.token().startCol,this._readWhitespace(),e.match(Tokens.IDENT)&&(r=e.token().value,r.toLowerCase()==="auto"&&this._unexpectedToken(e.token())),e.peek()==Tokens.COLON&&(i=this._pseudo_page()),this._readWhitespace(),this.fire({type:"startpage",id:r,pseudo:i,line:t,col:n}),this._readDeclarations(!0,!0),this.fire({type:"endpage",id:r,pseudo:i,line:t,col:n})},_margin:function(){var e=this._tokenStream,t,n,r=this._margin_sym();return r?(t=e.token().startLine,n=e.token().startCol,this.fire({type:"startpagemargin",margin:r,line:t,col:n}),this._readDeclarations(!0),this.fire({type:"endpagemargin",margin:r,line:t,col:n}),!0):!1},_margin_sym:function(){var e=this._tokenStream;return e.match([Tokens.TOPLEFTCORNER_SYM,Tokens.TOPLEFT_SYM,Tokens.TOPCENTER_SYM,Tokens.TOPRIGHT_SYM,Tokens.TOPRIGHTCORNER_SYM,Tokens.BOTTOMLEFTCORNER_SYM,Tokens.BOTTOMLEFT_SYM,Tokens.BOTTOMCENTER_SYM,Tokens.BOTTOMRIGHT_SYM,Tokens.BOTTOMRIGHTCORNER_SYM,Tokens.LEFTTOP_SYM,Tokens.LEFTMIDDLE_SYM,Tokens.LEFTBOTTOM_SYM,Tokens.RIGHTTOP_SYM,Tokens.RIGHTMIDDLE_SYM,Tokens.RIGHTBOTTOM_SYM])?SyntaxUnit.fromToken(e.token()):null},_pseudo_page:function(){var e=this._tokenStream;return e.mustMatch(Tokens.COLON),e.mustMatch(Tokens.IDENT),e.token().value},_font_face:function(){var e=this._tokenStream,t,n;e.mustMatch(Tokens.FONT_FACE_SYM),t=e.token().startLine,n=e.token().startCol,this._readWhitespace(),this.fire({type:"startfontface",line:t,col:n}),this._readDeclarations(!0),this.fire({type:"endfontface",line:t,col:n})},_viewport:function(){var e=this._tokenStream,t,n;e.mustMatch(Tokens.VIEWPORT_SYM),t=e.token().startLine,n=e.token().startCol,this._readWhitespace(),this.fire({type:"startviewport",line:t,col:n}),this._readDeclarations(!0),this.fire({type:"endviewport",line:t,col:n})},_operator:function(e){var t=this._tokenStream,n=null;if(t.match([Tokens.SLASH,Tokens.COMMA])||e&&t.match([Tokens.PLUS,Tokens.STAR,Tokens.MINUS]))n=t.token(),this._readWhitespace();return n?PropertyValuePart.fromToken(n):null},_combinator:function(){var e=this._tokenStream,t=null,n;return e.match([Tokens.PLUS,Tokens.GREATER,Tokens.TILDE])&&(n=e.token(),t=new Combinator(n.value,n.startLine,n.startCol),this._readWhitespace()),t},_unary_operator:function(){var e=this._tokenStream;return e.match([Tokens.MINUS,Tokens.PLUS])?e.token().value:null},_property:function(){var e=this._tokenStream,t=null,n=null,r,i,s,o;return e.peek()==Tokens.STAR&&this.options.starHack&&(e.get(),i=e.token(),n=i.value,s=i.startLine,o=i.startCol),e.match(Tokens.IDENT)&&(i=e.token(),r=i.value,r.charAt(0)=="_"&&this.options.underscoreHack&&(n="_",r=r.substring(1)),t=new PropertyName(r,n,s||i.startLine,o||i.startCol),this._readWhitespace()),t},_ruleset:function(){var e=this._tokenStream,t,n;try{n=this._selectors_group()}catch(r){if(r instanceof SyntaxError&&!this.options.strict){this.fire({type:"error",error:r,message:r.message,line:r.line,col:r.col}),t=e.advance([Tokens.RBRACE]);if(t!=Tokens.RBRACE)throw r;return!0}throw r}return n&&(this.fire({type:"startrule",selectors:n,line:n[0].line,col:n[0].col}),this._readDeclarations(!0),this.fire({type:"endrule",selectors:n,line:n[0].line,col:n[0].col})),n},_selectors_group:function(){var e=this._tokenStream,t=[],n;n=this._selector();if(n!==null){t.push(n);while(e.match(Tokens.COMMA))this._readWhitespace(),n=this._selector(),n!==null?t.push(n):this._unexpectedToken(e.LT(1))}return t.length?t:null},_selector:function(){var e=this._tokenStream,t=[],n=null,r=null,i=null;n=this._simple_selector_sequence();if(n===null)return null;t.push(n);do{r=this._combinator();if(r!==null)t.push(r),n=this._simple_selector_sequence(),n===null?this._unexpectedToken(e.LT(1)):t.push(n);else{if(!this._readWhitespace())break;i=new Combinator(e.token().value,e.token().startLine,e.token().startCol),r=this._combinator(),n=this._simple_selector_sequence(),n===null?r!==null&&this._unexpectedToken(e.LT(1)):(r!==null?t.push(r):t.push(i),t.push(n))}}while(!0);return new Selector(t,t[0].line,t[0].col)},_simple_selector_sequence:function(){var e=this._tokenStream,t=null,n=[],r="",i=[function(){return e.match(Tokens.HASH)?new SelectorSubPart(e.token().value,"id",e.token().startLine,e.token().startCol):null},this._class,this._attrib,this._pseudo,this._negation],s=0,o=i.length,u=null,a=!1,f,l;f=e.LT(1).startLine,l=e.LT(1).startCol,t=this._type_selector(),t||(t=this._universal()),t!==null&&(r+=t);for(;;){if(e.peek()===Tokens.S)break;while(s1&&e.unget()),null)},_class:function(){var e=this._tokenStream,t;return e.match(Tokens.DOT)?(e.mustMatch(Tokens.IDENT),t=e.token(),new SelectorSubPart("."+t.value,"class",t.startLine,t.startCol-1)):null},_element_name:function(){var e=this._tokenStream,t;return e.match(Tokens.IDENT)?(t=e.token(),new SelectorSubPart(t.value,"elementName",t.startLine,t.startCol)):null},_namespace_prefix:function(){var e=this._tokenStream,t="";if(e.LA(1)===Tokens.PIPE||e.LA(2)===Tokens.PIPE)e.match([Tokens.IDENT,Tokens.STAR])&&(t+=e.token().value),e.mustMatch(Tokens.PIPE),t+="|";return t.length?t:null},_universal:function(){var e=this._tokenStream,t="",n;return n=this._namespace_prefix(),n&&(t+=n),e.match(Tokens.STAR)&&(t+="*"),t.length?t:null},_attrib:function(){var e=this._tokenStream,t=null,n,r;return e.match(Tokens.LBRACKET)?(r=e.token(),t=r.value,t+=this._readWhitespace(),n=this._namespace_prefix(),n&&(t+=n),e.mustMatch(Tokens.IDENT),t+=e.token().value,t+=this._readWhitespace(),e.match([Tokens.PREFIXMATCH,Tokens.SUFFIXMATCH,Tokens.SUBSTRINGMATCH,Tokens.EQUALS,Tokens.INCLUDES,Tokens.DASHMATCH])&&(t+=e.token().value,t+=this._readWhitespace(),e.mustMatch([Tokens.IDENT,Tokens.STRING]),t+=e.token().value,t+=this._readWhitespace()),e.mustMatch(Tokens.RBRACKET),new SelectorSubPart(t+"]","attribute",r.startLine,r.startCol)):null},_pseudo:function(){var e=this._tokenStream,t=null,n=":",r,i;return e.match(Tokens.COLON)&&(e.match(Tokens.COLON)&&(n+=":"),e.match(Tokens.IDENT)?(t=e.token().value,r=e.token().startLine,i=e.token().startCol-n.length):e.peek()==Tokens.FUNCTION&&(r=e.LT(1).startLine,i=e.LT(1).startCol-n.length,t=this._functional_pseudo()),t&&(t=new SelectorSubPart(n+t,"pseudo",r,i))),t},_functional_pseudo:function(){var e=this._tokenStream,t=null;return e.match(Tokens.FUNCTION)&&(t=e.token().value,t+=this._readWhitespace(),t+=this._expression(),e.mustMatch(Tokens.RPAREN),t+=")"),t},_expression:function(){var e=this._tokenStream,t="";while(e.match([Tokens.PLUS,Tokens.MINUS,Tokens.DIMENSION,Tokens.NUMBER,Tokens.STRING,Tokens.IDENT,Tokens.LENGTH,Tokens.FREQ,Tokens.ANGLE,Tokens.TIME,Tokens.RESOLUTION,Tokens.SLASH]))t+=e.token().value,t+=this._readWhitespace();return t.length?t:null},_negation:function(){var e=this._tokenStream,t,n,r="",i,s=null;return e.match(Tokens.NOT)&&(r=e.token().value,t=e.token().startLine,n=e.token().startCol,r+=this._readWhitespace(),i=this._negation_arg(),r+=i,r+=this._readWhitespace(),e.match(Tokens.RPAREN),r+=e.token().value,s=new SelectorSubPart(r,"not",t,n),s.args.push(i)),s},_negation_arg:function(){var e=this._tokenStream,t=[this._type_selector,this._universal,function(){return e.match(Tokens.HASH)?new SelectorSubPart(e.token().value,"id",e.token().startLine,e.token().startCol):null},this._class,this._attrib,this._pseudo],n=null,r=0,i=t.length,s,o,u,a;o=e.LT(1).startLine,u=e.LT(1).startCol;while(r0?new PropertyValue(n,n[0].line,n[0].col):null},_term:function(e){var t=this._tokenStream,n=null,r=null,i=null,s,o,u;return n=this._unary_operator(),n!==null&&(o=t.token().startLine,u=t.token().startCol),t.peek()==Tokens.IE_FUNCTION&&this.options.ieFilters?(r=this._ie_function(),n===null&&(o=t.token().startLine,u=t.token().startCol)):e&&t.match([Tokens.LPAREN,Tokens.LBRACE,Tokens.LBRACKET])?(s=t.token(),i=s.endChar,r=s.value+this._expr(e).text,n===null&&(o=t.token().startLine,u=t.token().startCol),t.mustMatch(Tokens.type(i)),r+=i,this._readWhitespace()):t.match([Tokens.NUMBER,Tokens.PERCENTAGE,Tokens.LENGTH,Tokens.ANGLE,Tokens.TIME,Tokens.FREQ,Tokens.STRING,Tokens.IDENT,Tokens.URI,Tokens.UNICODE_RANGE])?(r=t.token().value,n===null&&(o=t.token().startLine,u=t.token().startCol),this._readWhitespace()):(s=this._hexcolor(),s===null?(n===null&&(o=t.LT(1).startLine,u=t.LT(1).startCol),r===null&&(t.LA(3)==Tokens.EQUALS&&this.options.ieFilters?r=this._ie_function():r=this._function())):(r=s.value,n===null&&(o=s.startLine,u=s.startCol))),r!==null?new PropertyValuePart(n!==null?n+r:r,o,u):null},_function:function(){var e=this._tokenStream,t=null,n=null,r;if(e.match(Tokens.FUNCTION)){t=e.token().value,this._readWhitespace(),n=this._expr(!0),t+=n;if(this.options.ieFilters&&e.peek()==Tokens.EQUALS)do{this._readWhitespace()&&(t+=e.token().value),e.LA(0)==Tokens.COMMA&&(t+=e.token().value),e.match(Tokens.IDENT),t+=e.token().value,e.match(Tokens.EQUALS),t+=e.token().value,r=e.peek();while(r!=Tokens.COMMA&&r!=Tokens.S&&r!=Tokens.RPAREN)e.get(),t+=e.token().value,r=e.peek()}while(e.match([Tokens.COMMA,Tokens.S]));e.match(Tokens.RPAREN),t+=")",this._readWhitespace()}return t},_ie_function:function(){var e=this._tokenStream,t=null,n=null,r;if(e.match([Tokens.IE_FUNCTION,Tokens.FUNCTION])){t=e.token().value;do{this._readWhitespace()&&(t+=e.token().value),e.LA(0)==Tokens.COMMA&&(t+=e.token().value),e.match(Tokens.IDENT),t+=e.token().value,e.match(Tokens.EQUALS),t+=e.token().value,r=e.peek();while(r!=Tokens.COMMA&&r!=Tokens.S&&r!=Tokens.RPAREN)e.get(),t+=e.token().value,r=e.peek()}while(e.match([Tokens.COMMA,Tokens.S]));e.match(Tokens.RPAREN),t+=")",this._readWhitespace()}return t},_hexcolor:function(){var e=this._tokenStream,t=null,n;if(e.match(Tokens.HASH)){t=e.token(),n=t.value;if(!/#[a-f0-9]{3,6}/i.test(n))throw new SyntaxError("Expected a hex color but found '"+n+"' at line "+t.startLine+", col "+t.startCol+".",t.startLine,t.startCol);this._readWhitespace()}return t},_keyframes:function(){var e=this._tokenStream,t,n,r,i="";e.mustMatch(Tokens.KEYFRAMES_SYM),t=e.token(),/^@\-([^\-]+)\-/.test(t.value)&&(i=RegExp.$1),this._readWhitespace(),r=this._keyframe_name(),this._readWhitespace(),e.mustMatch(Tokens.LBRACE),this.fire({type:"startkeyframes",name:r,prefix:i,line:t.startLine,col:t.startCol}),this._readWhitespace(),n=e.peek();while(n==Tokens.IDENT||n==Tokens.PERCENTAGE)this._keyframe_rule(),this._readWhitespace(),n=e.peek();this.fire({type:"endkeyframes",name:r,prefix:i,line:t.startLine,col:t.startCol}),this._readWhitespace(),e.mustMatch(Tokens.RBRACE)},_keyframe_name:function(){var e=this._tokenStream,t;return e.mustMatch([Tokens.IDENT,Tokens.STRING]),SyntaxUnit.fromToken(e.token())},_keyframe_rule:function(){var e=this._tokenStream,t,n=this._key_list();this.fire({type:"startkeyframerule",keys:n,line:n[0].line,col:n[0].col}),this._readDeclarations(!0),this.fire({type:"endkeyframerule",keys:n,line:n[0].line,col:n[0].col})},_key_list:function(){var e=this._tokenStream,t,n,r=[];r.push(this._key()),this._readWhitespace();while(e.match(Tokens.COMMA))this._readWhitespace(),r.push(this._key()),this._readWhitespace();return r},_key:function(){var e=this._tokenStream,t;if(e.match(Tokens.PERCENTAGE))return SyntaxUnit.fromToken(e.token());if(e.match(Tokens.IDENT)){t=e.token();if(/from|to/i.test(t.value))return SyntaxUnit.fromToken(t);e.unget()}this._unexpectedToken(e.LT(1))},_skipCruft:function(){while(this._tokenStream.match([Tokens.S,Tokens.CDO,Tokens.CDC]));},_readDeclarations:function(e,t){var n=this._tokenStream,r;this._readWhitespace(),e&&n.mustMatch(Tokens.LBRACE),this._readWhitespace();try{for(;;){if(!(n.match(Tokens.SEMICOLON)||t&&this._margin())){if(!this._declaration())break;if(!n.match(Tokens.SEMICOLON))break}this._readWhitespace()}n.mustMatch(Tokens.RBRACE),this._readWhitespace()}catch(i){if(!(i instanceof SyntaxError&&!this.options.strict))throw i;this.fire({type:"error",error:i,message:i.message,line:i.line,col:i.col}),r=n.advance([Tokens.SEMICOLON,Tokens.RBRACE]);if(r==Tokens.SEMICOLON)this._readDeclarations(!1,t);else if(r!=Tokens.RBRACE)throw i}},_readWhitespace:function(){var e=this._tokenStream,t="";while(e.match(Tokens.S))t+=e.token().value;return t},_unexpectedToken:function(e){throw new SyntaxError("Unexpected token '"+e.value+"' at line "+e.startLine+", col "+e.startCol+".",e.startLine,e.startCol)},_verifyEnd:function(){this._tokenStream.LA(1)!=Tokens.EOF&&this._unexpectedToken(this._tokenStream.LT(1))},_validateProperty:function(e,t){Validation.validate(e,t)},parse:function(e){this._tokenStream=new TokenStream(e,Tokens),this._stylesheet()},parseStyleSheet:function(e){return this.parse(e)},parseMediaQuery:function(e){this._tokenStream=new TokenStream(e,Tokens);var t=this._media_query();return this._verifyEnd(),t},parsePropertyValue:function(e){this._tokenStream=new TokenStream(e,Tokens),this._readWhitespace();var t=this._expr();return this._readWhitespace(),this._verifyEnd(),t},parseRule:function(e){this._tokenStream=new TokenStream(e,Tokens),this._readWhitespace();var t=this._ruleset();return this._readWhitespace(),this._verifyEnd(),t},parseSelector:function(e){this._tokenStream=new TokenStream(e,Tokens),this._readWhitespace();var t=this._selector();return this._readWhitespace(),this._verifyEnd(),t},parseStyleAttribute:function(e){e+="}",this._tokenStream=new TokenStream(e,Tokens),this._readDeclarations()}};for(t in n)n.hasOwnProperty(t)&&(e[t]=n[t]);return e}();var Properties={"align-items":"flex-start | flex-end | center | baseline | stretch","align-content":"flex-start | flex-end | center | space-between | space-around | stretch","align-self":"auto | flex-start | flex-end | center | baseline | stretch","-webkit-align-items":"flex-start | flex-end | center | baseline | stretch","-webkit-align-content":"flex-start | flex-end | center | space-between | space-around | stretch","-webkit-align-self":"auto | flex-start | flex-end | center | baseline | stretch","alignment-adjust":"auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical | | ","alignment-baseline":"baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical",animation:1,"animation-delay":{multi:"