diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..2996d286d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,20 @@ +/.github +/.husky +/packages/datagateway-*/cypress +/packages/datagateway-*/cypress.json +/packages/datagateway-*/server +/packages/datagateway-*/README.md +**/build +**/coverage +**/lib +**/node_modules +.gitignore +.prettierrc +codecov.yml +CODEOWNERS +LICENSE.md +README.md +Dockerfile +**/*.test.* +**/setupTests* +**/testData* diff --git a/.github/add_doi_datapublicationtype.py b/.github/add_doi_datapublicationtype.py new file mode 100644 index 000000000..47dd28a4d --- /dev/null +++ b/.github/add_doi_datapublicationtype.py @@ -0,0 +1,13 @@ +from icat.client import Client + +client = Client( + "https://localhost:8181", + checkCert=False, +) +client.login("simple", {"username": "root", "password": "pw"}) + +data_publication_type = client.new("dataPublicationType") +data_publication_type.name = "User-defined" +data_publication_type.description = "User-defined" +data_publication_type.facility = client.get("Facility", 1) +data_publication_type.create() diff --git a/.github/add_icat_rules.py b/.github/add_icat_rules.py new file mode 100644 index 000000000..f1702563e --- /dev/null +++ b/.github/add_icat_rules.py @@ -0,0 +1,50 @@ +from icat.client import Client + +client = Client( + "https://localhost:8181", + checkCert=False, +) +client.login("simple", {"username": "root", "password": "pw"}) + +public_tables = [ + "Instrument", + "ParameterType", + "InvestigationType", + "DatasetType", + "SampleType", + "DatafileFormat", + "Facility", + "FacilityCycle", +] + +client.createRules("R", public_tables) + +public_steps = [ + ("Datafile", "dataset"), + ("Dataset", "investigation"), + ("Sample", "investigation"), + ("Instrument", "instrumentScientists"), + ("Investigation", "investigationFacilityCycles"), + ("InstrumentScientist", "user"), + ("Investigation", "publications"), + ("Sample", "type"), + ("InvestigationUser", "user"), + ("Investigation", "investigationUsers"), + ("Investigation", "investigationInstruments"), + ("Dataset", "sample"), + ("Dataset", "datafiles"), + ("Investigation", "datasets"), + ("Investigation", "samples"), + ("Sample", "parameters"), + ("Investigation", "parameters"), + ("Dataset", "parameters"), + ("Datafile", "parameters"), +] + +public_step_objects = [] + +for step in public_steps: + ps = client.new("PublicStep", origin=step[0], field=step[1]) + public_step_objects.append(ps) + +client.createMany(public_step_objects) diff --git a/.github/config.env b/.github/config.env new file mode 100644 index 000000000..1e5012ea5 --- /dev/null +++ b/.github/config.env @@ -0,0 +1,18 @@ +ICAT_URL=https://host.docker.internal:8181 +FACILITY=LILS +ICAT_USERNAME=root +ICAT_PASSWORD=pw +PUBLISHER=test +MINTER_ROLE=PI +VERSION=0.01 + +ICAT_DOI_BASE_URL=https://example.stfc.ac.uk/ +ICAT_SESSION_PATH=/icat/session/ +ICAT_AUTHENTICATOR_NAME=simple +ICAT_CHECK_CERT=False +SSL_CERT_VERIFICATION=False + +DATACITE_PREFIX=10.5286 +DATACITE_URL=https://api.test.datacite.org/dois +DATACITE_USERNAME=BL.STFC + diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index be5436cd5..000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,141 +0,0 @@ -version: 2 -updates: -- package-ecosystem: npm - directory: "/" - schedule: - interval: daily - time: "00:00" - timezone: Europe/London - open-pull-requests-limit: 10 - versioning-strategy: increase - ignore: - - dependency-name: "*" - update-types: ["version-update:semver-patch"] - - dependency-name: "@date-io/date-fns" - versions: - - ">= 2.a, < 3" - - dependency-name: eslint-plugin-react - versions: - - "> 7.20.0, < 7.21" - - dependency-name: eslint-plugin-react-hooks - versions: - - "> 4.0.4, < 4.1" - - dependency-name: i18next - versions: - - ">= 19.7.a, < 19.8" - - dependency-name: i18next - versions: - - "> 19.9.0, < 19.10" - - dependency-name: i18next-browser-languagedetector - versions: - - "> 6.0.0, < 6.1" - - dependency-name: i18next-http-backend - versions: - - "> 1.0.15, < 1.1" - - dependency-name: jsrsasign - versions: - - "> 8.0.20, < 8.1" - - dependency-name: jsrsasign - versions: - - "> 9.0.0, < 9.1" - - dependency-name: react-i18next - versions: - - "> 11.7.0, < 11.8" - - dependency-name: react-redux - versions: - - "> 7.2.0, < 7.3" - - dependency-name: single-spa-react - versions: - - "> 3.0.0, < 3.1" - - dependency-name: typescript - versions: - - "> 3.9.6, < 3.10" - - dependency-name: typescript - versions: - - "> 4.2.2, < 4.3" - - dependency-name: "@types/jest" - versions: - - "> 26.0.4, < 26.1" - - dependency-name: "@types/jsrsasign" - versions: - - "> 8.0.3, < 8.1" - - dependency-name: "@types/node" - versions: - - "> 14.0.20, < 14.1" - - dependency-name: "@types/node" - versions: - - "> 14.14.31, < 14.15" - - dependency-name: "@types/react" - versions: - - "> 16.9.41, < 16.10" - - dependency-name: "@types/react-virtualized" - versions: - - "> 9.21.10, < 9.22" - - dependency-name: "@welldone-software/why-did-you-render" - versions: - - "> 4.2.5, < 4.3" - - dependency-name: i18next-http-backend - versions: - - 1.2.1 - - dependency-name: eslint - versions: - - 7.21.0 - - 7.22.0 - - 7.23.0 - - 7.24.0 - - dependency-name: date-fns - versions: - - 2.16.1 - - 2.18.0 - - 2.19.0 - - 2.20.2 - - 2.21.0 - - dependency-name: cypress - versions: - - 6.6.0 - - 6.7.1 - - 6.8.0 - - 7.0.1 - - 7.1.0 - - dependency-name: "@typescript-eslint/parser" - versions: - - 4.17.0 - - 4.18.0 - - 4.19.0 - - 4.20.0 - - 4.21.0 - - dependency-name: jsrsasign - versions: - - 10.1.13 - - dependency-name: "@welldone-software/why-did-you-render" - versions: - - 6.0.5 - - 6.1.0 - - dependency-name: react - versions: - - 17.0.1 - - dependency-name: typescript - versions: - - 4.1.3 - - 4.1.5 - - dependency-name: "@types/node" - versions: - - 14.14.22 - - 14.14.25 - - 14.14.26 - - 14.14.28 - - 14.14.29 - - dependency-name: "@typescript-eslint/eslint-plugin" - versions: - - 4.14.0 - - 4.14.2 - - 4.15.0 - - dependency-name: eslint-config-react-app - versions: - - 6.0.0 - - dependency-name: lint-staged - versions: - - 10.5.3 - - dependency-name: "@material-ui/core" - versions: - - 4.11.2 diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 000000000..dfd7337f8 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,11 @@ +changelog: + categories: + - title: Features + labels: + - '*' + exclude: + labels: + - dependencies + - title: Dependencies + labels: + - dependencies \ No newline at end of file diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 82e27ecad..f2ee6a3fe 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -2,7 +2,7 @@ name: CI Build on: workflow_dispatch: pull_request: - # By default, the pull_request event type is not triggered when a PR is merged into main + # By default, the pull_request event type is not triggered when a PR is merged into main or develop push: branches: - main @@ -14,30 +14,18 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout repo - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Setup Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4 with: - node-version: '14.x' - - # Cache yarn dependencies/ restore the cached dependencies during future workflows - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: Cache yarn dependencies - uses: actions/cache@v2 - id: yarn-cache - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- + node-version: 20 + cache: 'yarn' + - name: Install dependencies # Ubuntu 16+ does not install libgconf-2-4 by default, so we need to install it ourselves (for Cypress) run: | - npm config set scripts-prepend-node-path true sudo apt-get install libgconf-2-4 - yarn --frozen-lockfile + yarn --immutable # Linting and unit testing - name: Run linting @@ -48,55 +36,60 @@ jobs: # Test coverage upload - name: Upload unit test coverage for the Common package if: success() - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # v4 with: directory: ./packages/datagateway-common/ flags: common fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} - name: Upload unit test coverage for the DataView package if: success() - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # v4 with: directory: ./packages/datagateway-dataview/ flags: dataview fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} - name: Upload unit test coverage for the Search package if: success() - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # v4 with: directory: ./packages/datagateway-search/ flags: search fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} - name: Upload unit test coverage for the Download package if: success() - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # v4 with: directory: ./packages/datagateway-download/ flags: download fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} dataview-e2e-tests: name: DataGateway DataView End to End Tests runs-on: ubuntu-20.04 steps: - name: Checkout repo - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Add apt repo run: sudo add-apt-repository universe - name: Setup Java - uses: actions/setup-java@v1 + uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4 with: + distribution: 'zulu' java-version: 8 java-package: jdk - name: Setup Python - uses: actions/setup-python@v2 + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 with: python-version: 3.6 architecture: x64 # ICAT Ansible clone and install dependencies - name: Checkout icat-ansible - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: repository: icatproject-contrib/icat-ansible ref: master @@ -146,72 +139,51 @@ jobs: cd /home/runner/install/icat.server/ && ./setup -vv install - name: Checkout datagateway-api - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: repository: ral-facilities/datagateway-api path: datagateway-api - ref: v1.0.1 + ref: v9.0.2 # DataGateway API file setup + - name: Create search_api_mapping.json + run: cp datagateway-api/datagateway_api/search_api_mapping.json.example datagateway-api/datagateway_api/search_api_mapping.json - name: Create log file - run: touch logs.log - - name: Configure log file location - run: echo "`jq -r --arg REPO_DIR "$GITHUB_WORKSPACE/logs.log" \ - '.log_location=$REPO_DIR' datagateway-api/datagateway_api/config.json.example`" > datagateway-api/datagateway_api/config.json.example - - name: Configure API backend - run: echo "`jq -r --arg BACKEND "python_icat" \ - '.backend=$BACKEND' datagateway-api/datagateway_api/config.json.example`" > datagateway-api/datagateway_api/config.json.example - - name: Set debug mode to true - run: | - sed -i -e "s/\"debug_mode\": false,/\"debug_mode\": true,/" datagateway-api/datagateway_api/config.json.example - - name: Set log level to DEBUG - run: | - sed -i -e "s/\"log_level\": \"WARN\",/\"log_level\": \"DEBUG\",/" datagateway-api/datagateway_api/config.json.example - - name: Create config.json - run: cp datagateway-api/datagateway_api/config.json.example datagateway-api/datagateway_api/config.json + run: touch datagateway-api/datagateway_api/logs.log + + - name: Create config.yaml + run: cp datagateway-api/datagateway_api/config.yaml.example datagateway-api/datagateway_api/config.yaml # DataGateway API dependencies - name: Install Poetry run: pip install poetry - name: Install dependencies - run: cd datagateway-api; poetry install + run: cd datagateway-api/; poetry install - name: Add dummy data to icatdb run: | - cd datagateway-api; poetry run python -m util.icat_db_generator + cd datagateway-api/; poetry run python -m util.icat_db_generator - name: Start API - run: cd datagateway-api; nohup poetry run python -m datagateway_api.src.main > api-output.txt & + run: cd datagateway-api/; nohup poetry run python -m datagateway_api.src.main > api-output.txt & # E2E tests - - name: Checkout repo - uses: actions/checkout@v2 - name: Setup Node.js - uses: actions/setup-node@v1 - with: - node-version: '14.x' - # Cache yarn dependencies/ restore the cached dependencies during future workflows - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: Cache yarn dependencies - uses: actions/cache@v2 - id: yarn-cache + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4 with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- + node-version: 20 + cache: 'yarn' + - name: Install dependencies # Ubuntu 16+ does not install libgconf-2-4 by default, so we need to install it ourselves (for Cypress) run: | - npm config set scripts-prepend-node-path true sudo apt-get install libgconf-2-4 - yarn --frozen-lockfile + yarn --immutable + - name: Run datagateway-dataview e2e tests run: yarn workspace datagateway-dataview run e2e - name: Upload Cypress screenshots if: failure() - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4 with: name: DataView-Screenshots path: packages/datagateway-dataview/cypress/screenshots @@ -221,23 +193,24 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout repo - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Add apt repo run: sudo add-apt-repository universe - name: Setup Java - uses: actions/setup-java@v1 + uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4 with: + distribution: 'zulu' java-version: 8 java-package: jdk - name: Setup Python - uses: actions/setup-python@v2 + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 with: python-version: 3.6 architecture: x64 # ICAT Ansible clone and install dependencies - name: Checkout icat-ansible - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: repository: icatproject-contrib/icat-ansible ref: master @@ -276,9 +249,21 @@ jobs: ansible-playbook icat-ansible/icat_test_hosts.yml -i icat-ansible/hosts --vault-password-file icat-ansible/vault_pass.txt -vv # Fixes on ICAT components needed for e2e tests - - name: Add anon user to rootUserNames + - name: Removing authenticator prefix for simple auth run: | - awk -F" =" '/rootUserNames/{$2="= simple/root anon/anon";print;next}1' /home/runner/install/icat.server/run.properties > /home/runner/install/icat.server/run.properties.tmp + sed -i 's/mechanism = simple/!mechanism = simple/' /home/runner/install/authn.simple/run.properties + - name: Adding Chris481 user + run: | + sed -i '/user\.list/ s/$/ Chris481/' /home/runner/install/authn.simple/run.properties + - name: Adding Chris481 user password + run: | + echo "user.Chris481.password = pw" >> /home/runner/install/authn.simple/run.properties + - name: Reinstall authn.simple + run: | + cd /home/runner/install/authn.simple/ && ./setup -vv install + - name: Add anon, root (simple without prefix) and Chris481 users to rootUserNames + run: | + awk -F" =" '/rootUserNames/{$2="= root Chris481 anon/anon";print;next}1' /home/runner/install/icat.server/run.properties > /home/runner/install/icat.server/run.properties.tmp - name: Apply rootUserNames change run: | mv -f /home/runner/install/icat.server/run.properties.tmp /home/runner/install/icat.server/run.properties @@ -291,6 +276,15 @@ jobs: - name: Reinstall IDS Server run: | cd /home/runner/install/ids.server/ && python2 ./setup -vv install + - name: Add root (simple without prefix) to datagateway-download-api adminUserNames + run: | + awk -F" =" '/adminUserNames/{$2="= root";print;next}1' /home/runner/install/datagateway-download-api/run.properties > /home/runner/install/datagateway-download-api/run.properties.tmp + - name: Apply adminUserNames change + run: | + mv -f /home/runner/install/datagateway-download-api/run.properties.tmp /home/runner/install/datagateway-download-api/run.properties + - name: Reinstall datagateway-download-api + run: | + cd /home/runner/install/datagateway-download-api/ && python2 ./setup -vv install # Disable Globus for Download e2e tests - name: Login to ICAT @@ -303,72 +297,61 @@ jobs: run: rm -f login_output - name: Checkout datagateway-api - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: repository: ral-facilities/datagateway-api path: datagateway-api - ref: v1.0.1 + ref: v9.0.2 # DataGateway API file setup + - name: Create search_api_mapping.json + run: cp datagateway-api/datagateway_api/search_api_mapping.json.example datagateway-api/datagateway_api/search_api_mapping.json - name: Create log file - run: touch logs.log - - name: Configure log file location - run: echo "`jq -r --arg REPO_DIR "$GITHUB_WORKSPACE/logs.log" \ - '.log_location=$REPO_DIR' datagateway-api/datagateway_api/config.json.example`" > datagateway-api/datagateway_api/config.json.example - - name: Configure API backend - run: echo "`jq -r --arg BACKEND "python_icat" \ - '.backend=$BACKEND' datagateway-api/datagateway_api/config.json.example`" > datagateway-api/datagateway_api/config.json.example - - name: Set debug mode to true - run: | - sed -i -e "s/\"debug_mode\": false,/\"debug_mode\": true,/" datagateway-api/datagateway_api/config.json.example - - name: Set log level to DEBUG - run: | - sed -i -e "s/\"log_level\": \"WARN\",/\"log_level\": \"DEBUG\",/" datagateway-api/datagateway_api/config.json.example - - name: Create config.json - run: cp datagateway-api/datagateway_api/config.json.example datagateway-api/datagateway_api/config.json + run: touch datagateway-api/datagateway_api/logs.log + + - name: Create config.yaml + run: cp datagateway-api/datagateway_api/config.yaml.example datagateway-api/datagateway_api/config.yaml # DataGateway API dependencies - name: Install Poetry run: pip install poetry - name: Install dependencies - run: cd datagateway-api; poetry install + run: cd datagateway-api/; poetry install - name: Add dummy data to icatdb run: | - cd datagateway-api; poetry run python -m util.icat_db_generator + cd datagateway-api/; poetry run python -m util.icat_db_generator - name: Start API - run: cd datagateway-api; nohup poetry run python -m datagateway_api.src.main > api-output.txt & + run: cd datagateway-api/; nohup poetry run python -m datagateway_api.src.main > api-output.txt & + + # DOI minter setup + - name: Adding 'User-defined' DataPublicationType (needed for DOI minting api) + run: cd datagateway-api/; poetry run python ../.github/add_doi_datapublicationtype.py + + - name: 'Add password to env file' + run: echo DATACITE_PASSWORD=${{ secrets.DATACITE_PASSWORD }} >> ./.github/config.env + + - name: Run minting api + run: docker run --env-file ./.github/config.env -p 8000:8000 --add-host host.docker.internal:host-gateway -d harbor.stfc.ac.uk/icat/doi-mint-api # E2E tests - - name: Checkout repo - uses: actions/checkout@v2 - name: Setup Node.js - uses: actions/setup-node@v1 - with: - node-version: '14.x' - # Cache yarn dependencies/ restore the cached dependencies during future workflows - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: Cache yarn dependencies - uses: actions/cache@v2 - id: yarn-cache + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4 with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- + node-version: 20 + cache: 'yarn' + - name: Install dependencies # Ubuntu 16+ does not install libgconf-2-4 by default, so we need to install it ourselves (for Cypress) run: | - npm config set scripts-prepend-node-path true sudo apt-get install libgconf-2-4 - yarn --frozen-lockfile + yarn --immutable + - name: Run datagateway-download e2e tests run: yarn workspace datagateway-download run e2e - name: Upload Cypress screenshots if: failure() - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4 with: name: Download-Screenshots path: packages/datagateway-download/cypress/screenshots @@ -378,23 +361,24 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout repo - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Add apt repo run: sudo add-apt-repository universe - name: Setup Java - uses: actions/setup-java@v1 + uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4 with: + distribution: 'zulu' java-version: 8 java-package: jdk - name: Setup Python - uses: actions/setup-python@v2 + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 with: python-version: 3.6 architecture: x64 # ICAT Ansible clone and install dependencies - name: Checkout icat-ansible - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: repository: icatproject-contrib/icat-ansible ref: master @@ -412,6 +396,12 @@ jobs: - name: Replace default payara user with Actions user run: | sed -i -e "s/^payara_user: \"glassfish\"/payara_user: \"runner\"/" icat-ansible/group_vars/all/vars.yml + - name: Change icat.server version + run: | + echo "icat_server_version: '6.1.0-SNAPSHOT'" >> icat-ansible/group_vars/all/vars.yml + - name: Change icat.lucene version + run: | + echo "icat_lucene_version: '3.0.0-SNAPSHOT'" >> icat-ansible/group_vars/all/vars.yml - name: Amending roles run: | sed -i 's/role: authn_uows_isis/role: authn_anon/' icat-ansible/icat_test_hosts.yml @@ -442,90 +432,90 @@ jobs: cd /home/runner/install/icat.server/ && ./setup -vv install - name: Checkout datagateway-api - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: repository: ral-facilities/datagateway-api path: datagateway-api - ref: v1.0.1 + ref: v9.0.2 # DataGateway API file setup + - name: Create search_api_mapping.json + run: cp datagateway-api/datagateway_api/search_api_mapping.json.example datagateway-api/datagateway_api/search_api_mapping.json - name: Create log file - run: touch logs.log - - name: Configure log file location - run: echo "`jq -r --arg REPO_DIR "$GITHUB_WORKSPACE/logs.log" \ - '.log_location=$REPO_DIR' datagateway-api/datagateway_api/config.json.example`" > datagateway-api/datagateway_api/config.json.example - - name: Configure API backend - run: echo "`jq -r --arg BACKEND "python_icat" \ - '.backend=$BACKEND' datagateway-api/datagateway_api/config.json.example`" > datagateway-api/datagateway_api/config.json.example - - name: Set debug mode to true - run: | - sed -i -e "s/\"debug_mode\": false,/\"debug_mode\": true,/" datagateway-api/datagateway_api/config.json.example - - name: Set log level to DEBUG - run: | - sed -i -e "s/\"log_level\": \"WARN\",/\"log_level\": \"DEBUG\",/" datagateway-api/datagateway_api/config.json.example - - name: Create config.json - run: cp datagateway-api/datagateway_api/config.json.example datagateway-api/datagateway_api/config.json + run: touch datagateway-api/datagateway_api/logs.log + + - name: Create config.yaml + run: cp datagateway-api/datagateway_api/config.yaml.example datagateway-api/datagateway_api/config.yaml # DataGateway API dependencies - name: Install Poetry run: pip install poetry - name: Install dependencies - run: cd datagateway-api; poetry install + run: cd datagateway-api/; poetry install - name: Add dummy data to icatdb run: | - cd datagateway-api; poetry run python -m util.icat_db_generator + cd datagateway-api/; poetry run python -m util.icat_db_generator + - name: Add ICAT rules & public steps + run: cd datagateway-api/; poetry run python ../.github/add_icat_rules.py # Recreate Lucene indexes - - name: Login to ICAT - run: | - curl -k --request POST 'https://localhost:8181/icat/session' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'json={"plugin":"simple", "credentials": [{"username":"root"}, {"password":"pw"}]}' > login_output - - name: Recreate Datafile index - run: | - curl -k --request POST 'https://localhost:8181/icat/lucene/db/Datafile/0' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'sessionId='`jq -r '.sessionId' login_output` - - name: Recreate Dataset index - run: | - curl -k --request POST 'https://localhost:8181/icat/lucene/db/Dataset/1' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'sessionId='`jq -r '.sessionId' login_output` - - name: Recreate Investigation index - run: | - curl -k --request POST 'https://localhost:8181/icat/lucene/db/Investigation/1' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'sessionId='`jq -r '.sessionId' login_output` + - name: Use icatadmin to reindex all indexes + run: ~/bin/icatadmin https://localhost:8181 simple username root password pw -- populate --delete - name: Let reindexes complete run: sleep 30 - - name: Remove session ID data - run: rm -f login_output - name: Start API - run: cd datagateway-api; nohup poetry run python -m datagateway_api.src.main > api-output.txt & + run: cd datagateway-api/; nohup poetry run python -m datagateway_api.src.main > api-output.txt & # E2E tests - - name: Checkout repo - uses: actions/checkout@v2 - name: Setup Node.js - uses: actions/setup-node@v1 - with: - node-version: '14.x' - # Cache yarn dependencies/ restore the cached dependencies during future workflows - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: Cache yarn dependencies - uses: actions/cache@v2 - id: yarn-cache + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4 with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- + node-version: 20 + cache: 'yarn' + - name: Install dependencies # Ubuntu 16+ does not install libgconf-2-4 by default, so we need to install it ourselves (for Cypress) run: | - npm config set scripts-prepend-node-path true sudo apt-get install libgconf-2-4 - yarn --frozen-lockfile + yarn --immutable + - name: Run datagateway-search e2e tests run: yarn workspace datagateway-search run e2e - name: Upload Cypress screenshots if: failure() - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4 with: name: Search-Screenshots path: packages/datagateway-search/cypress/screenshots + + docker: + # This job triggers only if all the other jobs succeed. It builds the Docker image and if successful, + # it pushes it to Harbor. + needs: [lint-and-unit-test, dataview-e2e-tests, download-e2e-tests, search-e2e-tests] + name: Docker + runs-on: ubuntu-20.04 + steps: + - name: Checkout repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + + - name: Login to Harbor + uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0 + with: + registry: ${{ secrets.HARBOR_URL }} + username: ${{ secrets.HARBOR_USERNAME }} + password: ${{ secrets.HARBOR_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@818d4b7b91585d195f67373fd9cb0332e31a7175 # v4.6.0 + with: + images: ${{ secrets.HARBOR_URL }}/plugins + + - name: Build and push Docker image to Harbor + uses: docker/build-push-action@0a97817b6ade9f46837855d676c4cca3a2471fc9 # v4.2.1 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index f14bd8877..19ec46b3c 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -4,7 +4,8 @@ on: branches: - main - develop - tags: '*' + tags: + - '*' jobs: build: @@ -13,33 +14,19 @@ jobs: steps: - name: Checkout repo - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Setup Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4 with: - node-version: '14.x' - - # Cache yarn dependencies/ restore the cached dependencies during future workflows - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - - name: Cache yarn dependencies - uses: actions/cache@v2 - id: yarn-cache - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- + node-version: 20 + cache: 'yarn' - name: Install dependencies # Ubuntu 16+ does not install libgconf-2-4 by default, so we need to install it ourselves (for Cypress) run: | - npm config set scripts-prepend-node-path true sudo apt-get install libgconf-2-4 - yarn --frozen-lockfile + yarn --immutable - name: Determine tag name run: | @@ -78,7 +65,7 @@ jobs: tar -czf ../../datagateway-search-$TAG_NAME.tar.gz datagateway-search-$TAG_NAME - name: Update snapshot tag - uses: richardsimko/update-tag@v1 + uses: richardsimko/update-tag@e173a8ef8f54ab526a91dad6139a25efed62424c # v1 with: tag_name: ${{ env.TAG_NAME }} env: @@ -86,11 +73,15 @@ jobs: if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop' }} - name: Create/update release - uses: johnwbyrd/update-release@v1.0.0 + uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 # v2.0.8 with: token: ${{ secrets.GITHUB_TOKEN }} - files: ./datagateway-dataview-${{ env.TAG_NAME }}.tar.gz ./datagateway-download-${{ env.TAG_NAME }}.tar.gz ./datagateway-search-${{ env.TAG_NAME }}.tar.gz - release: Release ${{ env.TAG_NAME }} - tag: ${{ env.TAG_NAME }} + files: | + ./datagateway-dataview-${{ env.TAG_NAME }}.tar.gz + ./datagateway-download-${{ env.TAG_NAME }}.tar.gz + ./datagateway-search-${{ env.TAG_NAME }}.tar.gz + name: ${{ env.TAG_NAME }} + tag_name: ${{ env.TAG_NAME }} prerelease: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop' }} draft: false + generate_release_notes: true diff --git a/.gitignore b/.gitignore index 678ed6de8..75007c98b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,15 @@ node_modules/ /.pnp .pnp.js +# yarn 2 +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions + # testing coverage/ screenshots/ @@ -29,3 +38,4 @@ yarn-error.log* **/public/*settings*.json !**/public/*settings.example.json +.vscode/ diff --git a/.husky/pre-commit b/.husky/pre-commit index a94c6b198..2d833c641 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -2,4 +2,4 @@ . "$(dirname "$0")/_/husky.sh" . "$(dirname "$0")/common.sh" -yarn lerna run --concurrency 1 --stream pre-commit \ No newline at end of file +yarn workspaces foreach --interlaced --verbose --jobs 1 run pre-commit \ No newline at end of file diff --git a/.yarn/plugins/@yarnpkg/plugin-version.cjs b/.yarn/plugins/@yarnpkg/plugin-version.cjs new file mode 100644 index 000000000..16113269f --- /dev/null +++ b/.yarn/plugins/@yarnpkg/plugin-version.cjs @@ -0,0 +1,523 @@ +/* eslint-disable */ +//prettier-ignore +module.exports = { +name: "@yarnpkg/plugin-version", +factory: function (require) { +var plugin=(()=>{var fU=Object.create;var ky=Object.defineProperty;var cU=Object.getOwnPropertyDescriptor;var dU=Object.getOwnPropertyNames;var pU=Object.getPrototypeOf,hU=Object.prototype.hasOwnProperty;var Kn=(u=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(u,{get:(l,c)=>(typeof require<"u"?require:l)[c]}):u)(function(u){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+u+'" is not supported')});var re=(u,l)=>()=>(l||u((l={exports:{}}).exports,l),l.exports),gS=(u,l)=>{for(var c in l)ky(u,c,{get:l[c],enumerable:!0})},_S=(u,l,c,p)=>{if(l&&typeof l=="object"||typeof l=="function")for(let _ of dU(l))!hU.call(u,_)&&_!==c&&ky(u,_,{get:()=>l[_],enumerable:!(p=cU(l,_))||p.enumerable});return u};var pu=(u,l,c)=>(c=u!=null?fU(pU(u)):{},_S(l||!u||!u.__esModule?ky(c,"default",{value:u,enumerable:!0}):c,u)),vU=u=>_S(ky({},"__esModule",{value:!0}),u);var iD=re((fee,ES)=>{function mU(u,l){for(var c=-1,p=u==null?0:u.length,_=Array(p);++c
{function yU(){this.__data__=[],this.size=0}DS.exports=yU});var oD=re((dee,SS)=>{function gU(u,l){return u===l||u!==u&&l!==l}SS.exports=gU});var ah=re((pee,TS)=>{var _U=oD();function EU(u,l){for(var c=u.length;c--;)if(_U(u[c][0],l))return c;return-1}TS.exports=EU});var xS=re((hee,CS)=>{var DU=ah(),wU=Array.prototype,SU=wU.splice;function TU(u){var l=this.__data__,c=DU(l,u);if(c<0)return!1;var p=l.length-1;return c==p?l.pop():SU.call(l,c,1),--this.size,!0}CS.exports=TU});var AS=re((vee,RS)=>{var CU=ah();function xU(u){var l=this.__data__,c=CU(l,u);return c<0?void 0:l[c][1]}RS.exports=xU});var OS=re((mee,kS)=>{var RU=ah();function AU(u){return RU(this.__data__,u)>-1}kS.exports=AU});var NS=re((yee,MS)=>{var kU=ah();function OU(u,l){var c=this.__data__,p=kU(c,u);return p<0?(++this.size,c.push([u,l])):c[p][1]=l,this}MS.exports=OU});var sh=re((gee,LS)=>{var MU=wS(),NU=xS(),FU=AS(),LU=OS(),bU=NS();function k2(u){var l=-1,c=u==null?0:u.length;for(this.clear();++l {var bz=sc(),Pz=function(){try{var u=bz(Object,"defineProperty");return u({},"",{}),u}catch{}}();QT.exports=Pz});var dD=re((rte,ZT)=>{var JT=cD();function Iz(u,l,c){l=="__proto__"&&JT?JT(u,l,{configurable:!0,enumerable:!0,value:c,writable:!0}):u[l]=c}ZT.exports=Iz});var pD=re((ite,$T)=>{var Bz=dD(),Uz=oD(),jz=Object.prototype,zz=jz.hasOwnProperty;function qz(u,l,c){var p=u[l];(!(zz.call(u,l)&&Uz(p,c))||c===void 0&&!(l in u))&&Bz(u,l,c)}$T.exports=qz});var L2=re((ote,eC)=>{var Hz=pD(),Wz=dD();function Vz(u,l,c,p){var _=!c;c||(c={});for(var t=-1,O=l.length;++t {function qH(u,l){for(var c=-1,p=u==null?0:u.length,_=0,t=[];++c {function HH(){return[]}$C.exports=HH});var Py=re((Nte,t6)=>{var WH=ZC(),VH=DD(),GH=Object.prototype,YH=GH.propertyIsEnumerable,e6=Object.getOwnPropertySymbols,KH=e6?function(u){return u==null?[]:(u=Object(u),WH(e6(u),function(l){return YH.call(u,l)}))}:VH;t6.exports=KH});var r6=re((Fte,n6)=>{var XH=L2(),QH=Py();function JH(u,l){return XH(u,QH(u),l)}n6.exports=JH});var Iy=re((Lte,i6)=>{function ZH(u,l){for(var c=-1,p=l.length,_=u.length;++c {var $H=_D(),eW=$H(Object.getPrototypeOf,Object);o6.exports=eW});var wD=re((Pte,u6)=>{var tW=Iy(),nW=By(),rW=Py(),iW=DD(),oW=Object.getOwnPropertySymbols,uW=oW?function(u){for(var l=[];u;)tW(l,rW(u)),u=nW(u);return l}:iW;u6.exports=uW});var a6=re((Ite,l6)=>{var lW=L2(),aW=wD();function sW(u,l){return lW(u,aW(u),l)}l6.exports=sW});var SD=re((Bte,s6)=>{var fW=Iy(),cW=cc();function dW(u,l,c){var p=l(u);return cW(u)?p:fW(p,c(u))}s6.exports=dW});var c6=re((Ute,f6)=>{var pW=SD(),hW=Py(),vW=Ly();function mW(u){return pW(u,vW,hW)}f6.exports=mW});var TD=re((jte,d6)=>{var yW=SD(),gW=wD(),_W=by();function EW(u){return yW(u,_W,gW)}d6.exports=EW});var h6=re((zte,p6)=>{var DW=sc(),wW=ra(),SW=DW(wW,"DataView");p6.exports=SW});var m6=re((qte,v6)=>{var TW=sc(),CW=ra(),xW=TW(CW,"Promise");v6.exports=xW});var g6=re((Hte,y6)=>{var RW=sc(),AW=ra(),kW=RW(AW,"Set");y6.exports=kW});var E6=re((Wte,_6)=>{var OW=sc(),MW=ra(),NW=OW(MW,"WeakMap");_6.exports=NW});var Uy=re((Vte,R6)=>{var CD=h6(),xD=Oy(),RD=m6(),AD=g6(),kD=E6(),x6=t1(),B2=sD(),D6="[object Map]",FW="[object Object]",w6="[object Promise]",S6="[object Set]",T6="[object WeakMap]",C6="[object DataView]",LW=B2(CD),bW=B2(xD),PW=B2(RD),IW=B2(AD),BW=B2(kD),n1=x6;(CD&&n1(new CD(new ArrayBuffer(1)))!=C6||xD&&n1(new xD)!=D6||RD&&n1(RD.resolve())!=w6||AD&&n1(new AD)!=S6||kD&&n1(new kD)!=T6)&&(n1=function(u){var l=x6(u),c=l==FW?u.constructor:void 0,p=c?B2(c):"";if(p)switch(p){case LW:return C6;case bW:return D6;case PW:return w6;case IW:return S6;case BW:return T6}return l});R6.exports=n1});var k6=re((Gte,A6)=>{var UW=Object.prototype,jW=UW.hasOwnProperty;function zW(u){var l=u.length,c=new u.constructor(l);return l&&typeof u[0]=="string"&&jW.call(u,"index")&&(c.index=u.index,c.input=u.input),c}A6.exports=zW});var M6=re((Yte,O6)=>{var qW=ra(),HW=qW.Uint8Array;O6.exports=HW});var jy=re((Kte,F6)=>{var N6=M6();function WW(u){var l=new u.constructor(u.byteLength);return new N6(l).set(new N6(u)),l}F6.exports=WW});var b6=re((Xte,L6)=>{var VW=jy();function GW(u,l){var c=l?VW(u.buffer):u.buffer;return new u.constructor(c,u.byteOffset,u.byteLength)}L6.exports=GW});var I6=re((Qte,P6)=>{var YW=/\w*$/;function KW(u){var l=new u.constructor(u.source,YW.exec(u));return l.lastIndex=u.lastIndex,l}P6.exports=KW});var q6=re((Jte,z6)=>{var B6=O2(),U6=B6?B6.prototype:void 0,j6=U6?U6.valueOf:void 0;function XW(u){return j6?Object(j6.call(u)):{}}z6.exports=XW});var W6=re((Zte,H6)=>{var QW=jy();function JW(u,l){var c=l?QW(u.buffer):u.buffer;return new u.constructor(c,u.byteOffset,u.length)}H6.exports=JW});var G6=re(($te,V6)=>{var ZW=jy(),$W=b6(),eV=I6(),tV=q6(),nV=W6(),rV="[object Boolean]",iV="[object Date]",oV="[object Map]",uV="[object Number]",lV="[object RegExp]",aV="[object Set]",sV="[object String]",fV="[object Symbol]",cV="[object ArrayBuffer]",dV="[object DataView]",pV="[object Float32Array]",hV="[object Float64Array]",vV="[object Int8Array]",mV="[object Int16Array]",yV="[object Int32Array]",gV="[object Uint8Array]",_V="[object Uint8ClampedArray]",EV="[object Uint16Array]",DV="[object Uint32Array]";function wV(u,l,c){var p=u.constructor;switch(l){case cV:return ZW(u);case rV:case iV:return new p(+u);case dV:return $W(u,c);case pV:case hV:case vV:case mV:case yV:case gV:case _V:case EV:case DV:return nV(u,c);case oV:return new p;case uV:case sV:return new p(u);case lV:return eV(u);case aV:return new p;case fV:return tV(u)}}V6.exports=wV});var X6=re((ene,K6)=>{var SV=vf(),Y6=Object.create,TV=function(){function u(){}return function(l){if(!SV(l))return{};if(Y6)return Y6(l);u.prototype=l;var c=new u;return u.prototype=void 0,c}}();K6.exports=TV});var J6=re((tne,Q6)=>{var CV=X6(),xV=By(),RV=Fy();function AV(u){return typeof u.constructor=="function"&&!RV(u)?CV(xV(u)):{}}Q6.exports=AV});var $6=re((nne,Z6)=>{var kV=Uy(),OV=fc(),MV="[object Map]";function NV(u){return OV(u)&&kV(u)==MV}Z6.exports=NV});var rx=re((rne,nx)=>{var FV=$6(),LV=My(),ex=Ny(),tx=ex&&ex.isMap,bV=tx?LV(tx):FV;nx.exports=bV});var ox=re((ine,ix)=>{var PV=Uy(),IV=fc(),BV="[object Set]";function UV(u){return IV(u)&&PV(u)==BV}ix.exports=UV});var sx=re((one,ax)=>{var jV=ox(),zV=My(),ux=Ny(),lx=ux&&ux.isSet,qV=lx?zV(lx):jV;ax.exports=qV});var hx=re((une,px)=>{var HV=YT(),WV=XT(),VV=pD(),GV=PC(),YV=HC(),KV=KC(),XV=QC(),QV=r6(),JV=a6(),ZV=c6(),$V=TD(),eG=Uy(),tG=k6(),nG=G6(),rG=J6(),iG=cc(),oG=vD(),uG=rx(),lG=vf(),aG=sx(),sG=Ly(),fG=by(),cG=1,dG=2,pG=4,fx="[object Arguments]",hG="[object Array]",vG="[object Boolean]",mG="[object Date]",yG="[object Error]",cx="[object Function]",gG="[object GeneratorFunction]",_G="[object Map]",EG="[object Number]",dx="[object Object]",DG="[object RegExp]",wG="[object Set]",SG="[object String]",TG="[object Symbol]",CG="[object WeakMap]",xG="[object ArrayBuffer]",RG="[object DataView]",AG="[object Float32Array]",kG="[object Float64Array]",OG="[object Int8Array]",MG="[object Int16Array]",NG="[object Int32Array]",FG="[object Uint8Array]",LG="[object Uint8ClampedArray]",bG="[object Uint16Array]",PG="[object Uint32Array]",Fi={};Fi[fx]=Fi[hG]=Fi[xG]=Fi[RG]=Fi[vG]=Fi[mG]=Fi[AG]=Fi[kG]=Fi[OG]=Fi[MG]=Fi[NG]=Fi[_G]=Fi[EG]=Fi[dx]=Fi[DG]=Fi[wG]=Fi[SG]=Fi[TG]=Fi[FG]=Fi[LG]=Fi[bG]=Fi[PG]=!0;Fi[yG]=Fi[cx]=Fi[CG]=!1;function zy(u,l,c,p,_,t){var O,M=l&cG,A=l&dG,T=l&pG;if(c&&(O=_?c(u,p,_,t):c(u)),O!==void 0)return O;if(!lG(u))return u;var P=iG(u);if(P){if(O=tG(u),!M)return XV(u,O)}else{var U=eG(u),z=U==cx||U==gG;if(oG(u))return KV(u,M);if(U==dx||U==fx||z&&!_){if(O=A||z?{}:rG(u),!M)return A?JV(u,YV(O,u)):QV(u,GV(O,u))}else{if(!Fi[U])return _?u:{};O=nG(u,U,M)}}t||(t=new HV);var Q=t.get(u);if(Q)return Q;t.set(u,O),aG(u)?u.forEach(function(ye){O.add(zy(ye,l,c,ye,u,t))}):uG(u)&&u.forEach(function(ye,le){O.set(le,zy(ye,l,c,le,u,t))});var v=T?A?$V:ZV:A?fG:sG,de=P?void 0:v(u);return WV(de||u,function(ye,le){de&&(le=ye,ye=u[le]),VV(O,le,zy(ye,l,c,le,u,t))}),O}px.exports=zy});var yh=re((lne,vx)=>{var IG=t1(),BG=fc(),UG="[object Symbol]";function jG(u){return typeof u=="symbol"||BG(u)&&IG(u)==UG}vx.exports=jG});var yx=re((ane,mx)=>{var zG=cc(),qG=yh(),HG=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,WG=/^\w*$/;function VG(u,l){if(zG(u))return!1;var c=typeof u;return c=="number"||c=="symbol"||c=="boolean"||u==null||qG(u)?!0:WG.test(u)||!HG.test(u)||l!=null&&u in Object(l)}mx.exports=VG});var Ex=re((sne,_x)=>{var gx=fD(),GG="Expected a function";function OD(u,l){if(typeof u!="function"||l!=null&&typeof l!="function")throw new TypeError(GG);var c=function(){var p=arguments,_=l?l.apply(this,p):p[0],t=c.cache;if(t.has(_))return t.get(_);var O=u.apply(this,p);return c.cache=t.set(_,O)||t,O};return c.cache=new(OD.Cache||gx),c}OD.Cache=gx;_x.exports=OD});var wx=re((fne,Dx)=>{var YG=Ex(),KG=500;function XG(u){var l=YG(u,function(p){return c.size===KG&&c.clear(),p}),c=l.cache;return l}Dx.exports=XG});var Tx=re((cne,Sx)=>{var QG=wx(),JG=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,ZG=/\\(\\)?/g,$G=QG(function(u){var l=[];return u.charCodeAt(0)===46&&l.push(""),u.replace(JG,function(c,p,_,t){l.push(_?t.replace(ZG,"$1"):p||c)}),l});Sx.exports=$G});var Ox=re((dne,kx)=>{var Cx=O2(),eY=iD(),tY=cc(),nY=yh(),rY=1/0,xx=Cx?Cx.prototype:void 0,Rx=xx?xx.toString:void 0;function Ax(u){if(typeof u=="string")return u;if(tY(u))return eY(u,Ax)+"";if(nY(u))return Rx?Rx.call(u):"";var l=u+"";return l=="0"&&1/u==-rY?"-0":l}kx.exports=Ax});var Nx=re((pne,Mx)=>{var iY=Ox();function oY(u){return u==null?"":iY(u)}Mx.exports=oY});var qy=re((hne,Fx)=>{var uY=cc(),lY=yx(),aY=Tx(),sY=Nx();function fY(u,l){return uY(u)?u:lY(u,l)?[u]:aY(sY(u))}Fx.exports=fY});var bx=re((vne,Lx)=>{function cY(u){var l=u==null?0:u.length;return l?u[l-1]:void 0}Lx.exports=cY});var MD=re((mne,Px)=>{var dY=yh(),pY=1/0;function hY(u){if(typeof u=="string"||dY(u))return u;var l=u+"";return l=="0"&&1/u==-pY?"-0":l}Px.exports=hY});var Bx=re((yne,Ix)=>{var vY=qy(),mY=MD();function yY(u,l){l=vY(l,u);for(var c=0,p=l.length;u!=null&&c {function gY(u,l,c){var p=-1,_=u.length;l<0&&(l=-l>_?0:_+l),c=c>_?_:c,c<0&&(c+=_),_=l>c?0:c-l>>>0,l>>>=0;for(var t=Array(_);++p<_;)t[p]=u[p+l];return t}Ux.exports=gY});var qx=re((_ne,zx)=>{var _Y=Bx(),EY=jx();function DY(u,l){return l.length<2?u:_Y(u,EY(l,0,-1))}zx.exports=DY});var Wx=re((Ene,Hx)=>{var wY=qy(),SY=bx(),TY=qx(),CY=MD();function xY(u,l){return l=wY(l,u),u=TY(u,l),u==null||delete u[CY(SY(l))]}Hx.exports=xY});var Yx=re((Dne,Gx)=>{var RY=t1(),AY=By(),kY=fc(),OY="[object Object]",MY=Function.prototype,NY=Object.prototype,Vx=MY.toString,FY=NY.hasOwnProperty,LY=Vx.call(Object);function bY(u){if(!kY(u)||RY(u)!=OY)return!1;var l=AY(u);if(l===null)return!0;var c=FY.call(l,"constructor")&&l.constructor;return typeof c=="function"&&c instanceof c&&Vx.call(c)==LY}Gx.exports=bY});var Xx=re((wne,Kx)=>{var PY=Yx();function IY(u){return PY(u)?void 0:u}Kx.exports=IY});var $x=re((Sne,Zx)=>{var Qx=O2(),BY=hD(),UY=cc(),Jx=Qx?Qx.isConcatSpreadable:void 0;function jY(u){return UY(u)||BY(u)||!!(Jx&&u&&u[Jx])}Zx.exports=jY});var n5=re((Tne,t5)=>{var zY=Iy(),qY=$x();function e5(u,l,c,p,_){var t=-1,O=u.length;for(c||(c=qY),_||(_=[]);++t