diff --git a/.github/actions/run-ee-server-for-ext-container/action.yml b/.github/actions/run-ee-server-for-ext-container/action.yml new file mode 100644 index 00000000..3d9c5c76 --- /dev/null +++ b/.github/actions/run-ee-server-for-ext-container/action.yml @@ -0,0 +1,40 @@ +name: 'Run EE server for another Docker container' +description: 'Run EE server and configure tests to connect to it from another Docker container' +inputs: + # All inputs in composite actions are strings + use-server-rc: + required: true + default: false + server-tag: + required: true + default: 'latest' + # Github Composite Actions can't access secrets + # so we need to pass them in as inputs + docker-hub-username: + required: false + docker-hub-password: + required: false + +runs: + using: "composite" + steps: + - name: Run EE server + uses: ./.github/actions/run-ee-server + with: + use-server-rc: ${{ inputs.use-server-rc }} + server-tag: ${{ inputs.server-tag }} + docker-hub-username: ${{ inputs.docker-hub-username }} + docker-hub-password: ${{ inputs.docker-hub-password }} + + - name: Get IP address of Docker container hosting server + id: get-server-ip-address + run: echo server-ip=$(docker container inspect -f '{{ .NetworkSettings.IPAddress }}' aerospike) >> $GITHUB_OUTPUT + shell: bash + + - name: Configure tests to connect to that Docker container + run: | + pipx install crudini --pip-args "-c ${{ github.workspace }}/.github/workflows/requirements.txt"; + crudini --existing=param --set config.conf enterprise-edition hosts ${{ steps.get-server-ip-address.outputs.server-ip }}:3000; + cat config.conf + working-directory: .github/workflows + shell: bash diff --git a/.github/actions/run-ee-server/action.yml b/.github/actions/run-ee-server/action.yml index f7d4379f..d6fdf3c7 100644 --- a/.github/actions/run-ee-server/action.yml +++ b/.github/actions/run-ee-server/action.yml @@ -1,35 +1,56 @@ name: 'Run EE Server' -description: 'Run EE server' +description: 'Run EE server. Returns once server is ready. Only tested on Linux and macOS' +# NOTE: do not share this server container with others +# since it's using the default admin / admin credentials inputs: # All inputs in composite actions are strings use-server-rc: required: true - default: false + description: Deploy server release candidate? + default: 'false' server-tag: required: true + description: Specify Docker tag + default: 'latest' # Github Composite Actions can't access secrets # so we need to pass them in as inputs docker-hub-username: + description: Required for using release candidates required: false docker-hub-password: + description: Required for using release candidates required: false runs: using: "composite" steps: - - name: Create config folder to store configs in - run: mkdir configs + - name: Install crudini to manipulate config.conf + # This will only work on the Github hosted runners. + run: pipx install crudini --pip-args "-c ${{ github.workspace }}/.github/workflows/requirements.txt" + working-directory: .github/workflows shell: bash - - name: Use release server - if: ${{ inputs.use-server-rc == 'false' }} - run: echo "SERVER_IMAGE=aerospike/aerospike-server-enterprise" >> $GITHUB_ENV + - name: Create config.conf + run: cp config.conf.template config.conf + working-directory: .github/workflows shell: bash - - name: Use release candidate server - if: ${{ inputs.use-server-rc == 'true' }} - run: echo "SERVER_IMAGE=aerospike/aerospike-server-enterprise-rc" >> $GITHUB_ENV + - name: Use enterprise edition instead of community edition in config.conf + run: | + crudini --existing=param --set config.conf enterprise-edition hosts '' + crudini --existing=param --set config.conf enterprise-edition hosts 127.0.0.1:3000 + working-directory: .github/workflows + shell: bash + + - run: echo SUPERUSER_NAME_AND_PASSWORD="superuser" >> $GITHUB_ENV + shell: bash + + - name: Set credentials in config file + run: | + crudini --existing=param --set config.conf enterprise-edition user ${{ env.SUPERUSER_NAME_AND_PASSWORD }} + crudini --existing=param --set config.conf enterprise-edition password ${{ env.SUPERUSER_NAME_AND_PASSWORD }} + working-directory: .github/workflows shell: bash - name: Log into Docker Hub to get server RC @@ -37,26 +58,51 @@ runs: run: docker login --username ${{ inputs.docker-hub-username }} --password ${{ inputs.docker-hub-password }} shell: bash - - name: Get default aerospike.conf from Docker server EE container - run: | - docker run -d --name aerospike -p 3000-3002:3000-3002 $SERVER_IMAGE:${{ inputs.server-tag }} - sleep 5 - docker cp aerospike:/etc/aerospike/aerospike.conf ./configs/aerospike.conf - docker container stop aerospike - docker container rm aerospike + - run: echo IMAGE_NAME=aerospike/aerospike-server-enterprise${{ inputs.use-server-rc == 'true' && '-rc' || '' }}:${{ inputs.server-tag }} >> $GITHUB_ENV + shell: bash + + - run: echo NEW_IMAGE_NAME=${{ env.IMAGE_NAME }}-security-and-sc >> $GITHUB_ENV + shell: bash + + # macOS Github runners and Windows self-hosted runners don't have buildx installed by default + - if: ${{ runner.os == 'Windows' || runner.os == 'macOS' }} + uses: docker/setup-buildx-action@v3 + + - name: Build and push + uses: docker/build-push-action@v6 + with: + # Don't want to use default Git context or else it will clone the whole Python client repo again + context: .github/workflows/docker-build-context + build-args: | + server_image=${{ env.IMAGE_NAME }} + tags: ${{ env.NEW_IMAGE_NAME }} + # setup-buildx-action configures Docker to use the docker-container build driver + # This driver doesn't publish an image locally by default + # so we have to manually enable it + load: true + + - run: echo SERVER_CONTAINER_NAME="aerospike" >> $GITHUB_ENV + shell: bash + + - run: docker run -d --name ${{ env.SERVER_CONTAINER_NAME }} -e DEFAULT_TTL=2592000 -p 3000:3000 ${{ env.NEW_IMAGE_NAME }} + shell: bash + + - uses: ./.github/actions/wait-for-as-server-to-start + with: + container-name: ${{ env.SERVER_CONTAINER_NAME }} + is-strong-consistency-enabled: true + + - run: echo ASADM_AUTH_FLAGS="--user=${{ env.SUPERUSER_NAME_AND_PASSWORD }} --password=${{ env.SUPERUSER_NAME_AND_PASSWORD }}" >> $GITHUB_ENV shell: bash - - name: Enable security features using aerospike.conf - # Security stanza - run: echo -e "security {\n\tenable-quotas true\n}\n" >> ./aerospike.conf - working-directory: ./configs + # All the partitions are assumed to be dead when reusing a roster file + - run: docker exec ${{ env.SERVER_CONTAINER_NAME }} asadm $ASADM_AUTH_FLAGS --enable --execute "manage revive ns test" shell: bash - - name: Run enterprise edition server - run: docker run -tid -v $(pwd)/configs:/opt/aerospike/etc -p 3000:3000 --name aerospike $SERVER_IMAGE:${{ inputs.server-tag }} asd --config-file /opt/aerospike/etc/aerospike.conf + # Apply changes + - run: docker exec ${{ env.SERVER_CONTAINER_NAME }} asadm $ASADM_AUTH_FLAGS --enable --execute "manage recluster" shell: bash - - name: Create user in database for tests - # Use default admin user to create another user for testing - run: docker exec aerospike asadm --user admin --password admin --enable -e "manage acl create user superuser password superuser roles read-write-udf sys-admin user-admin data-admin" + # For debugging + - run: docker logs aerospike shell: bash \ No newline at end of file diff --git a/.github/actions/update-version/action.yml b/.github/actions/update-version/action.yml index 21a30634..ae81938d 100644 --- a/.github/actions/update-version/action.yml +++ b/.github/actions/update-version/action.yml @@ -9,5 +9,5 @@ runs: using: "composite" steps: - name: Update VERSION metadata - run: echo ${{ inputs.new_version }} > VERSION + run: npm version ${{ inputs.new_version }} --no-git-tag-version shell: bash diff --git a/.github/actions/wait-for-as-server-to-start/action.yml b/.github/actions/wait-for-as-server-to-start/action.yml new file mode 100644 index 00000000..373c2697 --- /dev/null +++ b/.github/actions/wait-for-as-server-to-start/action.yml @@ -0,0 +1,28 @@ +name: 'Wait for Aerospike server to start' +description: Only tested on Linux and macOS +inputs: + container-name: + required: true + is-security-enabled: + required: false + default: 'false' + is-strong-consistency-enabled: + required: false + default: 'false' + +runs: + using: "composite" + steps: + - name: 'macOS: install timeout command' + if: ${{ runner.os == 'macOS' }} + run: brew install coreutils + shell: bash + + # Composite actions doesn't support step-level timeout-minutes + # Use timeout command and store polling logic in file to make it easier to read + # Call bash shell explicitly since timeout uses "sh" shell by default, for some reason + # Also, we don't want to fail if we timeout in case the server *did* finish starting up but the script couldn't detect it due to a bug + # Effectively, this composite action is like calling "sleep" that is optimized to exit early when it detects an ok from the server + - name: Wait for EE server to start + run: timeout 30 bash ./.github/workflows/wait-for-as-server-to-start.bash ${{ inputs.container-name }} ${{ inputs.is-security-enabled }} ${{ inputs.is-strong-consistency-enabled }} || true + shell: bash diff --git a/.github/workflows/Dockerfile b/.github/workflows/Dockerfile new file mode 100644 index 00000000..e1584824 --- /dev/null +++ b/.github/workflows/Dockerfile @@ -0,0 +1,10 @@ +ARG image +FROM $image +RUN echo -e "security {\n\tenable-quotas true\n}\n" >> /etc/aerospike/aerospike.template.conf +# security.smd was generated manually by +# 1. Starting a new Aerospike EE server using Docker +# 2. Creating the superuser user +# 3. Copying /opt/aerospike/smd/security.smd from the container and committing it to this repo +# This file should always work +# TODO: generate this automatically, somehow +COPY security.smd /opt/aerospike/smd/ diff --git a/.github/workflows/build-artifacts.yml b/.github/workflows/build-artifacts.yml index 8a90cae0..e306fc29 100644 --- a/.github/workflows/build-artifacts.yml +++ b/.github/workflows/build-artifacts.yml @@ -86,10 +86,10 @@ jobs: matrix: platform-tag: [ "manylinux_x86_64", - "manylinux_aarch64", + #"manylinux_aarch64", "macosx_x86_64", - "macosx_arm64", - "win_amd64" + #"macosx_arm64", + #"win_amd64" ] fail-fast: false uses: ./.github/workflows/build-bindings.yml diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index d68ef14e..328215c1 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -34,10 +34,10 @@ on: required: true options: - manylinux_x86_64 - - manylinux_aarch64 + #- manylinux_aarch64 - macosx_x86_64 - - macosx_arm64 - - win_amd64 + #- macosx_arm64 + #- win_amd64 # Makes debugging via gh cli easier. default: manylinux_x86_64 unoptimized: @@ -65,6 +65,10 @@ on: required: true default: 'latest' description: 'Server docker image tag' + test-file: + required: false + default: '' + description: 'new_tests/' workflow_call: inputs: @@ -106,6 +110,10 @@ on: type: string default: 'latest' description: 'Server docker image tag' + test-file: + required: false + type: string + default: '' secrets: # Just make all the secrets required to make things simpler... DOCKER_HUB_BOT_USERNAME: @@ -184,7 +192,7 @@ jobs: - name: 'macOS x86: run Aerospike server in Docker container and connect via localhost' if: ${{ env.RUN_INTEGRATION_TESTS_IN_CIBW == 'true' && inputs.platform-tag == 'macosx_x86_64' }} - uses: ./.github/actions/run-ee-server + uses: ./.github/actions/run-ee-server-for-ext-container with: use-server-rc: ${{ inputs.use-server-rc }} server-tag: ${{ inputs.server-tag }} @@ -212,14 +220,14 @@ jobs: # run: echo "TEST_COMMAND=python -c \"import aerospike\"" >> $GITHUB_ENV # shell: bash - - name: Otherwise, enable integration tests - if: ${{ env.RUN_INTEGRATION_TESTS_IN_CIBW == 'true' }} - run: echo "TEST_COMMAND=cd ts-test; - npm install typescript --save-dev; - npx tsc; - cd ..; - npm run test dist/ -- --h 127.0.0.1 --port 3000" >> $GITHUB_ENV - shell: bash + #- name: Otherwise, enable integration tests + # if: ${{ env.RUN_INTEGRATION_TESTS_IN_CIBW == 'true' }} + # run: echo "TEST_COMMAND=cd ts-test; + # npm install typescript --save-dev; + # npx tsc; + # cd ..; + # npm run test dist/ -- --h 127.0.0.1 --port 3000" >> $GITHUB_ENV + # shell: bash - name: Set unoptimize flag if: ${{ inputs.unoptimized && (startsWith(inputs.platform-tag, 'manylinux') || startsWith(inputs.platform-tag, 'macosx')) }} @@ -234,6 +242,29 @@ jobs: ./scripts/build-c-client.sh; npm install; + + - name: Run tests + if: ${{ inputs.run_tests && inputs.platform-tag == 'manylinux_x86_64'}} + run: | + docker ps; + docker logs aerospike; + cd ts-test; + npm install typescript --save-dev; + npx tsc; + cd ..; + npm run test dist/${{ inputs.test-file }} -- --h 172.17.0.2 --port 3000 --U superuser --P superuser; + + - name: Run tests + if: ${{ inputs.run_tests && inputs.platform-tag == 'macosx_x86_64'}} + run: | + docker ps; + docker logs aerospike; + cd ts-test; + npm install typescript --save-dev; + npx tsc; + cd ..; + npm run test dist/${{ inputs.test-file }} -- --h localhost --port 3000 --U superuser --P superuser; + # NEED TO MAKE A NODEJS ACTION WHICH REPLACES THIS!!! #- name: Build wheel # uses: pypa/cibuildwheel@v2.20.0 @@ -334,7 +365,7 @@ jobs: run: | $env:DOCKER_HOST_IP = $env:DOCKER_HOST | foreach {$_.replace("tcp://","")} | foreach {$_.replace(":2375", "")} crudini --set config.conf enterprise-edition hosts ${env:DOCKER_HOST_IP}:3000 - working-directory: test + working-directory: ./github/workflows # FIGURE OUT WHAT SETUP NEEDS TO HAPPEN - run: | @@ -347,7 +378,7 @@ jobs: - run: npx tsc shell: bash - - run: npm run test dist/ -- --h 127.0.0.1 --port 3000 + - run: npm run test dist/ -- --h ${env:DOCKER_HOST_IP} --port 3000 shell: bash - name: Show job status for commit diff --git a/.github/workflows/bump-dev-num.js b/.github/workflows/bump-dev-num.js new file mode 100644 index 00000000..7e555541 --- /dev/null +++ b/.github/workflows/bump-dev-num.js @@ -0,0 +1,25 @@ +const semver = require('semver') + +const versionString = process.argv[2] +const version = semver.parse(versionString) + +if (!version) { + console.error('Invalid version string') + process.exit(1) +} + +if (version.prerelease.includes('dev')) { + // Increment the dev release number + version.inc('prerelease', 'dev') +} else if (version.prerelease.includes('rc')) { + // Increment the RC number + version.inc('prerelease', 'rc') + version.prerelease[1] = 1 // Ensure dev number starts at 1 +} else { + // Assume this is a release version + version.inc('minor') // Bump to next minor version + version.prerelease = ['rc', 1] // Start RC numbers from 1 + version.format() // Apply changes +} + +console.log(version.version) diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml index cec01cb0..c88c43f5 100644 --- a/.github/workflows/bump-version.yml +++ b/.github/workflows/bump-version.yml @@ -55,7 +55,13 @@ jobs: - name: Get current version id: get-current-version - run: echo current_version=$(cat VERSION) >> $GITHUB_OUTPUT + run: | + echo "current_version=$(node -p 'require(\"./package.json\").version')" >> $GITHUB_OUTPUT + + - name: Print current version + run: echo "Current version is ${{ steps.get-current-version.outputs.current_version }}" + + get-new-version: runs-on: ubuntu-22.04 @@ -66,14 +72,21 @@ jobs: # Checkout branch where workflow is being called from - uses: actions/checkout@v4 - - name: Install library that parses PEP 440 versions + - name: Install library that parses nodejs versions # NEED TO CHANGE THIS TO WORK WITH NODEJS - run: pip install parver -c requirements.txt + run: npm install semver working-directory: .github/workflows - name: Get new version id: get-new-version - run: echo new_version=$(python3 .github/workflows/${{ inputs.change }}.py ${{ needs.get-current-version.outputs.current_version }}) >> $GITHUB_OUTPUT + run: | + echo new_version=$(node bump-dev-num.js) >> $GITHUB_OUTPUT + echo "new_version=$new_version" >> $GITHUB_OUTPUT + working-directory: .github/workflows + + #- name: Print new version + # run: echo "New version is: ${{ steps.get-current-version.outputs.new_version }}" + update-version-in-repo: needs: get-new-version diff --git a/.github/workflows/config.conf.template b/.github/workflows/config.conf.template new file mode 100644 index 00000000..e9fd3924 --- /dev/null +++ b/.github/workflows/config.conf.template @@ -0,0 +1,7 @@ +[community-edition] +hosts: 127.0.0.1:3000 + +[enterprise-edition] +hosts : +user : +password : diff --git a/.github/workflows/dev-workflow-p1.yml b/.github/workflows/dev-workflow-p1.yml index daee8c11..8e90900c 100644 --- a/.github/workflows/dev-workflow-p1.yml +++ b/.github/workflows/dev-workflow-p1.yml @@ -9,6 +9,7 @@ on: types: - opened - review_requested + - synchronize branches: - 'dev*' - 'dev-CICD' @@ -33,8 +34,9 @@ jobs: sha-to-build-and-test: ${{ github.sha }} secrets: inherit - test-with-server-rc: - needs: test-with-server-release - if: ${{ github.event_name == 'workflow_dispatch' || contains(github.event.pull_request.labels.*.name, 'new-server-features') }} - uses: ./.github/workflows/test-server-rc.yml - secrets: inherit +# test-with-server-rc: +# needs: test-with-server-release +# if: ${{ github.event_name == 'workflow_dispatch' || contains(github.event.pull_request.labels.*.name, 'new-server-features') }} +# uses: ./.github/workflows/test-server-rc.yml +# secrets: inherit +# \ No newline at end of file diff --git a/.github/workflows/dev-workflow-p2.yml b/.github/workflows/dev-workflow-p2.yml index 31a345b6..d2b53762 100644 --- a/.github/workflows/dev-workflow-p2.yml +++ b/.github/workflows/dev-workflow-p2.yml @@ -1,31 +1,35 @@ -#name: Dev workflow (part 2) -# -#on: -# pull_request_target: -# branches: -# - 'dev*' -# types: -# - closed -# workflow_dispatch: -# -#jobs: -# bump-dev-number: -# if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true }} -# uses: ./.github/workflows/bump-version.yml -# with: -# change: 'bump-dev-num' -# secrets: inherit -# -# rebuild-artifacts-with-new-dev-num: -# needs: bump-dev-number -# name: Rebuild artifacts with new dev number -# uses: ./.github/workflows/build-artifacts.yml -# with: -# # On pull_request_target, the bump version commit will be ignored -# # So we must pass it manually to the workflow -# sha-to-build-and-test: ${{ needs.bump-dev-number.outputs.bump_sha }} -# secrets: inherit -# +name: Dev workflow (part 2) + +on: + pull_request: + types: + - synchronize + branches: + - 'dev*' + +jobs: + bump-dev-number: + #if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true }} + uses: ./.github/workflows/bump-version.yml + with: + change: 'bump-dev-num' + secrets: inherit + + rebuild-artifacts-with-new-dev-num: + needs: bump-dev-number + name: Rebuild artifacts with new dev number + uses: ./.github/workflows/build-artifacts.yml + with: + # On pull_request_target, the bump version commit will be ignored + # So we must pass it manually to the workflow + sha-to-build-and-test: ${{ needs.bump-dev-number.outputs.bump_sha }} + secrets: inherit + + test-npm-install: + needs: rebuild-artifacts-with-new-dev-num + name: Test npm install command for npm package + uses: ./.github/workflows/npm-install-script-test.yml + # upload-to-jfrog: # name: Upload artifacts to JFrog # needs: [ @@ -41,3 +45,4 @@ # delete-artifacts: # needs: upload-to-jfrog # uses: ./.github/workflows/delete-artifacts.yml +# \ No newline at end of file diff --git a/.github/workflows/docker-build-context/Dockerfile b/.github/workflows/docker-build-context/Dockerfile new file mode 100644 index 00000000..142c78aa --- /dev/null +++ b/.github/workflows/docker-build-context/Dockerfile @@ -0,0 +1,50 @@ +ARG server_image=aerospike/aerospike-server-enterprise:8.0.0.0-rc1 +ARG ROSTER_FILE_NAME=roster.smd +# Temp file for passing node id from one build stage to another +# Docker doesn't support command substitution for setting values for ARG variables, so we have to do this +ARG NODE_ID_FILE_NAME=node_id + +FROM $server_image as configure-server + +WORKDIR /opt/aerospike/smd + +# Enable authentication + +ARG AEROSPIKE_CONF_TEMPLATE_PATH=/etc/aerospike/aerospike.template.conf + +# Not using asconfig to edit config because we are working with a template file, which may not have valid values yet +RUN echo -e "security {\n\tenable-quotas true\n}\n" >> $AEROSPIKE_CONF_TEMPLATE_PATH +# security.smd was generated manually by +# 1. Starting a new Aerospike EE server using Docker +# 2. Creating the superuser user +# 3. Copying /opt/aerospike/smd/security.smd from the container and committing it to this repo +# This file should always work +# TODO: generate this automatically, somehow. +COPY security.smd . + +# Enable strong consistency +RUN sed -i "s/\(namespace.*{\)/\1\n\tstrong-consistency true/" $AEROSPIKE_CONF_TEMPLATE_PATH +RUN sed -i "s/\(namespace.*{\)/\1\n\tstrong-consistency-allow-expunge true/" $AEROSPIKE_CONF_TEMPLATE_PATH +RUN sed -i "s/\(namespace.*{\)/\1\n\tdefault-ttl 2592000/" $AEROSPIKE_CONF_TEMPLATE_PATH +ARG ROSTER_FILE_NAME +COPY $ROSTER_FILE_NAME . + +# Fetch node id from roster.smd + +# There's no tag for the latest major version to prevent breaking changes in jq +# This is the next best thing +FROM ghcr.io/jqlang/jq:1.7 as get-jq +# jq docker image doesn't have a shell +# We need a shell to fetch and pass the node id to the next build stage +FROM busybox as get-node-id +COPY --from=get-jq /jq /bin/ +ARG ROSTER_FILE_NAME +COPY $ROSTER_FILE_NAME . +ARG NODE_ID_FILE_NAME +RUN jq --raw-output '.[1].value' $ROSTER_FILE_NAME > $NODE_ID_FILE_NAME + +FROM configure-server as set-node-id +ARG NODE_ID_FILE_NAME +COPY --from=get-node-id $NODE_ID_FILE_NAME . +RUN sed -i "s/\(^service {\)/\1\n\tnode-id $(cat $NODE_ID_FILE_NAME)/" $AEROSPIKE_CONF_TEMPLATE_PATH +RUN rm $NODE_ID_FILE_NAME \ No newline at end of file diff --git a/.github/workflows/docker-build-context/roster.smd b/.github/workflows/docker-build-context/roster.smd new file mode 100644 index 00000000..76ba77ef --- /dev/null +++ b/.github/workflows/docker-build-context/roster.smd @@ -0,0 +1,12 @@ +[ + [ + 97107025374203, + 1 + ], + { + "key": "test", + "value": "a1", + "generation": 1, + "timestamp": 465602976982 + } +] \ No newline at end of file diff --git a/.github/workflows/docker-build-context/security.smd b/.github/workflows/docker-build-context/security.smd new file mode 100644 index 00000000..9c530d51 --- /dev/null +++ b/.github/workflows/docker-build-context/security.smd @@ -0,0 +1,48 @@ +[ + [ + 162276881999406, + 14 + ], + { + "key": "admin|P", + "value": "$2a$10$7EqJtq98hPqEX7fNZaFWoO1mVO/4MLpGzsqojz6E9Gef6iXDjXdDa", + "generation": 1, + "timestamp": 0 + }, + { + "key": "admin|R|user-admin", + "value": "", + "generation": 1, + "timestamp": 0 + }, + { + "key": "superuser|P", + "value": "$2a$10$7EqJtq98hPqEX7fNZaFWoOZX0o4mZCBUwvzt/iecIcG4JaDOC41zK", + "generation": 3, + "timestamp": 458774922440 + }, + { + "key": "superuser|R|read-write-udf", + "value": "", + "generation": 3, + "timestamp": 458774922441 + }, + { + "key": "superuser|R|sys-admin", + "value": "", + "generation": 3, + "timestamp": 458774922442 + }, + { + "key": "superuser|R|user-admin", + "value": "", + "generation": 3, + "timestamp": 458774922442 + }, + { + "key": "superuser|R|data-admin", + "value": null, + "generation": 2, + "timestamp": 458774718056 + } +] diff --git a/.github/workflows/npm-install-script-test.yml b/.github/workflows/npm-install-script-test.yml new file mode 100644 index 00000000..823f39fe --- /dev/null +++ b/.github/workflows/npm-install-script-test.yml @@ -0,0 +1,120 @@ +name: npm install script test + +on: + workflow_call: # This allows this workflow to be reused by others. + +jobs: + npm-install-script-test: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + + - name: Create multiple directories + run: mkdir -p ./lib/binding ./lib/binding/glibc@2.35/ ./lib/binding/glibc@2.31 + + + + # - uses: actions/download-artifact@v4 + # with: + # name: v108-macosx_aarch64.build + + - uses: actions/download-artifact@v4 + with: + name: v108-macosx_x86_64.node + + # - uses: actions/download-artifact@v4 + # with: + # name: v115-macosx_aarch64.build + + - uses: actions/download-artifact@v4 + with: + name: v115-macosx_x86_64.node + + # - uses: actions/download-artifact@v4 + # with: + # name: v127-macosx_aarch64.build + + - uses: actions/download-artifact@v4 + with: + name: v127-macosx_x86_64.node + + - uses: actions/download-artifact@v4 + with: + name: v131-macosx_x86_64.node + + - uses: actions/download-artifact@v4 + with: + name: v108-manylinux_x86_64.node + + # - uses: actions/download-artifact@v4 + # with: + # name: v108-manylinux_aarch64.build + + - uses: actions/download-artifact@v4 + with: + name: v115-manylinux_x86_64.node + + # - uses: actions/download-artifact@v4 + # with: + # name: v115-manylinux_aarch64.build + + - uses: actions/download-artifact@v4 + with: + name: v127-manylinux_x86_64.node + + # - uses: actions/download-artifact@v4 + # with: + # name: v127-manylinux_aarch64.build + + - uses: actions/download-artifact@v4 + with: + name: v131-manylinux_x86_64.node + + # - uses: actions/download-artifact@v4 + # with: + # name: v131-manylinux_aarch64.build + + - name: Install client + shell: bash + run: | + ls .; + ls ./lib/binding; + mkdir -p lib/binding/node-v108-darwin-arm64 lib/binding/node-v115-darwin-arm64 lib/binding/node-v127-darwin-arm64 lib/binding/node-v131-darwin-arm64 + mkdir -p lib/binding/glibc@2.39/node-v108-linux-arm64 lib/binding/glibc@2.39/node-v115-linux-arm64 lib/binding/glibc@2.39/node-v127-linux-arm64 lib/binding/glibc@2.39/node-v131-linux-arm64 + mkdir -p lib/binding/glibc@2.35/node-v108-linux-arm64 lib/binding/glibc@2.35/node-v115-linux-arm64 lib/binding/glibc@2.35/node-v127-linux-arm64 lib/binding/glibc@2.31/node-v131-linux-arm64 + mkdir -p lib/binding/glibc@2.31/node-v108-linux-arm64 lib/binding/glibc@2.31/node-v115-linux-arm64 lib/binding/glibc@2.31/node-v127-linux-arm64 lib/binding/glibc@2.35/node-v131-linux-arm64 + mkdir -p lib/binding/glibc@2.39/node-v108-linux-x64 lib/binding/glibc@2.39/node-v115-linux-x64 lib/binding/glibc@2.39/node-v127-linux-x64 lib/binding/glibc@2.39/node-v131-linux-x64 + mkdir -p lib/binding/glibc@2.35/node-v108-linux-x64 lib/binding/glibc@2.35/node-v115-linux-x64 lib/binding/glibc@2.35/node-v127-linux-x64 lib/binding/glibc@2.35/node-v131-linux-x64 + mkdir -p lib/binding/glibc@2.31/node-v108-linux-x64 lib/binding/glibc@2.31/node-v115-linux-x64 lib/binding/glibc@2.31/node-v127-linux-x64 lib/binding/glibc@2.31/node-v131-linux-x64 + cp -r node-v108-linux-x64 lib/binding/glibc@2.35/ + cp -r node-v115-linux-x64 lib/binding/glibc@2.35/ + cp -r node-v127-linux-x64 lib/binding/glibc@2.35/ + cp -r node-v108-darwin-x64 lib/binding/node-v108-darwin-x64 + cp -r node-v115-darwin-x64 lib/binding/node-v115-darwin-x64 + cp -r node-v127-darwin-x64 lib/binding/node-v127-darwin-x64 + cp -r node-v127-darwin-x64 lib/binding/node-v131-darwin-x64 + # cp -r node-v108-linux-arm64 lib/binding/node-v108-linux-arm64 + # cp -r node-v115-linux-arm64 lib/binding/node-v115-linux-arm64 + # cp -r node-v127-linux-arm64 lib/binding/node-v127-linux-arm64 + # cp -r node-v127-linux-arm64 lib/binding/node-v131-linux-arm64 + # cp -r node-v108-darwin-arm64 lib/binding/node-v108-darwin-arm64 + # cp -r node-v115-darwin-arm64 lib/binding/node-v115-darwin-arm64 + # cp -r node-v127-darwin-arm64 lib/binding/node-v127-darwin-arm64 + # cp -r node-v127-darwin-arm64 lib/binding/node-v131-darwin-arm64 + + - name: List available artifacts + run: ls ./lib/binding || echo "No artifacts found in binding" + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: 20 + + - name: Run Node.js script + run: node ./scripts/prebuiltBinding.js + + - name: List available artifacts + run: ls ./lib/binding || echo "No artifacts found in binding" \ No newline at end of file diff --git a/.github/workflows/requirements.txt b/.github/workflows/requirements.txt new file mode 100644 index 00000000..5099e0d6 --- /dev/null +++ b/.github/workflows/requirements.txt @@ -0,0 +1,4 @@ +parver==0.5 +crudini==0.9.4 +delocate==0.10.4 +mypy==1.10.0 diff --git a/.github/workflows/test-server-rc.yml b/.github/workflows/test-server-rc.yml index 7bdc2f7c..6428684a 100644 --- a/.github/workflows/test-server-rc.yml +++ b/.github/workflows/test-server-rc.yml @@ -25,7 +25,7 @@ jobs: ] platform: [ ["x86_64", "ubuntu-22.04"], - ["aarch64", "aerospike_arm_runners_2"] + #["aarch64", "aerospike_arm_runners_2"] ] runs-on: ${{ matrix.platform[1] }} steps: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 00000000..7a9ba295 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,456 @@ +name: PR pre-merge tests + +env: + LOWEST_SUPPORTED_NODEJS_VERSION: '18' + LOWEST_SUPPORTED_NODE_MODULE: 'v108' + +# Trigger test workflow whenever: +# 1. A pull request is updated (e.g with new commits) +# 2. Commits are pushed directly to the stage or master branch +on: + push: + branches: ["stage", "master"] + pull_request: + branches: ["stage", "master"] + types: [ + # Default triggers + opened, + synchronize, + reopened, + # Additional triggers + labeled, + unlabeled + ] + workflow_dispatch: + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: install standard + run: npm install standard + + - name: lint + run: npm run lint + + build-ubuntu: + runs-on: ubuntu-latest + strategy: + matrix: + nodejs-version: ["18", "20", "22", "23"] + fail-fast: false + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.nodejs-version }} + architecture: 'x64' + - name: debugging + run: | + echo "LOWEST_SUPPORTED_NODEJS_VERSION: $LOWEST_SUPPORTED_NODEJS_VERSION" + + - run: sudo apt update + - name: Install build dependencies (C Client dependency packages) + run: sudo apt install g++ libssl-dev zlib1g-dev; + - name: Install build dependencies (make) + run: sudo apt-get install -y make; + - name: Install build dependencies (make) + run: sudo apt install build-essential; + + - name: Build client + run: | + ./scripts/build-c-client.sh + npm install + env: + CFLAGS: '-Werror' + + - name: list + run: ls lib/binding + - name: Send binding to test jobs + uses: actions/upload-artifact@v4 + with: + name: binding-${{ matrix.nodejs-version }} + path: ./lib/binding/node-*-linux-x64/ + +# test-memray: +# needs: build-ubuntu +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@v4 +# +# - uses: actions/setup-node@v4 +# with: +# node-version: ${{ matrix.nodejs-version }} +# architecture: 'x64' +# +# - uses: actions/download-artifact@v4 +# with: +# name: binding-18 +# +# - name: make binding folder +# run: mkdir lib/binding +# +# - name: Install client +# run: cp -r install node-v108-linux-x64 lib/binding/node-v108-linux-x64 +# +# - name: Install client +# run: npm install . +# +# - name: Run Aerospike server +# run: docker run -d --name aerospike -p 3000-3002:3000-3002 aerospike/aerospike-server +# +# - name: Wait for database to be ready +# # Should be ready after 3 seconds +# run: sleep 3 +# +# - name: Get number of tests +# run: echo "NUM_TESTS=$(npm run test-dry-run | grep -oP '\d+ (passing|pending)' | awk '{ sum += $1 } END { print sum }')" >> $GITHUB_ENV +# working-directory: test +# +# - name: Run tests +# # Get number of tests since setting to 0 doesn't work properly +# # pytest-memray currently throws a ZeroDivision error due to having a bug +# # We ignore this for now +# run: python -m pytest ./new_tests --memray --memray-bin-path=./ --most-allocations=${{ env.NUM_TESTS }} || true +# working-directory: test + + # Run this when testing new server features on server release candidate + # to make sure the tests don't regress on the last server release. + test-ce-latest-release: + runs-on: ubuntu-latest + if: ${{ contains(github.event.pull_request.labels.*.name, 'new-server-features') }} + needs: build-ubuntu + + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: debugging + run: | + echo "LOWEST_SUPPORTED_NODEJS_VERSION: $LOWEST_SUPPORTED_NODEJS_VERSION" + - uses: actions/setup-node@v4 + with: + node-version: ${{ env.LOWEST_SUPPORTED_NODEJS_VERSION }} + architecture: 'x64' + + - uses: actions/download-artifact@v4 + with: + name: binding-${{ env.LOWEST_SUPPORTED_NODEJS_VERSION }} + env: + LOWEST_SUPPORTED_NODEJS_VERSION: ${{ env.LOWEST_SUPPORTED_NODEJS_VERSION }} + + + - name: make binding folder + run: mkdir lib/binding + + - name: Install client + run: cp -r node-${{ env.LOWEST_SUPPORTED_NODE_MODULE }}-linux-x64 lib/binding/node-${{ env.LOWEST_SUPPORTED_NODE_MODULE }}-linux-x64 + + - name: Run Aerospike server + run: docker run -d --name aerospike -p 3000-3002:3000-3002 aerospike/aerospike-server + + - name: Wait for database to be ready + # Should be ready after 3 seconds + run: sleep 3 + + - name: Run tests + run: npm run test + + test-ce: + runs-on: ubuntu-latest + needs: build-ubuntu + strategy: + matrix: + node-version: [ + "18", + "20", + "22", + "23" + ] + fail-fast: false + + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + architecture: 'x64' + + - uses: actions/download-artifact@v4 + with: + name: binding-${{ matrix.node-version }} + + - name: make binding folder + run: mkdir lib/binding + + - name: install mocha + run: npm install mocha + + - name: Install client + #fix the convention here + run: | + if [ "${{ matrix.node-version }}" = "18" ]; then + cp -r node-v108-linux-x64 lib/binding/node-v108-linux-x64 + elif [ "${{ matrix.node-version }}" = "20" ]; then + cp -r node-v115-linux-x64 lib/binding/node-v115-linux-x64 + elif [ "${{ matrix.node-version }}" = "22" ]; then + cp -r node-v127-linux-x64 lib/binding/node-v127-linux-x64 + elif [ "${{ matrix.node-version }}" = "23" ]; then + cp -r node-v131-linux-x64 lib/binding/node-v131-linux-x64 + fi + + - if: ${{ contains(github.event.pull_request.labels.*.name, 'new-server-features') }} + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_HUB_BOT_USERNAME }} + password: ${{ secrets.DOCKER_HUB_BOT_PW }} + + - name: Run Aerospike server release candidate with latest tag + if: ${{ contains(github.event.pull_request.labels.*.name, 'new-server-features') }} + run: docker run -d --name aerospike -p 3000-3002:3000-3002 aerospike/aerospike-server-rc:latest + + - name: Run Aerospike server + if: ${{ !contains(github.event.pull_request.labels.*.name, 'new-server-features') }} + run: docker run -d -v $(pwd)/.github/assets/aerospike.conf:/etc/mail/aerospike.conf --name aerospike -p 3000-3002:3000-3002 aerospike/aerospike-server --config-file /etc/mail/aerospike.conf + + - name: Wait for database to be ready + # Should be ready after 3 seconds + run: sleep 3 + + - name: Run tests + run: | + cd ts-test; + npm install typescript --save-dev; + npx tsc; + cd ..; + npm run test + + test-lowest-supported-server: + runs-on: ubuntu-latest + needs: build-ubuntu + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + + - uses: actions/setup-node@v4 + with: + node-version: ${{ env.LOWEST_SUPPORTED_NODEJS_VERSION }} + architecture: 'x64' + + - uses: actions/download-artifact@v4 + with: + name: binding-${{ env.LOWEST_SUPPORTED_NODEJS_VERSION }} + env: + LOWEST_SUPPORTED_NODEJS_VERSION: ${{ env.LOWEST_SUPPORTED_NODEJS_VERSION }} + + - name: make binding folder + run: mkdir lib/binding + + - name: install mocha + run: npm install mocha + + - name: Install client + #fix the convention here + run: cp -r node-${{ env.LOWEST_SUPPORTED_NODE_MODULE }}-linux-x64 lib/binding/node-${{ env.LOWEST_SUPPORTED_NODE_MODULE }}-linux-x64 + + - name: Run lowest supported server + run: | + SERVER_VERSION=$(curl -s "https://registry.hub.docker.com/v2/repositories/aerospike/aerospike-server/tags?page_size=100" | jq '.results[] | select(.name | startswith("6.1")).name' -r | head -n 1) + docker run -d --name aerospike -p 3000-3002:3000-3002 aerospike/aerospike-server:$SERVER_VERSION + + - name: Wait for database to be ready + # Should be ready after 3 seconds + run: sleep 3 + + - name: Run tests + run: | + cd ts-test; + npm install typescript --save-dev; + npx tsc; + cd ..; + npm run test -- --t 20000 + + test-ee: + runs-on: ubuntu-latest + needs: build-ubuntu + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - uses: actions/setup-node@v4 + with: + node-version: ${{ env.LOWEST_SUPPORTED_NODEJS_VERSION }} + architecture: 'x64' + + - uses: actions/download-artifact@v4 + with: + name: binding-${{ env.LOWEST_SUPPORTED_NODEJS_VERSION }} + env: + LOWEST_SUPPORTED_NODEJS_VERSION: ${{ env.LOWEST_SUPPORTED_NODEJS_VERSION }} + + - name: make binding folder + run: mkdir lib/binding + + - name: install mocha + run: npm install mocha + + - name: Install client + #fix the convention here + run: cp -r node-${{ env.LOWEST_SUPPORTED_NODE_MODULE }}-linux-x64 lib/binding/node-${{ env.LOWEST_SUPPORTED_NODE_MODULE }}-linux-x64 + + - name: Download aerospike-client-python repository + run: git clone https://github.com/aerospike/aerospike-client-python.git + + - name: debugging + run: | + ls; + ls .github; + docker ps; + + - name: Run ee server + uses: ./.github/actions/run-ee-server + with: + use-server-rc: ${{ contains(github.event.pull_request.labels.*.name, 'new-server-features') }} + docker-hub-username: ${{ secrets.DOCKER_HUB_BOT_USERNAME }} + docker-hub-password: ${{ secrets.DOCKER_HUB_BOT_PW }} + + + - name: Wait for server to start + run: sleep 5 + + - name: Run tests + run: | + cd ts-test; + npm install typescript --save-dev; + npx tsc; + cd ..; + npm run test -- --h localhost --U superuser --P superuser --t 40000 + + test-valgrind: + runs-on: ubuntu-latest + needs: build-ubuntu + strategy: + matrix: + node-version: [ + "20", + ] + fail-fast: false + + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + architecture: 'x64' + + - uses: actions/download-artifact@v4 + with: + name: binding-${{ matrix.node-version }} + + - name: make binding folder + run: mkdir lib/binding + + - name: install mocha + run: npm install mocha + + - name: install valgrind + run: | + sudo apt-get update; + sudo apt update; + sudo apt install valgrind; + + - name: Install client + #fix the convention here + run: | + cp -r node-v115-linux-x64 lib/binding/node-v115-linux-x64 + + - if: ${{ contains(github.event.pull_request.labels.*.name, 'new-server-features') }} + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_HUB_BOT_USERNAME }} + password: ${{ secrets.DOCKER_HUB_BOT_PW }} + + - name: Run Aerospike server release candidate with latest tag + if: ${{ contains(github.event.pull_request.labels.*.name, 'new-server-features') }} + run: docker run -d --name aerospike -p 3000-3002:3000-3002 aerospike/aerospike-server-rc:latest + + - name: Run Aerospike server + if: ${{ !contains(github.event.pull_request.labels.*.name, 'new-server-features') }} + run: docker run -d -v $(pwd)/.github/assets/aerospike.conf:/etc/mail/aerospike.conf --name aerospike -p 3000-3002:3000-3002 aerospike/aerospike-server --config-file /etc/mail/aerospike.conf + + - name: Wait for database to be ready + # Should be ready after 3 seconds + run: sleep 3 + + - name: Run tests + run: npm run valgrind -- --t 40000 + +# test-typescript: +# runs-on: ubuntu-latest +# needs: build-ubuntu +# strategy: +# matrix: +# node-version: [ +# "20", +# ] +# fail-fast: false +# +# steps: +# - uses: actions/checkout@v2 +# with: +# submodules: recursive +# +# - uses: actions/setup-node@v4 +# with: +# node-version: ${{ matrix.node-version }} +# architecture: 'x64' +# +# - uses: actions/download-artifact@v4 +# with: +# name: binding-${{ matrix.node-version }} +# +# - name: make binding folder +# run: mkdir lib/binding +# +# - name: Install client +# run: | +# cp -r node-v115-linux-x64 lib/binding/node-v115-linux-x64 +# +# - if: ${{ contains(github.event.pull_request.labels.*.name, 'new-server-features') }} +# uses: docker/login-action@v3 +# with: +# username: ${{ secrets.DOCKER_HUB_BOT_USERNAME }} +# password: ${{ secrets.DOCKER_HUB_BOT_PW }} +# +# - name: Run Aerospike server release candidate with latest tag +# if: ${{ contains(github.event.pull_request.labels.*.name, 'new-server-features') }} +# run: docker run -d --name aerospike -p 3000-3002:3000-3002 aerospike/aerospike-server-rc:latest +# +# - name: Run Aerospike server +# if: ${{ !contains(github.event.pull_request.labels.*.name, 'new-server-features') }} +# run: docker run -d --name aerospike -p 3000-3002:3000-3002 aerospike/aerospike-server +# +# - name: Modify the package.json +# run: | +# mkdir my-aerospike-project +# cd my-aerospike-project +# npm init -y +# npm install typescript ts-node --save-dev +# npm install .. +# cp ../examples/typescript.ts index.ts +# npx tsc index.ts +# node index.js \ No newline at end of file diff --git a/.github/workflows/wait-for-as-server-to-start.bash b/.github/workflows/wait-for-as-server-to-start.bash new file mode 100644 index 00000000..18189f19 --- /dev/null +++ b/.github/workflows/wait-for-as-server-to-start.bash @@ -0,0 +1,55 @@ +#!/bin/bash + +set -x +# Makes sure that if the "docker exec" command fails, it is not ignored +set -o pipefail + +container_name=$1 +is_security_enabled=$2 +is_strong_consistency_enabled=$3 + +if [[ $is_security_enabled == true ]]; then + # We need to pass credentials to asinfo if server requires it + # TODO: passing in credentials via command line flags since I can't figure out how to use --instance with global astools.conf + user_credentials="--user=admin --password=admin" +fi + +while true; do + # An unset variable will have a default empty value + # Intermediate step is to print docker exec command's output in case it fails + # Sometimes, errors only appear in stdout and not stderr, like if asinfo throws an error because of no credentials + # (This is a bug in asinfo since all error messages should be sent to stderr) + # But piping and passing stdin to grep will hide the first command's stdout. + # grep doesn't have a way to print all lines passed as input. + # ack does have an option but it doesn't come installed by default + # shellcheck disable=SC2086 # The flags in user credentials should be separate anyways. Not one string + echo "Checking if we can reach the server via the service port..." + if docker exec "$container_name" asinfo $user_credentials -v status | tee >(cat) | grep -qE "^ok"; then + # Server is ready when asinfo returns ok + echo "Can reach server now." + # docker container inspect "$container_name" + break + fi + + echo "Server didn't return ok via the service port. Polling again..." +done + +# Although the server may be reachable via the service port, the cluster may not be fully initialized yet. +# If we try to connect too soon (e.g right after "status" returns ok), the client may throw error code -1 +while true; do + echo "Waiting for server to stabilize (i.e return a cluster key)..." + # We assume that when an ERROR is returned, the cluster is not stable yet (i.e not fully initialized) + cluster_stable_info_cmd="cluster-stable" + if [[ $is_strong_consistency_enabled == true ]]; then + # The Dockerfile uses a roster from a previously running Aerospike server in a Docker container + # When we reuse this roster, the server assumes all of its partitions are dead because it's running on a new + # storage device. + cluster_stable_info_cmd="$cluster_stable_info_cmd:ignore-migrations=true" + fi + if docker exec "$container_name" asinfo $user_credentials -v $cluster_stable_info_cmd 2>&1 | (! grep -qE "^ERROR"); then + echo "Server is in a stable state." + break + fi + + echo "Server did not return a cluster key. Polling again..." +done diff --git a/.github_former/workflows/build-bindings.yml b/.github_former/workflows/build-bindings.yml index 337c7f3e..c94c6559 100644 --- a/.github_former/workflows/build-bindings.yml +++ b/.github_former/workflows/build-bindings.yml @@ -146,15 +146,15 @@ jobs: npm i @types/mocha @types/yargs @types/semver @types/chai; docker run -d -v $(pwd)/.github/assets/aerospike.conf:/etc/mail/aerospike.conf --name aerospike -p 3000-3002:3000-3002 aerospike/aerospike-server --config-file /etc/mail/aerospike.conf -# - name: Set config.conf to use Docker IP address of Aerospike server -# # config.conf should be copied into the cibuildwheel Docker container -# run: | -# export SERVER_DOCKER_IP=$(docker container inspect -f '{{ .NetworkSettings.IPAddress }}' aerospike) -# # Install crudini -# pip install crudini -c ../.github/workflows/requirements.txt -# sed -i "s/127.0.0.1:3000//" config.conf -# crudini --set config.conf enterprise-edition hosts ${SERVER_DOCKER_IP}:3000 -# working-directory: test + - name: Set config.conf to use Docker IP address of Aerospike server + # config.conf should be copied into the cibuildwheel Docker container + run: | + export SERVER_DOCKER_IP=$(docker container inspect -f '{{ .NetworkSettings.IPAddress }}' aerospike) + # Install crudini + pip install crudini -c ../.github/workflows/requirements.txt + sed -i "s/127.0.0.1:3000//" config.conf + crudini --set config.conf enterprise-edition hosts ${SERVER_DOCKER_IP}:3000 + working-directory: test - name: Enable tests run: echo "TEST_COMMAND=cd ts-test; diff --git a/README.md b/README.md index 0a630b9b..46cf8046 100644 --- a/README.md +++ b/README.md @@ -340,6 +340,10 @@ To run all the test cases: npm test +To run a specific tests, use: + + npm test --testfile=filename.js + Note: make sure your server has TTL enabled for the `test` namespace ([Namespace Retention Configuration](https://docs.aerospike.com/server/operations/configure/namespace/retention)) to allow all tests to run correctly. To run the tests and also report on test coverage: diff --git a/aerospike-client-c b/aerospike-client-c index 9cfb73bf..22525aad 160000 --- a/aerospike-client-c +++ b/aerospike-client-c @@ -1 +1 @@ -Subproject commit 9cfb73bf539de5db7158fe0021bc3d9fb25289d2 +Subproject commit 22525aad6daa10c1491175bd0b2bc301a70997c9 diff --git a/binding.gyp b/binding.gyp index cebead72..3574fdab 100644 --- a/binding.gyp +++ b/binding.gyp @@ -67,6 +67,7 @@ 'sources': [ 'src/main/aerospike.cc', 'src/main/client.cc', + 'src/main/transaction.cc', 'src/main/config.cc', 'src/main/events.cc', 'src/main/cdt_ctx.cc', @@ -125,11 +126,17 @@ 'src/main/commands/scan_background.cc', 'src/main/commands/scan_pages.cc', 'src/main/commands/select_async.cc', + 'src/main/commands/transaction_abort.cc', + 'src/main/commands/transaction_commit.cc', 'src/main/commands/truncate.cc', 'src/main/commands/user_create.cc', 'src/main/commands/user_drop.cc', 'src/main/commands/udf_register.cc', 'src/main/commands/udf_remove.cc', + 'src/main/enums/abort_status.cc', + 'src/main/enums/commit_status.cc', + 'src/main/enums/txn_state.cc', + 'src/main/enums/txn_capacity.cc', 'src/main/enums/predicates.cc', 'src/main/enums/bitwise_enum.cc', 'src/main/enums/hll_enum.cc', diff --git a/examples/mrtAbort.js b/examples/mrtAbort.js new file mode 100644 index 00000000..0fbc2fa0 --- /dev/null +++ b/examples/mrtAbort.js @@ -0,0 +1,58 @@ +#!/usr/bin/env node +// ***************************************************************************** +// Copyright 2013-2024 Aerospike, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License") +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ***************************************************************************** +// +const Aerospike = require('aerospike') +const shared = require('./shared') + +shared.runner() + +async function mrtAbort (client, argv) { + // sconst record1 = { abc: 123 } + const record2 = { def: 456 } + + const mrt = new Aerospike.Transaction() + + const policy = { + txn: mrt + } + const keyList = [] + for (let i = 0; i < argv.keys.length; i++) { + keyList.push(new Aerospike.Key(argv.namespace, argv.set, argv.keys[i])) + } + + for (let i = 0; i < keyList.length; i++) { + await client.put(keyList[i], record2, policy) + await client.get(keyList[i], policy) + } + + console.log(keyList) + + console.log('aborting multi-record transaction with %d operations.', keyList.length * 2) + await client.abort(mrt) + console.info('multi-record transaction has been aborted.') +} + +exports.command = 'mrtAbort ' +exports.describe = 'Abort a multi-record transaction' +exports.handler = shared.run(mrtAbort) +exports.builder = { + keys: { + desc: 'Provide keys for the records in the multi-record transaction', + type: 'array', + group: 'Command:' + } +} diff --git a/examples/mrtCommit.js b/examples/mrtCommit.js new file mode 100644 index 00000000..99f190ef --- /dev/null +++ b/examples/mrtCommit.js @@ -0,0 +1,57 @@ +#!/usr/bin/env node +// ***************************************************************************** +// Copyright 2013-2024 Aerospike, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License") +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ***************************************************************************** +// +const Aerospike = require('aerospike') +const shared = require('./shared') + +shared.runner() + +async function mrtCommit (client, argv) { + // const record1 = { abc: 123 } + const record2 = { def: 456 } + + const mrt = new Aerospike.Transaction() + + const policy = { + txn: mrt + } + const keyList = [] + for (let i = 0; i < argv.keys.length; i++) { + keyList.push(new Aerospike.Key(argv.namespace, argv.set, argv.keys[i])) + } + for (let i = 0; i < argv.keys.length; i++) { + await client.put(keyList[i], record2, policy) + await client.get(keyList[i], policy) + } + + console.log(keyList) + + console.log('committing multi-record transaction with %d operations.', keyList.length * 2) + await client.commit(mrt) + console.info('multi-record transaction has been committed.') +} + +exports.command = 'mrtCommit ' +exports.describe = 'Commit a multi-record transaction' +exports.handler = shared.run(mrtCommit) +exports.builder = { + keys: { + desc: 'Provide keys for the records in the multi-record transaction', + type: 'array', + group: 'Command:' + } +} diff --git a/examples/run.js b/examples/run.js index 9264e7f6..2f17f9ad 100755 --- a/examples/run.js +++ b/examples/run.js @@ -28,6 +28,8 @@ const commands = [ 'geospatialMonteCarlo', 'get', 'info', + 'mrtAbort', + 'mrtCommit', 'operate', 'put', 'query', diff --git a/lib/abort_status.js b/lib/abort_status.js new file mode 100644 index 00000000..a647ef1e --- /dev/null +++ b/lib/abort_status.js @@ -0,0 +1,28 @@ +// ***************************************************************************** +// Copyright 2024 Aerospike, Inc. +// +// Licensed under the Apache License, Version 2.0 (the 'License') +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an 'AS IS' BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ***************************************************************************** + +'use strict' + +const as = require('bindings')('aerospike.node') +const abortStatus = as.abortStatus + +module.exports = { + OK: abortStatus.OK, + ALREADY_COMMITTED: abortStatus.ALREADY_COMMITTED, + ALREADY_ABORTED: abortStatus.ALREADY_ABORTED, + ROLL_BACK_ABANDONED: abortStatus.ROLL_BACK_ABANDONED, + CLOSE_ABANDONED: abortStatus.CLOSE_ABANDONED +} diff --git a/lib/aerospike.js b/lib/aerospike.js index a251be7f..2b4f7659 100644 --- a/lib/aerospike.js +++ b/lib/aerospike.js @@ -19,7 +19,11 @@ const as = require('bindings')('aerospike.node') const AerospikeError = require('./error') const EventLoop = require('./event_loop') +const TransactionPool = require('./transaction_pool') +const _transactionPool = new TransactionPool() + +exports._transactionPool = _transactionPool /** * @module aerospike * @@ -238,6 +242,39 @@ exports.Config = require('./config') */ exports.Double = require('./double') +/** + * Multi-record transaction (MRT) class. All commands in the same MRT must use the same namespace. + * + * note: By default, open transactions are destroyed when the final client in a process is closed. + * If you need your transaction to persist after the last client has been closed, provide `false` for the + * destroy Transactions argument in {@link Client#close} (see example below). + * + * @example + * + * const Aerospike = require('aerospike') + * + * // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE! + * var config = { + * hosts: '192.168.33.10:3000', + * } + * Aerospike.connect(config) + * .then(client => { + * // client is ready to accept commands + * console.log("Connected. Now Closing Connection.") + * client.close() + * }) + * .catch(error => { + * client.close( + * false, // do not release the event loop + * false // do not destroy open transactions + * ) + * console.error('Failed to connect to cluster: %s', error.message) + * }) + * + * @summary {@link Transaction} class + */ +exports.Transaction = require('./transaction') + /** * Representation of a GeoJSON value. Since GeoJSON values are JSON objects * they need to be wrapped in the {@link GeoJSON} class so that the client can @@ -701,6 +738,22 @@ exports.setupGlobalCommandQueue = function (policy) { */ exports.batchType = require('./batch_type') +/** + * The {@link module:aerospike/commit_status|aerospike/commit_status} + * module contains a list of commit statuses. + * + * @summary {@link module:aerospike/commit_status|aerospike/commit_status} module + */ +exports.commitStatus = require('./commit_status') + +/** + * The {@link module:aerospike/abortStatus|aerospike/abort_status} + * module contains a list of abort statuses. + * + * @summary {@link module:aerospike/abortStatus|aerospike/abort_status} module + */ +exports.abortStatus = require('./abort_status') + /** * The {@link module:aerospike/privilegeCode|aerospike/privilege_code} * module is comprised of permission codes which define the type of diff --git a/lib/client.js b/lib/client.js index 5420839d..c5c4b736 100644 --- a/lib/client.js +++ b/lib/client.js @@ -22,6 +22,10 @@ const EventEmitter = require('events') const as = require('bindings')('aerospike.node') const AerospikeError = require('./error') +const abortStatus = require('./abort_status') +const commitStatus = require('./commit_status') +const txnState = require('./txn_state') +const Transaction = require('./transaction') const Context = require('./cdt_context') const Commands = require('./commands') const Config = require('./config') @@ -35,6 +39,7 @@ const utils = require('./utils') // number of client instances currently connected to any Aerospike cluster let _connectedClients = 0 +const { _transactionPool } = require('./aerospike') // callback function for cluster events (node added/removed, etc.) function eventsCallback (event) { @@ -211,6 +216,40 @@ Client.prototype.getNodes = function () { return this.as_client.getNodes() } +Client.prototype.abort = function (transaction, callback) { + _transactionPool.tendTransactions() + if (transaction instanceof Transaction) { + if (transaction.getState() === txnState.COMMITTED) { + return abortStatus.ALREADY_COMMITTED + } else if (transaction.getState() === txnState.ABORTED) { + return abortStatus.ALREADY_ABORTED + } else if (transaction.getDestroyed() === true) { + throw new AerospikeError('The object has been destroyed, please create a new transaction.') + } + } else { + throw new AerospikeError('transaction must be an instance of class Transaction.') + } + const cmd = new Commands.TransactionAbort(this, [transaction.transaction], callback) + return cmd.execute() +} + +Client.prototype.commit = function (transaction, callback) { + _transactionPool.tendTransactions() + if (transaction instanceof Transaction) { + if (transaction.getState() === txnState.COMMITTED) { + return commitStatus.ALREADY_COMMITTED + } else if (transaction.getState() === txnState.ABORTED) { + return commitStatus.ALREADY_ABORTED + } else if (transaction.getDestroyed() === true) { + throw new AerospikeError('The object has been destroyed, please create a new transaction.') + } + } else { + throw new AerospikeError('transaction must be an instance of class Transaction.') + } + const cmd = new Commands.TransactionCommit(this, [transaction.transaction], callback) + return cmd.execute() +} + /** * @function Client#contextToBase64 * @@ -1711,7 +1750,8 @@ Client.prototype.batchSelect = function (keys, bins, policy, callback) { * * @summary Closes the client connection to the cluster. * - * @param {boolean} [releaseEventLoop=false] - Whether to release the event loop handle after the client is closed. + * @param {boolean} [releaseEventLoop=false] - Whether to release the event loop handle after the last client is closed. + * @param {boolean} [destroyTransactions=true] - Whether to destroy any open transactions after the last client is closed. * * @see module:aerospike.releaseEventLoop * @@ -1734,13 +1774,16 @@ Client.prototype.batchSelect = function (keys, bins, policy, callback) { * console.error('Failed to connect to cluster: %s', error.message) * }) */ -Client.prototype.close = function (releaseEventLoop = false) { +Client.prototype.close = function (releaseEventLoop = false, destroyTransactions = true) { if (this.isConnected(false)) { this.connected = false this.as_client.close() _connectedClients -= 1 } if (_connectedClients === 0) { + if (destroyTransactions) { + _transactionPool.removeAllTransactions() + } if (releaseEventLoop) { EventLoop.releaseEventLoop() } else { diff --git a/lib/commands/index.js b/lib/commands/index.js index 7bba184f..fc83ba94 100644 --- a/lib/commands/index.js +++ b/lib/commands/index.js @@ -70,6 +70,8 @@ exports.ScanPages = class ScanPagesCommand extends StreamCommand('scanPages') { exports.ScanBackground = class ScanBackgroundCommand extends QueryBackgroundBaseCommand('scanBackground') { } exports.ScanOperate = class ScanOperateCommand extends QueryBackgroundBaseCommand('scanBackground') { } exports.Select = class SelectCommand extends ReadRecordCommand('selectAsync') { } +exports.TransactionAbort = class TransactionAbortCommand extends Command('transactionAbort') { } +exports.TransactionCommit = class TransactionCommitCommand extends Command('transactionCommit') { } exports.Truncate = class TruncateCommand extends Command('truncate') { } exports.UdfRegister = class UdfRegisterCommand extends Command('udfRegister') { } exports.UdfRemove = class UdfRemoveCommand extends Command('udfRemove') { } diff --git a/lib/commit_status.js b/lib/commit_status.js new file mode 100644 index 00000000..5c39a528 --- /dev/null +++ b/lib/commit_status.js @@ -0,0 +1,30 @@ +// ***************************************************************************** +// Copyright 2024 Aerospike, Inc. +// +// Licensed under the Apache License, Version 2.0 (the 'License') +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an 'AS IS' BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ***************************************************************************** + +'use strict' + +const as = require('bindings')('aerospike.node') +const commitStatus = as.commitStatus + +module.exports = { + OK: commitStatus.OK, + ALREADY_COMMITTED: commitStatus.ALREADY_COMMITTED, + ALREADY_ABORTED: commitStatus.ALREADY_ABORTED, + VERIFY_FAILED: commitStatus.VERIFY_FAILED, + MARK_ROLL_FORWARD_ABANDONED: commitStatus.MARK_ROLL_FORWARD_ABANDONED, + ROLL_FORWARD_ABANDONED: commitStatus.ROLL_FORWARD_ABANDONED, + CLOSE_ABANDONED: commitStatus.CLOSE_ABANDONED +} diff --git a/lib/policies/base_policy.js b/lib/policies/base_policy.js index 60d6b5c1..b6483ff6 100644 --- a/lib/policies/base_policy.js +++ b/lib/policies/base_policy.js @@ -121,6 +121,8 @@ class BasePolicy { * @since v3.14.0 */ this.compress = props.compress + + this.txn = props.txn } } diff --git a/lib/status.js b/lib/status.js index 7702001b..82e6beec 100644 --- a/lib/status.js +++ b/lib/status.js @@ -24,6 +24,12 @@ const as = require('bindings')('aerospike.node') * @description Database operation error codes. */ +/** + * Multi-record transaction failed. + * @const {number} + */ +exports.TXN_FAILED = exports.AEROSPIKE_TXN_FAILED = as.status.AEROSPIKE_TXN_FAILED + /** * One or more keys failed in a batch. * @const {number} @@ -303,6 +309,8 @@ exports.FILTERED_OUT = exports.AEROSPIKE_FILTERED_OUT = as.status.AEROSPIKE_FILT */ exports.LOST_CONFLICT = exports.AEROSPIKE_LOST_CONFLICT = as.status.AEROSPIKE_LOST_CONFLICT +exports.XDR_KEY_BUSY = exports.AEROSPIKE_XDR_KEY_BUSY = as.status.AEROSPIKE_XDR_KEY_BUSY + /** * There are no more records left for query. * @const {number} @@ -441,6 +449,13 @@ exports.ROLE_VIOLATION = exports.AEROSPIKE_ROLE_VIOLATION = as.status.AEROSPIKE_ */ exports.ERR_UDF = exports.AEROSPIKE_ERR_UDF = as.status.AEROSPIKE_ERR_UDF +exports.MRT_BLOCKED = exports.AEROSPIKE_MRT_BLOCKED = as.status.AEROSPIKE_MRT_BLOCKED +exports.MRT_VERSION_MISMATCH = exports.AEROSPIKE_MRT_VERSION_MISMATCH = as.status.AEROSPIKE_MRT_VERSION_MISMATCH +exports.MRT_EXPIRED = exports.AEROSPIKE_MRT_EXPIRED = as.status.AEROSPIKE_MRT_EXPIRED +exports.MRT_TOO_MANY_WRITES = exports.AEROSPIKE_MRT_TOO_MANY_WRITES = as.status.AEROSPIKE_MRT_TOO_MANY_WRITES +exports.MRT_COMMITTED = exports.AEROSPIKE_MRT_COMMITTED = as.status.AEROSPIKE_MRT_COMMITTED +exports.MRT_ABORTED = exports.AEROSPIKE_MRT_ABORTED = as.status.AEROSPIKE_MRT_ABORTED + /** * Batch functionality has been disabled. * @const {number} @@ -553,6 +568,9 @@ exports.ERR_LUA_FILE_NOT_FOUND = exports.AEROSPIKE_ERR_LUA_FILE_NOT_FOUND = as.s exports.getMessage = function (code) { /* istanbul ignore next */ switch (code) { + case exports.TXN_FAILED: + return 'Multi-record transaction failed.' + case exports.ERR_INVALID_NODE: return 'Node invalid or could not be found.' @@ -727,6 +745,24 @@ exports.getMessage = function (code) { case exports.ERR_UDF: return 'Generic UDF error.' + case exports.MRT_BLOCKED: + return 'MRT record blocked by a different transaction.' + + case exports.MRT_VERSION_MISMATCH: + return 'MRT read version mismatch identified during commit. Some other command changed the record outside of the transaction.' + + case exports.MRT_EXPIRED: + return 'MRT deadline reached without a successful commit or abort.' + + case exports.MRT_TOO_MANY_WRITES: + return 'MRT write command limit (4096) exceeded.' + + case exports.MRT_COMMITTED: + return 'MRT was already committed.' + + case exports.MRT_ABORTED: + return 'MRT was already aborted.' + case exports.ERR_BATCH_DISABLED: return 'Batch functionality has been disabled.' diff --git a/lib/transaction.js b/lib/transaction.js new file mode 100644 index 00000000..2c9837b2 --- /dev/null +++ b/lib/transaction.js @@ -0,0 +1,161 @@ +// ***************************************************************************** +// Copyright 2013-2024 Aerospike, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License") +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ***************************************************************************** + +'use strict' + +const as = require('bindings')('aerospike.node') + +const capacity = require('./txn_capacity') +const state = require('./txn_state') +const abortStatus = require('./abort_status') +const commitStatus = require('./commit_status') + +const AerospikeError = require('./error') + +const { _transactionPool } = require('./aerospike') + +const UINT32_MAX = 0xFFFFFFFF + +function isValidUint32 (value) { + return value >= 0 && value <= UINT32_MAX +} + +class Transaction { + static state = state + static capacity = capacity + static abortStatus = abortStatus + static commitStatus = commitStatus + + constructor (readsCapacity = capacity.READ_DEFAULT, writesCapacity = capacity.WRITE_DEFAULT) { + /** @private */ + this.inDoubt = null + /** @private */ + this.pooled = false + /** @private */ + this.state = null + /** @private */ + this.timeout = null + /** @private */ + this.destroyed = false + + if (Number.isInteger(readsCapacity)) { + if (Number.isInteger(writesCapacity)) { + if (isValidUint32(readsCapacity)) { + if (isValidUint32(writesCapacity)) { + /** @private */ + this.readsCapacity = readsCapacity + /** @private */ + this.writesCapacity = writesCapacity + + _transactionPool.pushTransaction(this) + this.transaction = as.transaction({ readsCapacity, writesCapacity }) + } else { + throw new RangeError('writesCapacity is out of uint32 range') + } + } else if (isValidUint32(writesCapacity)) { + throw new RangeError('readsCapacity is out of uint32 range') + } else { + throw new RangeError('both readsCapacity and writesCapacity are out of uint32 range') + } + } else { + throw new TypeError('Must specify a number for writesCapacity') + } + } else if (Number.isInteger(writesCapacity)) { + throw new TypeError('Must specify a number for readsCapacity') + } else { + /** @private */ + this.readsCapacity = readsCapacity + /** @private */ + this.writesCapacity = writesCapacity + + _transactionPool.pushTransaction(this) + this.transaction = as.transaction({}) + } + + /** @private */ + this.id = this.transaction.getId() + } + + /* getters */ + + getDestroyed () { + return this.destroyed + } + + getId () { + return this.id + } + + getInDoubt () { + if (this.destroyed) { + return this.inDoubt + } + return this.transaction.getInDoubt() + } + + getReadsCapacity () { + return this.readsCapacity + } + + getState () { + if (this.destroyed) { + return this.state + } + return this.transaction.getState() + } + + getTimeout () { + if (this.destroyed) { + return this.timeout + } + return this.transaction.getTimeout() + } + + getWritesCapacity () { + return this.writesCapacity + } + + /* setters */ + setTimeout (timeout) { + if (this.destroyed) { + throw new AerospikeError('Transaction is already complete') + } + return this.transaction.setTimeout(timeout) + } + + /** @private */ + prepareToClose () { + this.timeout = this.transaction.getTimeout() + this.inDoubt = this.transaction.getInDoubt() + this.state = this.transaction.getState() + _transactionPool.totalReadsAndWrites -= (this.writesCapacity + this.readsCapacity) + this.destroyed = true + } + + /** @private */ + close () { + if (this.destroyed === false) { + this.prepareToClose() + this.transaction.close() + } + } + + destroyAll () { + _transactionPool.removeAllTransactions() + } +} + +module.exports = Transaction diff --git a/lib/transaction_pool.js b/lib/transaction_pool.js new file mode 100644 index 00000000..600f164b --- /dev/null +++ b/lib/transaction_pool.js @@ -0,0 +1,106 @@ +// ***************************************************************************** +// Copyright 2024 Aerospike, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License") +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ***************************************************************************** + +'use strict' + +const txnState = require('./txn_state') + +// This is an arbitary limit provide to safe-guard against accidental over allocation by the user. +// In general, this limit should be high enough that users should never hit this mark under typical use. +const readWriteLimit = 500_000 + +/* private */ +class TransactionPool { + constructor (capacity = 128) { + this.transactions = [] + this.capacity = capacity + this.totalReadsAndWrites = 0 + } + + /* getters */ + getTransactions () { + return this.transactions + } + + getCapacity () { + return this.capacity + } + + getLength () { + return this.transactions.length + } + + pushTransaction (transaction) { + if (this.totalReadsAndWrites > readWriteLimit) { + this.tendTransactions() + if (this.totalReadsAndWrites > readWriteLimit) { + throw new RangeError('Maximum capacity for Multi-record transactions has been reached. Avoid setting readsCapacity and writesCapacity too high, and abort/commit open transactions so memory can be cleaned up and reused.') + } + } else { + this.totalReadsAndWrites += (transaction.getReadsCapacity() + transaction.getWritesCapacity()) + this.transactions.push(transaction) + } + } + + resetTransactions () { + this.transactions = [] + } + + increaseCapacity () { + this.capacity *= 2 + } + + removeTransactions (indices) { + for (const index of indices) { + if (index >= 0 && index < this.transactions.length) { + this.transactions.splice(index, 1) + } + } + } + + removeAllTransactions () { + for (const transaction of this.getTransactions()) { + transaction.close() + } + this.resetTransactions() + } + + /** + * Algorithm used to cleanup memory from completed transactions. + */ + tendTransactions () { + if (this.getLength() > this.getCapacity()) { + const indicesToDelete = [] + + for (let i = 0; i < this.getLength(); i++) { + const transaction = this.getTransactions()[i] + const state = transaction.getState() + if ((state === txnState.COMMITTED) || (state === txnState.ABORTED)) { + transaction.close() + indicesToDelete.unshift(i) + } + } + + this.removeTransactions(indicesToDelete) + + if (this.getLength() > this.getCapacity()) { + this.increaseCapacity() + } + } + } +} + +module.exports = TransactionPool diff --git a/lib/txn_capacity.js b/lib/txn_capacity.js new file mode 100644 index 00000000..13c79203 --- /dev/null +++ b/lib/txn_capacity.js @@ -0,0 +1,25 @@ +// ***************************************************************************** +// Copyright 2024 Aerospike, Inc. +// +// Licensed under the Apache License, Version 2.0 (the 'License') +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an 'AS IS' BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ***************************************************************************** + +'use strict' + +const as = require('bindings')('aerospike.node') +const capacity = as.txnCapacity + +module.exports = { + READ_DEFAULT: capacity.READ_DEFAULT, + WRITE_DEFAULT: capacity.WRITE_DEFAULT +} diff --git a/lib/txn_state.js b/lib/txn_state.js new file mode 100644 index 00000000..a9326679 --- /dev/null +++ b/lib/txn_state.js @@ -0,0 +1,27 @@ +// ***************************************************************************** +// Copyright 2024 Aerospike, Inc. +// +// Licensed under the Apache License, Version 2.0 (the 'License') +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an 'AS IS' BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ***************************************************************************** + +'use strict' + +const as = require('bindings')('aerospike.node') +const state = as.txnState + +module.exports = { + OK: state.OPEN, + VERIFIED: state.VERIFIED, + COMMITTED: state.COMMITTED, + ABORTED: state.ABORTED +} diff --git a/package-lock.json b/package-lock.json index 98eb763a..b96ea974 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "aerospike", - "version": "5.13.2", + "version": "6.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "aerospike", - "version": "5.13.2", + "version": "6.0.1", "cpu": [ "x64", "arm64" @@ -82,9 +82,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", - "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.3.tgz", + "integrity": "sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==", "dev": true, "engines": { "node": ">=6.9.0" @@ -136,13 +136,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", - "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", + "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", "dev": true, "dependencies": { - "@babel/parser": "^7.26.2", - "@babel/types": "^7.26.0", + "@babel/parser": "^7.26.3", + "@babel/types": "^7.26.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -262,12 +262,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", - "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", + "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", "dev": true, "dependencies": { - "@babel/types": "^7.26.0" + "@babel/types": "^7.26.3" }, "bin": { "parser": "bin/babel-parser.js" @@ -291,16 +291,16 @@ } }, "node_modules/@babel/traverse": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", - "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "version": "7.26.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz", + "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/parser": "^7.25.9", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.3", + "@babel/parser": "^7.26.3", "@babel/template": "^7.25.9", - "@babel/types": "^7.25.9", + "@babel/types": "^7.26.3", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -318,9 +318,9 @@ } }, "node_modules/@babel/types": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", - "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", + "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.25.9", @@ -426,9 +426,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", - "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz", + "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -645,9 +645,9 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dev": true, "dependencies": { "@jridgewell/set-array": "^1.2.1", @@ -763,22 +763,19 @@ } }, "node_modules/@npmcli/agent/node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dependencies": { - "debug": "^4.3.4" - }, + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "engines": { "node": ">= 14" } }, "node_modules/@npmcli/agent/node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { @@ -812,54 +809,54 @@ "dev": true }, "node_modules/@shikijs/core": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.2.tgz", - "integrity": "sha512-bvIQcd8BEeR1yFvOYv6HDiyta2FFVePbzeowf5pPS1avczrPK+cjmaxxh0nx5QzbON7+Sv0sQfQVciO7bN72sg==", + "version": "1.24.4", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.24.4.tgz", + "integrity": "sha512-jjLsld+xEEGYlxAXDyGwWsKJ1sw5Pc1pnp4ai2ORpjx2UX08YYTC0NNqQYO1PaghYaR+PvgMOGuvzw2he9sk0Q==", "dev": true, "dependencies": { - "@shikijs/engine-javascript": "1.22.2", - "@shikijs/engine-oniguruma": "1.22.2", - "@shikijs/types": "1.22.2", - "@shikijs/vscode-textmate": "^9.3.0", + "@shikijs/engine-javascript": "1.24.4", + "@shikijs/engine-oniguruma": "1.24.4", + "@shikijs/types": "1.24.4", + "@shikijs/vscode-textmate": "^9.3.1", "@types/hast": "^3.0.4", - "hast-util-to-html": "^9.0.3" + "hast-util-to-html": "^9.0.4" } }, "node_modules/@shikijs/engine-javascript": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.2.tgz", - "integrity": "sha512-iOvql09ql6m+3d1vtvP8fLCVCK7BQD1pJFmHIECsujB0V32BJ0Ab6hxk1ewVSMFA58FI0pR2Had9BKZdyQrxTw==", + "version": "1.24.4", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.24.4.tgz", + "integrity": "sha512-TClaQOLvo9WEMJv6GoUsykQ6QdynuKszuORFWCke8qvi6PeLm7FcD9+7y45UenysxEWYpDL5KJaVXTngTE+2BA==", "dev": true, "dependencies": { - "@shikijs/types": "1.22.2", - "@shikijs/vscode-textmate": "^9.3.0", - "oniguruma-to-js": "0.4.3" + "@shikijs/types": "1.24.4", + "@shikijs/vscode-textmate": "^9.3.1", + "oniguruma-to-es": "0.8.1" } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.2.tgz", - "integrity": "sha512-GIZPAGzQOy56mGvWMoZRPggn0dTlBf1gutV5TdceLCZlFNqWmuc7u+CzD0Gd9vQUTgLbrt0KLzz6FNprqYAxlA==", + "version": "1.24.4", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.24.4.tgz", + "integrity": "sha512-Do2ry6flp2HWdvpj2XOwwa0ljZBRy15HKZITzPcNIBOGSeprnA8gOooA/bLsSPuy8aJBa+Q/r34dMmC3KNL/zw==", "dev": true, "dependencies": { - "@shikijs/types": "1.22.2", - "@shikijs/vscode-textmate": "^9.3.0" + "@shikijs/types": "1.24.4", + "@shikijs/vscode-textmate": "^9.3.1" } }, "node_modules/@shikijs/types": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.2.tgz", - "integrity": "sha512-NCWDa6LGZqTuzjsGfXOBWfjS/fDIbDdmVDug+7ykVe1IKT4c1gakrvlfFYp5NhAXH/lyqLM8wsAPo5wNy73Feg==", + "version": "1.24.4", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.24.4.tgz", + "integrity": "sha512-0r0XU7Eaow0PuDxuWC1bVqmWCgm3XqizIaT7SM42K03vc69LGooT0U8ccSR44xP/hGlNx4FKhtYpV+BU6aaKAA==", "dev": true, "dependencies": { - "@shikijs/vscode-textmate": "^9.3.0", + "@shikijs/vscode-textmate": "^9.3.1", "@types/hast": "^3.0.4" } }, "node_modules/@shikijs/vscode-textmate": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz", - "integrity": "sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==", + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.3.1.tgz", + "integrity": "sha512-79QfK1393x9Ho60QFyLti+QfdJzRQCVLFb97kOIV7Eo9vQU/roINgk7m24uv0a7AUvN//RDH36FLjjK48v0s9g==", "dev": true }, "node_modules/@tootallnate/once": { @@ -896,12 +893,12 @@ } }, "node_modules/@types/node": { - "version": "22.8.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.6.tgz", - "integrity": "sha512-tosuJYKrIqjQIlVCM4PEGxOmyg3FCPa/fViuJChnGeEIhjA46oy8FMVoF9su1/v8PNs2a8Q0iFNyOx0uOF91nw==", + "version": "22.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", + "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", "dev": true, "dependencies": { - "undici-types": "~6.19.8" + "undici-types": "~6.20.0" } }, "node_modules/@types/unist": { @@ -911,16 +908,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.12.2.tgz", - "integrity": "sha512-gQxbxM8mcxBwaEmWdtLCIGLfixBMHhQjBqR8sVWNTPpcj45WlYL2IObS/DNMLH1DBP0n8qz+aiiLTGfopPEebw==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.0.tgz", + "integrity": "sha512-NggSaEZCdSrFddbctrVjkVZvFC6KGfKfNK0CU7mNK/iKHGKbzT4Wmgm08dKpcZECBu9f5FypndoMyRHkdqfT1Q==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.12.2", - "@typescript-eslint/type-utils": "8.12.2", - "@typescript-eslint/utils": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2", + "@typescript-eslint/scope-manager": "8.19.0", + "@typescript-eslint/type-utils": "8.19.0", + "@typescript-eslint/utils": "8.19.0", + "@typescript-eslint/visitor-keys": "8.19.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -935,24 +932,20 @@ }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.12.2.tgz", - "integrity": "sha512-MrvlXNfGPLH3Z+r7Tk+Z5moZAc0dzdVjTgUgwsdGweH7lydysQsnSww3nAmsq8blFuRD5VRlAr9YdEFw3e6PBw==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.19.0.tgz", + "integrity": "sha512-6M8taKyOETY1TKHp0x8ndycipTVgmp4xtg5QpEZzXxDhNvvHOJi5rLRkLr8SK3jTgD5l4fTlvBiRdfsuWydxBw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.12.2", - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/typescript-estree": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2", + "@typescript-eslint/scope-manager": "8.19.0", + "@typescript-eslint/types": "8.19.0", + "@typescript-eslint/typescript-estree": "8.19.0", + "@typescript-eslint/visitor-keys": "8.19.0", "debug": "^4.3.4" }, "engines": { @@ -963,22 +956,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.12.2.tgz", - "integrity": "sha512-gPLpLtrj9aMHOvxJkSbDBmbRuYdtiEbnvO25bCMza3DhMjTQw0u7Y1M+YR5JPbMsXXnSPuCf5hfq0nEkQDL/JQ==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.19.0.tgz", + "integrity": "sha512-hkoJiKQS3GQ13TSMEiuNmSCvhz7ujyqD1x3ShbaETATHrck+9RaDdUbt+osXaUuns9OFwrDTTrjtwsU8gJyyRA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2" + "@typescript-eslint/types": "8.19.0", + "@typescript-eslint/visitor-keys": "8.19.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -989,13 +978,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.12.2.tgz", - "integrity": "sha512-bwuU4TAogPI+1q/IJSKuD4shBLc/d2vGcRT588q+jzayQyjVK2X6v/fbR4InY2U2sgf8MEvVCqEWUzYzgBNcGQ==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.19.0.tgz", + "integrity": "sha512-TZs0I0OSbd5Aza4qAMpp1cdCYVnER94IziudE3JU328YUHgWu9gwiwhag+fuLeJ2LkWLXI+F/182TbG+JaBdTg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.12.2", - "@typescript-eslint/utils": "8.12.2", + "@typescript-eslint/typescript-estree": "8.19.0", + "@typescript-eslint/utils": "8.19.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1006,16 +995,15 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.12.2.tgz", - "integrity": "sha512-VwDwMF1SZ7wPBUZwmMdnDJ6sIFk4K4s+ALKLP6aIQsISkPv8jhiw65sAK6SuWODN/ix+m+HgbYDkH+zLjrzvOA==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.0.tgz", + "integrity": "sha512-8XQ4Ss7G9WX8oaYvD4OOLCjIQYgRQxO+qCiR2V2s2GxI9AUpo7riNwo6jDhKtTcaJjT8PY54j2Yb33kWtSJsmA==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1026,13 +1014,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.2.tgz", - "integrity": "sha512-mME5MDwGe30Pq9zKPvyduyU86PH7aixwqYR2grTglAdB+AN8xXQ1vFGpYaUSJ5o5P/5znsSBeNcs5g5/2aQwow==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.0.tgz", + "integrity": "sha512-WW9PpDaLIFW9LCbucMSdYUuGeFUz1OkWYS/5fwZwTA+l2RwlWFdJvReQqMUMBw4yJWJOfqd7An9uwut2Oj8sLw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2", + "@typescript-eslint/types": "8.19.0", + "@typescript-eslint/visitor-keys": "8.19.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1047,10 +1035,8 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { @@ -1078,15 +1064,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.12.2.tgz", - "integrity": "sha512-UTTuDIX3fkfAz6iSVa5rTuSfWIYZ6ATtEocQ/umkRSyC9O919lbZ8dcH7mysshrCdrAM03skJOEYaBugxN+M6A==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.19.0.tgz", + "integrity": "sha512-PTBG+0oEMPH9jCZlfg07LCB2nYI0I317yyvXGfxnvGvw4SHIOuRnQ3kadyyXY6tGdChusIHIbM5zfIbp4M6tCg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.12.2", - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/typescript-estree": "8.12.2" + "@typescript-eslint/scope-manager": "8.19.0", + "@typescript-eslint/types": "8.19.0", + "@typescript-eslint/typescript-estree": "8.19.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1096,17 +1082,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.2.tgz", - "integrity": "sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.0.tgz", + "integrity": "sha512-mCFtBbFBJDCNCWUl5y6sZSCHXw1DEFEk3c/M3nRK2a4XUB8StGFtmcEMizdjKuBzB6e/smJAAWYug3VrdLMr1w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.12.2", - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/types": "8.19.0", + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1116,10 +1103,22 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.1.tgz", + "integrity": "sha512-fEzPV3hSkSMltkw152tJKNARhOupqbH96MZWyRjNaYZOMIzbrTeQDG+MTc6Mr2pgzFQzFxAfmhGDNP5QK++2ZA==", "dev": true }, "node_modules/abbrev": { @@ -1287,12 +1286,12 @@ } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" }, "engines": { "node": ">= 0.4" @@ -1362,15 +1361,15 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -1380,15 +1379,15 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -1414,18 +1413,17 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dependencies": { "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { "node": ">= 0.4" @@ -1510,9 +1508,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.24.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", - "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", + "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", "dev": true, "funding": [ { @@ -1529,9 +1527,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", - "node-releases": "^2.0.18", + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { @@ -1655,15 +1653,41 @@ } }, "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dependencies": { + "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -1691,9 +1715,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001676", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001676.tgz", - "integrity": "sha512-Qz6zwGCiPghQXGJvgQAem79esjitvJ+CxSbSQkW9H/UX5hg8XM88d4lp2W+MEQ81j+Hip58Il+jGVdazk1z9cw==", + "version": "1.0.30001690", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", + "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==", "dev": true, "funding": [ { @@ -1938,9 +1962,9 @@ "dev": true }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1951,13 +1975,13 @@ } }, "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -1967,27 +1991,27 @@ } }, "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/inspect-js" } }, "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" }, @@ -1999,9 +2023,9 @@ } }, "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dependencies": { "ms": "^2.1.3" }, @@ -2146,15 +2170,28 @@ "node": ">=6.0.0" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/electron-to-chromium": { - "version": "1.5.50", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.50.tgz", - "integrity": "sha512-eMVObiUQ2LdgeO1F/ySTXsvqvxb6ZH2zPGaMYsWzRDdOddUa77tdmI0ltg+L16UpbWdhPmuF3wIQYyQq65WfZw==", + "version": "1.5.76", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.76.tgz", + "integrity": "sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ==", "dev": true }, "node_modules/emoji-regex": { @@ -2162,6 +2199,12 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, + "node_modules/emoji-regex-xs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz", + "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==", + "dev": true + }, "node_modules/encoding": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", @@ -2205,56 +2248,59 @@ } }, "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "version": "1.23.8", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.8.tgz", + "integrity": "sha512-lfab8IzDn6EpI1ibZakcgS6WsfEBiB+43cuJo+wgylx1xKXf+Sp+YR3vFuQwC/u3sxYwV8Cxe3B0DpVUu/WiJQ==", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.2.6", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", + "is-data-view": "^1.0.2", + "is-regex": "^1.2.1", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.0", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.3", "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", + "object.assign": "^4.1.7", + "own-keys": "^1.0.0", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.18" }, "engines": { "node": ">= 0.4" @@ -2264,12 +2310,9 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "engines": { "node": ">= 0.4" } @@ -2283,25 +2326,27 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.1.0.tgz", - "integrity": "sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", + "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", + "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", + "get-intrinsic": "^1.2.6", "globalthis": "^1.0.4", + "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.3", - "safe-array-concat": "^1.1.2" + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.4", + "safe-array-concat": "^1.1.3" }, "engines": { "node": ">= 0.4" @@ -2341,13 +2386,13 @@ } }, "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { "node": ">= 0.4" @@ -2681,28 +2726,28 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.37.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", - "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", + "version": "7.37.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.3.tgz", + "integrity": "sha512-DomWuTQPFYZwF/7c9W2fkKkStqZmBd3uugfqBYLdkZ3Hii23WzZuOLUskGxB8qkSKqftxEeGL1TB2kMhrce0jA==", "dev": true, "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.2", + "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.1.0", + "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.8", "object.fromentries": "^2.0.8", - "object.values": "^1.2.0", + "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.11", + "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "engines": { @@ -3080,9 +3125,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", + "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -3174,9 +3219,9 @@ } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", "dev": true }, "node_modules/for-each": { @@ -3260,14 +3305,16 @@ } }, "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" }, "engines": { "node": ">= 0.4" @@ -3333,15 +3380,20 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", + "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "dunder-proto": "^1.0.0", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -3372,13 +3424,13 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dependencies": { - "call-bind": "^1.0.5", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -3441,9 +3493,9 @@ } }, "node_modules/globals": { - "version": "15.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", - "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", + "version": "15.14.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz", + "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==", "dev": true, "engines": { "node": ">=18" @@ -3468,11 +3520,11 @@ } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3490,9 +3542,12 @@ "dev": true }, "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3517,9 +3572,12 @@ } }, "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dependencies": { + "dunder-proto": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -3528,9 +3586,9 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "engines": { "node": ">= 0.4" }, @@ -3586,9 +3644,9 @@ } }, "node_modules/hast-util-to-html": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz", - "integrity": "sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.4.tgz", + "integrity": "sha512-wxQzXtdbhiwGAUKrnQJXlOPmHnEehzphwkK7aluUPQ+lEc1xefC8pblMgpp2w5ldBTEfveRIrADcrhGIWrlTDA==", "dev": true, "dependencies": { "@types/hast": "^3.0.0", @@ -3669,12 +3727,9 @@ } }, "node_modules/http-proxy-agent/node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dependencies": { - "debug": "^4.3.4" - }, + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "engines": { "node": ">= 14" } @@ -3693,9 +3748,9 @@ } }, "node_modules/husky": { - "version": "9.1.6", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz", - "integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==", + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", "dev": true, "bin": { "husky": "bin.js" @@ -3787,13 +3842,13 @@ "dev": true }, "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dependencies": { "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -3817,12 +3872,13 @@ "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" }, "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -3840,7 +3896,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -3852,11 +3907,14 @@ } }, "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dependencies": { - "has-bigints": "^1.0.1" + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3875,12 +3933,12 @@ } }, "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz", + "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3901,9 +3959,9 @@ } }, "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dependencies": { "hasown": "^2.0.2" }, @@ -3915,10 +3973,12 @@ } }, "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" }, "engines": { @@ -3929,11 +3989,12 @@ } }, "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3952,12 +4013,14 @@ } }, "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "dev": true, + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3975,7 +4038,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -4007,18 +4069,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "engines": { "node": ">= 0.4" }, @@ -4036,11 +4086,12 @@ } }, "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -4068,12 +4119,14 @@ } }, "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -4086,7 +4139,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -4095,11 +4147,11 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dependencies": { - "call-bind": "^1.0.7" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -4121,11 +4173,12 @@ } }, "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -4135,11 +4188,13 @@ } }, "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dependencies": { - "has-symbols": "^1.0.2" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -4149,11 +4204,11 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dependencies": { - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -4184,7 +4239,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -4193,24 +4247,26 @@ } }, "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz", + "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==", "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-weakset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", - "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", - "dev": true, + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -4390,16 +4446,17 @@ } }, "node_modules/iterator.prototype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", - "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.4.tgz", + "integrity": "sha512-x4WH0BWmrMmg4oHHl+duwubhrvczGlyuGAZu3nvrf0UXOfPu8IhZObFEr7DE/iv01YgVZrsOiRcqw2srkKEDIA==", "dev": true, "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "reflect.getprototypeof": "^1.0.8", + "set-function-name": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -4444,9 +4501,9 @@ "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" }, "node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, "bin": { "jsesc": "bin/jsesc" @@ -4772,6 +4829,14 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mdast-util-to-hast": { "version": "13.2.0", "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", @@ -4817,9 +4882,9 @@ } }, "node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "dev": true, "funding": [ { @@ -4837,9 +4902,9 @@ } }, "node_modules/micromark-util-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", - "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", "dev": true, "funding": [ { @@ -4853,9 +4918,9 @@ ] }, "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", - "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", "dev": true, "funding": [ { @@ -4874,9 +4939,9 @@ } }, "node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "dev": true, "funding": [ { @@ -4890,9 +4955,9 @@ ] }, "node_modules/micromark-util-types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", - "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.1.tgz", + "integrity": "sha512-534m2WhVTddrcKVepwmVEVnUAmtrx9bfIjNoQHRqfnvdaHQiFytEhJoTgpWJvDEXCO5gLTQh3wYC1PgOJA4NSQ==", "dev": true, "funding": [ { @@ -5268,9 +5333,9 @@ } }, "node_modules/node-gyp": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.2.0.tgz", - "integrity": "sha512-sp3FonBAaFe4aYTcFdZUn2NYkbP7xroPGYvQmP4Nl5PxamznItBnNCgjrVTKrEfQynInMsJvZrdmqUnysCJ8rw==", + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.3.1.tgz", + "integrity": "sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ==", "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", @@ -5414,9 +5479,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true }, "node_modules/nopt": { @@ -5487,9 +5552,9 @@ } }, "node_modules/npm-run-all/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -5804,9 +5869,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", "engines": { "node": ">= 0.4" }, @@ -5823,13 +5888,15 @@ } }, "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" }, "engines": { @@ -5886,12 +5953,13 @@ } }, "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, @@ -5911,16 +5979,15 @@ "wrappy": "1" } }, - "node_modules/oniguruma-to-js": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz", - "integrity": "sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==", + "node_modules/oniguruma-to-es": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-0.8.1.tgz", + "integrity": "sha512-dekySTEvCxCj0IgKcA2uUCO/e4ArsqpucDPcX26w9ajx+DvMWLc5eZeJaRQkd7oC/+rwif5gnT900tA34uN9Zw==", "dev": true, "dependencies": { - "regex": "^4.3.2" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" + "emoji-regex-xs": "^1.0.0", + "regex": "^5.0.2", + "regex-recursion": "^5.0.0" } }, "node_modules/optionator": { @@ -5940,6 +6007,22 @@ "node": ">= 0.8.0" } }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -6356,9 +6439,9 @@ } }, "node_modules/process-on-spawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", - "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.1.0.tgz", + "integrity": "sha512-JOnOPQ/8TZgjs1JIH/m9ni7FfimjNa/PRx7y/Wb5qdItsnhO0jE4AT7fC0HjC28DUQWDr50dwSYZLdRMlqDq3Q==", "dev": true, "dependencies": { "fromentries": "^1.2.0" @@ -6493,18 +6576,18 @@ } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", - "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", - "dev": true, + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.9.tgz", + "integrity": "sha512-r0Ay04Snci87djAsI4U+WNRcSw5S4pOH7qFjd/veA5gC7TbqESR3tcj28ia95L/fYUDw11JKP7uqUKUAfVvV5Q==", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.23.1", + "dunder-proto": "^1.0.1", + "es-abstract": "^1.23.6", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "which-builtin-type": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -6514,9 +6597,28 @@ } }, "node_modules/regex": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/regex/-/regex-4.4.0.tgz", - "integrity": "sha512-uCUSuobNVeqUupowbdZub6ggI5/JZkYyJdDogddJr60L764oxC2pMZov1fQ3wM9bdyzUILDG+Sqx6NAKAz9rKQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/regex/-/regex-5.1.1.tgz", + "integrity": "sha512-dN5I359AVGPnwzJm2jN1k0W9LPZ+ePvoOeVMMfqIMFz53sSwXkxaJoxr50ptnsC771lK95BnTrVSZxq0b9yCGw==", + "dev": true, + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-5.1.1.tgz", + "integrity": "sha512-ae7SBCbzVNrIjgSbh7wMznPcQel1DNlDtzensnFxpiNpXt1U2ju/bHugH422r+4LAVS1FpW1YCwilmnNsjum9w==", + "dev": true, + "dependencies": { + "regex": "^5.1.1", + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", "dev": true }, "node_modules/regexp.prototype.flags": { @@ -6576,17 +6678,20 @@ "dev": true }, "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dependencies": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6679,13 +6784,14 @@ } }, "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", "isarray": "^2.0.5" }, "engines": { @@ -6715,14 +6821,29 @@ } ] }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "is-regex": "^1.1.4" + "is-regex": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -6819,36 +6940,90 @@ } }, "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", + "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/shiki": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.2.tgz", - "integrity": "sha512-3IZau0NdGKXhH2bBlUk4w1IHNxPh6A5B2sUpyY+8utLu2j/h1QpFkAaUA1bAMxOWWGtTWcAh531vnS4NJKS/lA==", + "version": "1.24.4", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.24.4.tgz", + "integrity": "sha512-aVGSFAOAr1v26Hh/+GBIsRVDWJ583XYV7CuNURKRWh9gpGv4OdbisZGq96B9arMYTZhTQkmRF5BrShOSTvNqhw==", "dev": true, "dependencies": { - "@shikijs/core": "1.22.2", - "@shikijs/engine-javascript": "1.22.2", - "@shikijs/engine-oniguruma": "1.22.2", - "@shikijs/types": "1.22.2", - "@shikijs/vscode-textmate": "^9.3.0", + "@shikijs/core": "1.24.4", + "@shikijs/engine-javascript": "1.24.4", + "@shikijs/engine-oniguruma": "1.24.4", + "@shikijs/types": "1.24.4", + "@shikijs/vscode-textmate": "^9.3.1", "@types/hast": "^3.0.4" } }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -6886,11 +7061,11 @@ } }, "node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", "dependencies": { - "agent-base": "^7.1.1", + "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" }, @@ -6899,12 +7074,9 @@ } }, "node_modules/socks-proxy-agent/node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dependencies": { - "debug": "^4.3.4" - }, + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "engines": { "node": ">= 14" } @@ -7102,23 +7274,24 @@ } }, "node_modules/string.prototype.matchall": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", - "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "regexp.prototype.flags": "^1.5.2", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7155,14 +7328,17 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7172,14 +7348,18 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7441,9 +7621,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", - "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", "dev": true, "engines": { "node": ">=16" @@ -7516,28 +7696,28 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -7547,16 +7727,17 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { "node": ">= 0.4" @@ -7566,16 +7747,16 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-proto": "^1.0.3", "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" }, "engines": { "node": ">= 0.4" @@ -7616,15 +7797,15 @@ } }, "node_modules/typedoc-plugin-rename-defaults": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/typedoc-plugin-rename-defaults/-/typedoc-plugin-rename-defaults-0.7.1.tgz", - "integrity": "sha512-hgg4mAy5IumgUmPOnVVGmGywjTGtUCmRJ2jRbseqtXdlUuYKj652ODL9joUWFt5uvNu4Dr/pNILc/qsKGHJw+w==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/typedoc-plugin-rename-defaults/-/typedoc-plugin-rename-defaults-0.7.2.tgz", + "integrity": "sha512-9oa1CsMN4p/xuVR2JW2YDD6xE7JcrIth3KAfjR8YBi6NnrDk2Q72o4lbArybLDjxKAkOzk7N1uUdGwJlooLEOg==", "dev": true, "dependencies": { "camelcase": "^8.0.0" }, "peerDependencies": { - "typedoc": ">=0.22.x <0.27.x" + "typedoc": ">=0.22.x <0.28.x" } }, "node_modules/typedoc-plugin-rename-defaults/node_modules/camelcase": { @@ -7677,14 +7858,14 @@ } }, "node_modules/typescript-eslint": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.12.2.tgz", - "integrity": "sha512-UbuVUWSrHVR03q9CWx+JDHeO6B/Hr9p4U5lRH++5tq/EbFq1faYZe50ZSBePptgfIKLEti0aPQ3hFgnPVcd8ZQ==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.19.0.tgz", + "integrity": "sha512-Ni8sUkVWYK4KAcTtPjQ/UTiRk6jcsuDhPpxULapUDi8A/l8TSBk+t1GtJA1RsCzIJg0q6+J7bf35AwQigENWRQ==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "8.12.2", - "@typescript-eslint/parser": "8.12.2", - "@typescript-eslint/utils": "8.12.2" + "@typescript-eslint/eslint-plugin": "8.19.0", + "@typescript-eslint/parser": "8.19.0", + "@typescript-eslint/utils": "8.19.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7693,10 +7874,9 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/uc.micro": { @@ -7706,23 +7886,26 @@ "dev": true }, "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dependencies": { - "call-bind": "^1.0.2", + "call-bound": "^1.0.3", "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", "dev": true }, "node_modules/unique-filename": { @@ -7955,38 +8138,41 @@ } }, "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/which-builtin-type": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", - "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", - "dev": true, + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "dependencies": { + "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", + "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", + "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", - "which-typed-array": "^1.1.15" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -7999,7 +8185,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dev": true, "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", @@ -8020,14 +8205,15 @@ "dev": true }, "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", + "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "for-each": "^0.3.3", - "gopd": "^1.0.1", + "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" }, "engines": { @@ -8200,9 +8386,9 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", - "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", "dev": true, "bin": { "yaml": "bin.mjs" diff --git a/package.json b/package.json index e7031e2d..5eb08965 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aerospike", - "version": "5.13.2", + "version": "6.0.1", "description": "Aerospike Client Library", "keywords": [ "aerospike", @@ -41,7 +41,8 @@ "preinstall": "npm install @mapbox/node-pre-gyp", "install": "npm run build", "build": "node-pre-gyp install --fallback-to-build", - "test": "rm -rf ts-test/dist; cd ts-test; npx tsc ; cp tests/udf.lua dist/udf.lua ; mocha", + "test-prereq": "cd ts-test; npm install ..; run: npm i --save-dev @types/jest; run: npm i --save-dev @types/chai; cd ..;", + "test": "rm -rf ts-test/dist; cd ts-test; npx tsc ; cp tests/udf.lua dist/udf.lua ; mocha dist/${npm_config_testfile:-} ", "test-dry-run": "mocha --dry-run", "test-noserver": "GLOBAL_CLIENT=false mocha -g '#noserver'", "lint": "standard", @@ -93,8 +94,7 @@ "apidocs", "tmp-*.js", "/*.js", - "libuv-v*", - "ts-test/dist" + "libuv-v*" ] }, "files": [ @@ -102,15 +102,12 @@ "aerospike-client-c.sha256", "binding.gyp", "benchmarks/", - "CHANGELOG.md", "examples/", "lib/", - "LICENSE", "scripts/", "src/", "test/", "ts-test/", - "tsconfig.json", "typings/" ] } diff --git a/scripts/build-package.sh-cclient-output.log b/scripts/build-package.sh-cclient-output.log new file mode 100644 index 00000000..7bccb0ff --- /dev/null +++ b/scripts/build-package.sh-cclient-output.log @@ -0,0 +1,8 @@ +project/modules.mk:16: *************************************************************** +project/modules.mk:17: * +project/modules.mk:18: * COMMON is '/home/dpelini/Documents/MRT/aerospike-client-nodejs/aerospike-client-c/modules/common' +project/modules.mk:19: * COMMON doesn't contain 'Makefile'. +project/modules.mk:20: * COMMON should be set to a valid path. +project/modules.mk:21: * +project/modules.mk:22: *************************************************************** +project/modules.mk:23: *** . Stop. diff --git a/src/include/async.h b/src/include/async.h index a72ffabe..825fac13 100644 --- a/src/include/async.h +++ b/src/include/async.h @@ -20,6 +20,7 @@ extern "C" { #include #include #include +#include } #include @@ -61,4 +62,10 @@ bool async_scan_pages_listener(as_error *err, as_record *record, void *udata, as_event_loop *event_loop); bool async_query_pages_listener(as_error *err, as_record *record, void *udata, - as_event_loop *event_loop); \ No newline at end of file + as_event_loop *event_loop); + +void async_abort_listener(as_error* err, as_abort_status status, void* udata, struct as_event_loop* event_loop); + +void async_commit_listener(as_error* err, as_commit_status status, void* udata, struct as_event_loop* event_loop); + +void async_mrt_listener(as_error* err, uint32_t status, void* udata); \ No newline at end of file diff --git a/src/include/client.h b/src/include/client.h index fafa8664..41cb3d3d 100644 --- a/src/include/client.h +++ b/src/include/client.h @@ -127,6 +127,8 @@ class AerospikeClient : public Nan::ObjectWrap { static NAN_METHOD(SelectAsync); static NAN_METHOD(SetLogLevel); static NAN_METHOD(SetupEventCb); + static NAN_METHOD(TransactionAbort); + static NAN_METHOD(TransactionCommit); static NAN_METHOD(Truncate); static NAN_METHOD(UDFRemove); static NAN_METHOD(UDFScan); diff --git a/src/include/conversions.h b/src/include/conversions.h index 380f4950..dcb431db 100644 --- a/src/include/conversions.h +++ b/src/include/conversions.h @@ -33,6 +33,7 @@ extern "C" { #include #include #include +#include } #include "client.h" @@ -55,7 +56,10 @@ bool instanceof (v8::Local value, const char *type); bool is_double_value(v8::Local value); double double_value(v8::Local value); +bool is_transaction_value(v8::Local value); + bool is_geojson_value(v8::Local value); + char *geojson_as_string(v8::Local value); // Utility functions to extract property values from V8 v8::Object instances @@ -85,6 +89,9 @@ int get_optional_asval_property(as_val **value, bool *defined, int get_optional_bool_property(bool *boolp, bool *defined, v8::Local obj, char const *prop, const LogInfo *log); +int get_optional_transaction_property(as_txn **txn, bool *defined, + v8::Local obj, char const *prop, + const LogInfo *log); int get_optional_bytes_property(uint8_t **bytes, int *size, bool *defined, v8::Local obj, char const *prop, const LogInfo *log); diff --git a/src/include/enums.h b/src/include/enums.h index a6fdb3be..7905d24a 100644 --- a/src/include/enums.h +++ b/src/include/enums.h @@ -45,4 +45,7 @@ v8::Local queryDuration(); v8::Local privilegeCode(); v8::Local expReadFlags(); v8::Local expWriteFlags(); - +v8::Local abortStatus(); +v8::Local commitStatus(); +v8::Local txnState(); +v8::Local txnCapacity(); diff --git a/src/include/transaction.h b/src/include/transaction.h new file mode 100644 index 00000000..55077ff5 --- /dev/null +++ b/src/include/transaction.h @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright 2013-2024 Aerospike, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ +#pragma once + +#include +#include + +extern "C" { +#include +} + +#include "log.h" +#include "command.h" + +class Transaction : public Nan::ObjectWrap { + + /*************************************************************************** + * PUBLIC + **************************************************************************/ + public: + static void Init(); + static v8::Local NewInstance(v8::Local capacity_obj); + + Nan::Persistent persistent; + as_txn *txn; + + Transaction(); + ~Transaction(); + + /*************************************************************************** + * PRIVATE + **************************************************************************/ + private: + + static inline Nan::Persistent &constructor() + { + static Nan::Persistent my_constructor; + return my_constructor; + } + + static NAN_METHOD(New); + + static NAN_METHOD(GetId); + static NAN_METHOD(GetInDoubt); + static NAN_METHOD(GetTimeout); + static NAN_METHOD(GetState); + + static NAN_METHOD(SetTimeout); + + static NAN_METHOD(Close); + +}; diff --git a/src/main/aerospike.cc b/src/main/aerospike.cc index 6f5fe76f..c2b6144f 100644 --- a/src/main/aerospike.cc +++ b/src/main/aerospike.cc @@ -28,6 +28,9 @@ extern "C" { #include } +#include "transaction.h" + + #define export(__name, __value) \ Nan::Set(target, Nan::New(__name).ToLocalChecked(), __value) @@ -116,6 +119,13 @@ NAN_METHOD(client) info.GetReturnValue().Set(AerospikeClient::NewInstance(config)); } +NAN_METHOD(transaction) +{ + Nan::HandleScope(); + + Local capacity_obj = info[0].As(); + info.GetReturnValue().Set(Transaction::NewInstance(capacity_obj)); +} /** * aerospike object. */ @@ -124,8 +134,9 @@ NAN_MODULE_INIT(Aerospike) Nan::HandleScope scope; AerospikeClient::Init(); - + Transaction::Init(); NAN_EXPORT(target, client); + NAN_EXPORT(target, transaction); NAN_EXPORT(target, get_cluster_count); NAN_EXPORT(target, register_as_event_loop); NAN_EXPORT(target, release_as_event_loop); @@ -160,6 +171,11 @@ NAN_MODULE_INIT(Aerospike) export("privilegeCode", privilegeCode()); export("expReadFlags", expReadFlags()); export("expWriteFlags", expWriteFlags()); + export("abortStatus", abortStatus()); + export("commitStatus", commitStatus()); + export("txnState", txnState()); + export("txnCapacity", txnCapacity()); + } NODE_MODULE(aerospike, Aerospike); diff --git a/src/main/async.cc b/src/main/async.cc index d8eb7a99..606535c0 100644 --- a/src/main/async.cc +++ b/src/main/async.cc @@ -20,6 +20,7 @@ #include "async.h" #include "command.h" +#include "transaction.h" #include "client.h" #include "conversions.h" #include "log.h" @@ -29,6 +30,7 @@ extern "C" { #include #include +#include } using namespace v8; @@ -280,3 +282,29 @@ bool async_query_pages_listener(as_error *err, as_record *record, void *udata, return continue_scan; } +void async_abort_listener(as_error* err, as_abort_status status, void* udata, struct as_event_loop* event_loop) +{ + async_mrt_listener(err, (uint32_t)status, udata); +} + +void async_commit_listener(as_error* err, as_commit_status status, void* udata, struct as_event_loop* event_loop) +{ + async_mrt_listener(err, (uint32_t)status, udata); +} + +void async_mrt_listener(as_error* err, uint32_t status, void* udata) +{ + Nan::HandleScope scope; + AsyncCommand *cmd = reinterpret_cast(udata); + + if (err) { + cmd->ErrorCallback(err); + } + else { + Local argv[] = {Nan::Null(), + Nan::New((uint32_t)status)}; + cmd->Callback(2, argv); + } + + delete cmd; +} \ No newline at end of file diff --git a/src/main/client.cc b/src/main/client.cc index e19d7db1..a3ac11bf 100644 --- a/src/main/client.cc +++ b/src/main/client.cc @@ -333,6 +333,8 @@ void AerospikeClient::Init() Nan::SetPrototypeMethod(tpl, "scanBackground", ScanBackground); Nan::SetPrototypeMethod(tpl, "selectAsync", SelectAsync); Nan::SetPrototypeMethod(tpl, "setupEventCb", SetupEventCb); + Nan::SetPrototypeMethod(tpl, "transactionAbort", TransactionAbort); + Nan::SetPrototypeMethod(tpl, "transactionCommit", TransactionCommit); Nan::SetPrototypeMethod(tpl, "truncate", Truncate); Nan::SetPrototypeMethod(tpl, "udfRegister", Register); Nan::SetPrototypeMethod(tpl, "udfRemove", UDFRemove); diff --git a/src/main/commands/transaction_abort.cc b/src/main/commands/transaction_abort.cc new file mode 100644 index 00000000..f2438643 --- /dev/null +++ b/src/main/commands/transaction_abort.cc @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright 2013-2023 Aerospike, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ + +#include "client.h" +#include "command.h" +#include "conversions.h" +#include "log.h" +#include "async.h" +#include "transaction.h" + +using namespace v8; + +NAN_METHOD(AerospikeClient::TransactionAbort) +{ + // TYPE_CHECK_REQ(info[0], is_transaction_value, "Transaction must be an object"); + TYPE_CHECK_REQ(info[1], IsFunction, "Callback must be a function"); + + AerospikeClient *client = + Nan::ObjectWrap::Unwrap(info.This()); + AsyncCommand *cmd = new AsyncCommand("Abort", client, info[1].As()); + LogInfo *log = client->log; + + Transaction *transaction; + as_status status; + + + if (is_transaction_value(info[0])) { + transaction = Nan::ObjectWrap::Unwrap(info[0].As()); + } + else { + CmdErrorCallback(cmd, AEROSPIKE_ERR_PARAM, "Transaction object invalid"); + goto Cleanup; + } + + status = aerospike_abort_async(client->as, &cmd->err, transaction->txn, async_abort_listener, cmd, NULL); + as_v8_debug(log, "Sending transaction abort command"); + + if (status == AEROSPIKE_OK) { + cmd = NULL; // async callback responsible for deleting the command + } + else { + cmd->ErrorCallback(); + } + +Cleanup: + delete cmd; +} \ No newline at end of file diff --git a/src/main/commands/transaction_commit.cc b/src/main/commands/transaction_commit.cc new file mode 100644 index 00000000..c5cdab34 --- /dev/null +++ b/src/main/commands/transaction_commit.cc @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright 2013-2023 Aerospike, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ + +#include "client.h" +#include "command.h" +#include "conversions.h" +#include "log.h" +#include "async.h" +#include "transaction.h" + +using namespace v8; + + +NAN_METHOD(AerospikeClient::TransactionCommit) +{ + //TYPE_CHECK_REQ(info[0], is_transaction_value, "Transaction must be an object"); + TYPE_CHECK_REQ(info[1], IsFunction, "Callback must be a function"); + + AerospikeClient *client = + Nan::ObjectWrap::Unwrap(info.This()); + AsyncCommand *cmd = new AsyncCommand("Commit", client, info[1].As()); + LogInfo *log = client->log; + + Transaction *transaction; + as_status status; + + if (is_transaction_value(info[0])) { + transaction = Nan::ObjectWrap::Unwrap(info[0].As()); + } + else { + CmdErrorCallback(cmd, AEROSPIKE_ERR_PARAM, "Transaction object invalid"); + goto Cleanup; + } + + status = aerospike_commit_async(client->as, &cmd->err, transaction->txn , async_commit_listener, cmd, NULL); + as_v8_debug(log, "Sending transaction commit command"); + + if (status == AEROSPIKE_OK) { + cmd = NULL; // async callback responsible for deleting the command + } + else { + cmd->ErrorCallback(); + } + +Cleanup: + delete cmd; + +} \ No newline at end of file diff --git a/src/main/enums/abort_status.cc b/src/main/enums/abort_status.cc new file mode 100644 index 00000000..a794a7a9 --- /dev/null +++ b/src/main/enums/abort_status.cc @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright 2024 Aerospike, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ + +#include +#include + +extern "C" { +#include +} + +using namespace v8; + +#define set(__obj, __name, __value) \ + Nan::Set(__obj, Nan::New(__name).ToLocalChecked(), Nan::New(__value)) + +Local abortStatus() +{ + Nan::EscapableHandleScope scope; + Local obj = Nan::New(); + set(obj, "OK", AS_ABORT_OK); + set(obj, "ALREADY_COMMITTED", AS_ABORT_ALREADY_COMMITTED); + set(obj, "ALREADY_ABORTED", AS_ABORT_ALREADY_ABORTED); + set(obj, "ROLL_BACK_ABANDONED", AS_ABORT_ROLL_BACK_ABANDONED); + set(obj, "CLOSE_ABANDONED", AS_ABORT_CLOSE_ABANDONED); + return scope.Escape(obj); +} diff --git a/src/main/enums/commit_status.cc b/src/main/enums/commit_status.cc new file mode 100644 index 00000000..381a2491 --- /dev/null +++ b/src/main/enums/commit_status.cc @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright 2024 Aerospike, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ + +#include +#include + +extern "C" { +#include +} + +using namespace v8; + +#define set(__obj, __name, __value) \ + Nan::Set(__obj, Nan::New(__name).ToLocalChecked(), Nan::New(__value)) + +Local commitStatus() +{ + Nan::EscapableHandleScope scope; + Local obj = Nan::New(); + set(obj, "OK", AS_COMMIT_OK); + set(obj, "ALREADY_COMMITTED", AS_COMMIT_ALREADY_COMMITTED); + set(obj, "ALREADY_ABORTED", AS_COMMIT_ALREADY_ABORTED); + set(obj, "VERIFY_FAILED", AS_COMMIT_VERIFY_FAILED); + set(obj, "MARK_ROLL_FORWARD_ABANDONED", AS_COMMIT_MARK_ROLL_FORWARD_ABANDONED); + set(obj, "ROLL_FORWARD_ABANDONED", AS_COMMIT_ROLL_FORWARD_ABANDONED); + set(obj, "CLOSE_ABANDONED", AS_COMMIT_CLOSE_ABANDONED); + return scope.Escape(obj); +} diff --git a/src/main/enums/status.cc b/src/main/enums/status.cc index 007e0985..9a0f283f 100644 --- a/src/main/enums/status.cc +++ b/src/main/enums/status.cc @@ -30,6 +30,8 @@ Local status() { Nan::EscapableHandleScope scope; Local obj = Nan::New(); + set(obj, "AEROSPIKE_TXN_FAILED", AEROSPIKE_TXN_FAILED); + set(obj, "AEROSPIKE_BATCH_FAILED", AEROSPIKE_BATCH_FAILED); set(obj, "AEROSPIKE_NO_RESPONSE", AEROSPIKE_NO_RESPONSE); set(obj, "AEROSPIKE_MAX_ERROR_RATE", AEROSPIKE_MAX_ERROR_RATE); set(obj, "AEROSPIKE_USE_NORMAL_RETRY", AEROSPIKE_USE_NORMAL_RETRY); @@ -83,6 +85,12 @@ Local status() AEROSPIKE_ERR_OP_NOT_APPLICABLE); set(obj, "AEROSPIKE_FILTERED_OUT", AEROSPIKE_FILTERED_OUT); set(obj, "AEROSPIKE_LOST_CONFLICT", AEROSPIKE_LOST_CONFLICT); + set(obj, "AEROSPIKE_MRT_BLOCKED", AEROSPIKE_MRT_BLOCKED); + set(obj, "AEROSPIKE_MRT_VERSION_MISMATCH", AEROSPIKE_MRT_VERSION_MISMATCH); + set(obj, "AEROSPIKE_MRT_EXPIRED", AEROSPIKE_MRT_EXPIRED); + set(obj, "AEROSPIKE_XDR_KEY_BUSY", AEROSPIKE_XDR_KEY_BUSY); + set(obj, "AEROSPIKE_MRT_COMMITTED", AEROSPIKE_MRT_COMMITTED); + set(obj, "AEROSPIKE_MRT_ABORTED", AEROSPIKE_MRT_ABORTED); set(obj, "AEROSPIKE_QUERY_END", AEROSPIKE_QUERY_END); set(obj, "AEROSPIKE_SECURITY_NOT_SUPPORTED", AEROSPIKE_SECURITY_NOT_SUPPORTED); diff --git a/src/main/enums/txn_capacity.cc b/src/main/enums/txn_capacity.cc new file mode 100644 index 00000000..e8925fab --- /dev/null +++ b/src/main/enums/txn_capacity.cc @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright 2022-2023 Aerospike, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ + +#include +#include + +extern "C" { +#include +} + +using namespace v8; + +#define set(__obj, __name, __value) \ + Nan::Set(__obj, Nan::New(__name).ToLocalChecked(), Nan::New(__value)) + +Local txnCapacity() +{ + Nan::EscapableHandleScope scope; + Local obj = Nan::New(); + set(obj, "READ_DEFAULT", AS_TXN_READ_CAPACITY_DEFAULT); + set(obj, "WRITE_DEFAULT", AS_TXN_WRITE_CAPACITY_DEFAULT); + + return scope.Escape(obj); +} diff --git a/src/main/enums/txn_state.cc b/src/main/enums/txn_state.cc new file mode 100644 index 00000000..0f309021 --- /dev/null +++ b/src/main/enums/txn_state.cc @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright 2022-2023 Aerospike, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ + +#include +#include + +extern "C" { +#include +} + +using namespace v8; + +#define set(__obj, __name, __value) \ + Nan::Set(__obj, Nan::New(__name).ToLocalChecked(), Nan::New(__value)) + +Local txnState() +{ + Nan::EscapableHandleScope scope; + Local obj = Nan::New(); + set(obj, "OPEN", AS_TXN_STATE_OPEN); + set(obj, "VERIFIED", AS_TXN_STATE_VERIFIED); + set(obj, "COMMITTED", AS_TXN_STATE_COMMITTED); + set(obj, "ABORTED", AS_TXN_STATE_ABORTED); + return scope.Escape(obj); +} diff --git a/src/main/policy.cc b/src/main/policy.cc index 88ac4d92..9a091216 100644 --- a/src/main/policy.cc +++ b/src/main/policy.cc @@ -99,6 +99,12 @@ int basepolicy_from_jsobject(as_policy_base *policy, Local obj, return rc; } + if ((rc = get_optional_transaction_property(&policy->txn, NULL, obj, + "txn", log)) != + AS_NODE_PARAM_OK) { + return rc; + } + return AS_NODE_PARAM_OK; } diff --git a/src/main/transaction.cc b/src/main/transaction.cc new file mode 100644 index 00000000..8169bcb0 --- /dev/null +++ b/src/main/transaction.cc @@ -0,0 +1,176 @@ +#include +#include "transaction.h" +#include "conversions.h" + +extern "C" { +#include +#include +} + +using namespace v8; + +/******************************************************************************* + * Constructor and Destructor + ******************************************************************************/ + +Transaction::Transaction() {} + +Transaction::~Transaction() {} + +/** + * Constructor for Transaction. + */ +NAN_METHOD(Transaction::New) +{ + + uint32_t writes_capacity; + uint32_t reads_capacity; + as_txn* txn; + Local v8CapacityObj = info[0].As(); + Local v8ReadsCapacity; + Local v8WritesCapacity; + + v8ReadsCapacity = + Nan::Get(v8CapacityObj.As(), Nan::New("readsCapacity").ToLocalChecked()).ToLocalChecked(); + v8WritesCapacity = + Nan::Get(v8CapacityObj.As(), Nan::New("writesCapacity").ToLocalChecked()).ToLocalChecked(); + + + if (v8ReadsCapacity->IsNumber() && v8ReadsCapacity->IsNumber() ) { + writes_capacity = (uint32_t) Nan::To(v8WritesCapacity).FromJust(); + reads_capacity = (uint32_t) Nan::To(v8ReadsCapacity).FromJust(); + txn = as_txn_create_capacity(reads_capacity, writes_capacity); + } + else { + txn = as_txn_create(); + } + + + Transaction *transaction = new Transaction(); + transaction->txn = txn; + transaction->Wrap(info.This()); + + info.GetReturnValue().Set(info.This()); +} +/** + * Constructor for Transaction. + */ +NAN_METHOD(Transaction::Close) +{ + + Transaction *transaction = + Nan::ObjectWrap::Unwrap(info.This()); + + as_txn_destroy(transaction->txn); + + delete transaction; +} + +/** + * Constructor for Transaction. + */ +NAN_METHOD(Transaction::GetId) +{ + + Transaction *transaction = + Nan::ObjectWrap::Unwrap(info.This()); + + info.GetReturnValue().Set(Nan::New(transaction->txn->id)); +} + +/** + * Constructor for Transaction. + */ +NAN_METHOD(Transaction::GetInDoubt) +{ + + Transaction *transaction = + Nan::ObjectWrap::Unwrap(info.This()); + + info.GetReturnValue().Set(Nan::New(transaction->txn->in_doubt)); +} + + +/** + * Constructor for Transaction. + */ +NAN_METHOD(Transaction::GetTimeout) +{ + + Transaction *transaction = + Nan::ObjectWrap::Unwrap(info.This()); + + info.GetReturnValue().Set(Nan::New(transaction->txn->timeout)); +} + +/** + * Constructor for Transaction. + */ +NAN_METHOD(Transaction::GetState) +{ + + Transaction *transaction = + Nan::ObjectWrap::Unwrap(info.This()); + + info.GetReturnValue().Set(Nan::New(transaction->txn->state)); +} + +/** + * Constructor for Transaction. + */ +NAN_METHOD(Transaction::SetTimeout) +{ + + Transaction *transaction = + Nan::ObjectWrap::Unwrap(info.This()); + + if(info[0]->IsNumber()){ + transaction->txn->timeout = Nan::To(info[0].As()).FromJust(); + } +} + +/** + * Instantiate a new Transaction. + */ +Local Transaction::NewInstance(Local capacity_obj) +{ + Nan::EscapableHandleScope scope; + const int argc = 1; + Local argv[argc] = {capacity_obj}; + + Local cons = Nan::New(constructor()); + Nan::TryCatch try_catch; + Nan::MaybeLocal instance = Nan::NewInstance(cons, argc, argv); + if (try_catch.HasCaught()) { + try_catch.ReThrow(); + return Nan::Undefined(); + } + + return scope.Escape(instance.ToLocalChecked()); +} + +/** + * Initialize a Transaction object. + * This creates a constructor function, and sets up the prototype. + */ +void Transaction::Init() +{ + Local tpl = + Nan::New(Transaction::New); + + tpl->SetClassName(Nan::New("Transaction").ToLocalChecked()); + + tpl->InstanceTemplate()->SetInternalFieldCount(1); + + Nan::SetPrototypeMethod(tpl, "getId", GetId); + Nan::SetPrototypeMethod(tpl, "getInDoubt", GetInDoubt); + Nan::SetPrototypeMethod(tpl, "getTimeout", GetTimeout); + Nan::SetPrototypeMethod(tpl, "getState", GetState); + + Nan::SetPrototypeMethod(tpl, "setTimeout", SetTimeout); + + Nan::SetPrototypeMethod(tpl, "close", Close); + + + constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked()); +} \ No newline at end of file diff --git a/src/main/util/conversions.cc b/src/main/util/conversions.cc index 3e109634..94921df1 100644 --- a/src/main/util/conversions.cc +++ b/src/main/util/conversions.cc @@ -54,6 +54,7 @@ extern "C" { #include "log.h" #include "enums.h" #include "string.h" +#include "transaction.h" using namespace node; using namespace v8; @@ -61,6 +62,7 @@ using namespace v8; const char *DoubleType = "Double"; const char *GeoJSONType = "GeoJSON"; const char *BinType = "Bin"; +const char *TransactionType = "Transaction"; const int64_t MIN_SAFE_INTEGER = -1 * (std::pow(2, 53) - 1); const int64_t MAX_SAFE_INTEGER = std::pow(2, 53) - 1; @@ -339,6 +341,42 @@ int get_optional_bool_property(bool *boolp, bool *defined, Local obj, return AS_NODE_PARAM_OK; } + + +int get_optional_transaction_property(as_txn **txn, bool *defined, + Local obj, char const *prop, + const LogInfo *log) +{ + Nan::HandleScope scope; + Local js_wrapper_value = + Nan::Get(obj, Nan::New(prop).ToLocalChecked()).ToLocalChecked(); + + if (js_wrapper_value->IsObject()) { + Local value = + Nan::Get(js_wrapper_value.As(), Nan::New("transaction").ToLocalChecked()).ToLocalChecked(); + if (is_transaction_value(value)) { + if (defined != NULL) + (*defined) = true; + Transaction *transaction = Nan::ObjectWrap::Unwrap(value.As()); + + (*txn) = transaction->txn; + + as_v8_detail(log, "%s => (transaction) %d", prop, (*txn)->id); + } + else if (value->IsUndefined() || value->IsNull()) { + if (defined != NULL) + (*defined) = false; + + as_v8_detail(log, "%s => undefined", prop); + } + else { + as_v8_error(log, "Type error: %s property should be a Transaction type", prop); + return AS_NODE_PARAM_ERR; + } + } + return AS_NODE_PARAM_OK; +} + int get_bool_property(bool *boolp, Local obj, char const *prop, const LogInfo *log) { @@ -1039,6 +1077,11 @@ bool is_geojson_value(Local value) return instanceof (value, GeoJSONType); } +bool is_transaction_value(Local value) +{ + return instanceof (value, TransactionType); +} + bool is_bin_value(Local value) { return instanceof (value, BinType); diff --git a/ts-test/package-lock.json b/ts-test/package-lock.json index afae7e3c..672a7296 100644 --- a/ts-test/package-lock.json +++ b/ts-test/package-lock.json @@ -1,3 +1,4 @@ + { "name": "ts-test", "version": "1.0.0", @@ -12,7 +13,7 @@ "aerospike": "file:.." }, "devDependencies": { - "@types/chai": "^4.3.19", + "@types/chai": "^5.0.1", "@types/mocha": "^10.0.7", "@types/semver": "^7.5.8", "@types/tmp": "^0.2.6", @@ -25,7 +26,7 @@ }, "..": { "name": "aerospike", - "version": "5.12.1", + "version": "5.13.1", "cpu": [ "x64", "arm64" @@ -41,12 +42,12 @@ "ansi-colors": "^4.1.3", "bindings": "^1.5.0", "minimatch": "^3.1.2", - "nan": "^2.19.0", + "nan": "^2.22.0", "node-gyp": "^10.1.0", "npm-run-all": "^4.1.5" }, "devDependencies": { - "@eslint/js": "^9.11.1", + "@eslint/js": "^9.12.0", "@mapbox/node-pre-gyp": "^1.0.11", "@types/node": "^22.7.4", "chai": "^4.4.1", @@ -54,7 +55,7 @@ "codecov": "^3.8.3", "deep-eql": "^4.1.3", "eslint": "^8.57.1", - "globals": "^15.9.0", + "globals": "^15.11.0", "husky": "^9.0.11", "mocha": "^10.4.0", "mocha-clean": "^1.0.0", @@ -63,8 +64,10 @@ "semver": "^7.6.0", "standard": "^17.1.0", "tmp": "^0.2.3", + "typedoc": "^0.26.7", + "typedoc-plugin-rename-defaults": "^0.7.1", "typescript": "^5.6.2", - "typescript-eslint": "^8.7.0", + "typescript-eslint": "^8.8.1", "yargs": "^17.7.2" }, "engines": { @@ -192,9 +195,18 @@ "license": "MIT" }, "node_modules/@types/chai": { - "version": "4.3.19", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.19.tgz", - "integrity": "sha512-2hHHvQBVE2FiSK4eN0Br6snX9MtolHaTo/batnLjlGRhoQzlCL61iVpxoqO7SfFyOw+P/pwv+0zNHzKoGWz9Cw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.0.1.tgz", + "integrity": "sha512-5T8ajsg3M/FOncpLYW7sdOcD6yf4+722sze/tc4KQV0P8Z2rAr3SAuHCIkYmYpt8VbcQlnz8SxlOlPQYefe4cA==", + "dev": true, + "dependencies": { + "@types/deep-eql": "*" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true }, "node_modules/@types/hast": { diff --git a/ts-test/package.json b/ts-test/package.json index f423e6e5..11d91d51 100644 --- a/ts-test/package.json +++ b/ts-test/package.json @@ -13,7 +13,7 @@ "license": "ISC", "description": "", "devDependencies": { - "@types/chai": "^4.3.19", + "@types/chai": "^5.0.1", "@types/mocha": "^10.0.7", "@types/semver": "^7.5.8", "@types/tmp": "^0.2.6", diff --git a/ts-test/tests/batch_read.ts b/ts-test/tests/batch_read.ts index 351aeb71..56ce1d28 100644 --- a/ts-test/tests/batch_read.ts +++ b/ts-test/tests/batch_read.ts @@ -204,7 +204,7 @@ describe('client.batchRead()', function () { const batchResult = await client.batchRead(batch, policy) expect(batchResult[0].record.bins).to.eql({ i: 2 }) - expect(batchResult[0].record.ttl).to.be.within(7, 8) + expect(batchResult[0].record.ttl).to.be.within(6, 8) const record = await client.get(new Aerospike.Key('test', 'demo', 'batchTtl1')) expect(record.bins).to.eql({ i: 2 }) @@ -228,7 +228,7 @@ describe('client.batchRead()', function () { const batchResult = await client.batchRead(batch, policy) expect(batchResult[0].record.bins).to.eql({ i: 2 }) - expect(batchResult[0].record.ttl).to.be.within(7, 8) + expect(batchResult[0].record.ttl).to.be.within(6, 8) const record = await client.get(new Aerospike.Key('test', 'demo', 'batchTtl2')) expect(record.bins).to.eql({ i: 2 }) @@ -252,11 +252,11 @@ describe('client.batchRead()', function () { const batchResult = await client.batchRead(batch, policy) expect(batchResult[0].record.bins).to.eql({ i: 2 }) - expect(batchResult[0].record.ttl).to.be.within(7, 8) + expect(batchResult[0].record.ttl).to.be.within(6, 8) const record = await client.get(new Aerospike.Key('test', 'demo', 'batchTtl3')) expect(record.bins).to.eql({ i: 2 }) - expect(record.ttl).to.be.within(7, 8) + expect(record.ttl).to.be.within(6, 8) await client.remove(new Aerospike.Key('test', 'demo', 'batchTtl3')) }) @@ -276,11 +276,11 @@ describe('client.batchRead()', function () { const batchResult = await client.batchRead(batch, policy) expect(batchResult[0].record.bins).to.eql({ i: 2 }) - expect(batchResult[0].record.ttl).to.be.within(7, 8) + expect(batchResult[0].record.ttl).to.be.within(6, 8) const record = await client.get(new Aerospike.Key('test', 'demo', 'batchTtl4')) expect(record.bins).to.eql({ i: 2 }) - expect(record.ttl).to.be.within(7, 8) + expect(record.ttl).to.be.within(6, 8) await client.remove(new Aerospike.Key('test', 'demo', 'batchTtl4')) }) @@ -301,7 +301,7 @@ describe('client.batchRead()', function () { const batchResult = await client.batchRead(batch) expect(batchResult[0].record.bins).to.eql({ i: 2 }) - expect(batchResult[0].record.ttl).to.be.within(7, 8) + expect(batchResult[0].record.ttl).to.be.within(6, 8) const record = await client.get(new Aerospike.Key('test', 'demo', 'batchReadTtl1')) expect(record.bins).to.eql({ i: 2 }) @@ -323,7 +323,7 @@ describe('client.batchRead()', function () { const batchResult: BatchResult[] = await client.batchRead(batch) expect(batchResult[0].record.bins).to.eql({ i: 2 }) - expect(batchResult[0].record.ttl).to.be.within(7, 8) + expect(batchResult[0].record.ttl).to.be.within(6, 8) const record = await client.get(new Aerospike.Key('test', 'demo', 'batchReadTtl2')) expect(record.bins).to.eql({ i: 2 }) @@ -345,11 +345,11 @@ describe('client.batchRead()', function () { const batchResult: BatchResult[] = await client.batchRead(batch) expect(batchResult[0].record.bins).to.eql({ i: 2 }) - expect(batchResult[0].record.ttl).to.be.within(7, 8) + expect(batchResult[0].record.ttl).to.be.within(6, 8) const record: AerospikeRecord = await client.get(new Aerospike.Key('test', 'demo', 'batchReadTtl3')) expect(record.bins).to.eql({ i: 2 }) - expect(record.ttl).to.be.within(7, 8) + expect(record.ttl).to.be.within(6, 8) await client.remove(new Aerospike.Key('test', 'demo', 'batchReadTtl3')) }) @@ -367,11 +367,11 @@ describe('client.batchRead()', function () { const batchResult: BatchResult[] = await client.batchRead(batch) expect(batchResult[0].record.bins).to.eql({ i: 2 }) - expect(batchResult[0].record.ttl).to.be.within(7, 8) + expect(batchResult[0].record.ttl).to.be.within(6, 8) const record: AerospikeRecord = await client.get(new Aerospike.Key('test', 'demo', 'batchReadTtl4')) expect(record.bins).to.eql({ i: 2 }) - expect(record.ttl).to.be.within(7, 8) + expect(record.ttl).to.be.within(6, 8) await client.remove(new Aerospike.Key('test', 'demo', 'batchReadTtl4')) }) diff --git a/ts-test/tests/batch_write.ts b/ts-test/tests/batch_write.ts index e653b020..e0864637 100644 --- a/ts-test/tests/batch_write.ts +++ b/ts-test/tests/batch_write.ts @@ -530,9 +530,11 @@ describe('client.batchWrite()', function () { const config: ConfigOptions = { hosts: helper.config.hosts, + user: helper.config.user, + password: helper.config.password, policies: { batchParentWrite: new Aerospike.BatchPolicy({ socketTimeout: 0, totalTimeout: 0, deserialize: false }) - } + }, } const dummyClient = await Aerospike.connect(config) diff --git a/ts-test/tests/client.ts b/ts-test/tests/client.ts index d5f1073b..c1ca1cb2 100644 --- a/ts-test/tests/client.ts +++ b/ts-test/tests/client.ts @@ -153,7 +153,7 @@ describe('Client', function () { expect(nodes).to.be.an('array') expect(nodes.length).to.be.greaterThan(0) nodes.forEach(function (node) { - expect(node.name).to.match(/^[0-9A-F]{15}$/) + expect(node.name).to.match(/^[0-9A-F]+$/) expect(node.address).to.be.a('string') }) }) diff --git a/ts-test/tests/get.ts b/ts-test/tests/get.ts index 26d212c8..16364c92 100644 --- a/ts-test/tests/get.ts +++ b/ts-test/tests/get.ts @@ -100,7 +100,7 @@ describe('client.get()', function () { let record: AerospikeRecord = await client.get(key, policy) expect(record.bins).to.eql({ i: 2 }) - expect(record.ttl).to.be.within(7, 8) + expect(record.ttl).to.be.within(6, 8) record = await client.get(key, policy) @@ -121,7 +121,7 @@ describe('client.get()', function () { let record: AerospikeRecord = await client.get(key, policy) expect(record.bins).to.eql({ i: 2 }) - expect(record.ttl).to.be.within(7, 8) + expect(record.ttl).to.be.within(6, 8) record = await client.get(key, policy) @@ -142,12 +142,12 @@ describe('client.get()', function () { let record: AerospikeRecord = await client.get(key, policy) expect(record.bins).to.eql({ i: 2 }) - expect(record.ttl).to.be.within(7, 8) + expect(record.ttl).to.be.within(6, 8) record = await client.get(key, policy) expect(record.bins).to.eql({ i: 2 }) - expect(record.ttl).to.be.within(7, 8) + expect(record.ttl).to.be.within(6, 8) await client.remove(key) }) @@ -162,12 +162,12 @@ describe('client.get()', function () { let record: AerospikeRecord = await client.get(key, policy) expect(record.bins).to.eql({ i: 2 }) - expect(record.ttl).to.be.within(7, 8) + expect(record.ttl).to.be.within(6, 8) record = await client.get(key, policy) expect(record.bins).to.eql({ i: 2 }) - expect(record.ttl).to.be.within(7, 8) + expect(record.ttl).to.be.within(6, 8) await client.remove(key) }) }) diff --git a/ts-test/tests/mrt_api.ts b/ts-test/tests/mrt_api.ts new file mode 100644 index 00000000..ae2727db --- /dev/null +++ b/ts-test/tests/mrt_api.ts @@ -0,0 +1,231 @@ +// ***************************************************************************** +// Copyright 2013-2023 Aerospike, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License") +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ***************************************************************************** + +'use strict' + +/* eslint-env mocha */ +/* global expect */ + +import Aerospike, { Key as K, RecordMetadata, status as statusModule, AerospikeRecord, Client as Cli, WritePolicyOptions, AerospikeError, Transaction, _transactionPool} from 'aerospike'; + +import { expect, assert } from 'chai'; +import * as helper from './test_helper'; + +const keygen: any = helper.keygen +const metagen: any = helper.metagen +const recgen: any = helper.recgen + +const status: typeof statusModule = Aerospike.status + +describe('MRT API Tests', function () { + helper.skipUnlessVersionAndEnterprise('>= 8.0.0', this) + + const client: Cli = helper.client + + it('should initialize a transaction', async function () { + let mrt: any = new Aerospike.Transaction() + + let id: number = mrt.getId() + expect(id).to.be.a('number') + + let timeout: number = mrt.getTimeout() + expect(timeout).to.be.a('number') + + let state: number = mrt.getState() + expect(state).to.be.a('number') + + let inDoubt: boolean = mrt.getInDoubt() + expect(state).to.be.a('number') + }) + + context('transaction getters', function () { + + it('transaction.getId before and after transaction completion', async function () { + let mrt: any = new Aerospike.Transaction() + + expect(mrt.getId()).to.be.a('number') + + let result: number = await client.abort(mrt) + + expect(mrt.getId()).to.be.a('number') + + }) + + it('transaction.getInDoubt before and after transaction completion', async function () { + let mrt: any = new Aerospike.Transaction() + + expect(mrt.getInDoubt()).to.be.a('boolean') + + let result: number = await client.abort(mrt) + + expect(mrt.getInDoubt()).to.be.a('boolean') + + }) + + it('transaction.getTimeout before and after transaction completion', async function () { + let mrt: any = new Aerospike.Transaction() + + expect(mrt.getTimeout()).to.be.a('number') + + let result: number = await client.abort(mrt) + + expect(mrt.getTimeout()).to.be.a('number') + + }) + + it('transaction.getState before and after transaction completion', async function () { + let mrt: any = new Aerospike.Transaction() + + expect(mrt.getState()).to.be.a('number') + + let result: number = await client.abort(mrt) + + expect(mrt.getState()).to.be.a('number') + + + }) + }) + + it('should fail with readsCapacity error string', function () { + expect(() => new Aerospike.Transaction("256" as any, 256)).to.throw('Must specify a number for readsCapacity'); + + + }) + + it('should fail with writesCapacity error string', function () { + expect(() => new Aerospike.Transaction(256, "256" as any)).to.throw('Must specify a number for writesCapacity'); + + + }) + + it('should fail with readsCapacity range error string', function () { + expect(() => new Aerospike.Transaction( 2**32, 256)).to.throw('readsCapacity is out of uint32 range'); + + }) + + it('should fail with writesCapacity range error string', function () { + expect(() => new Aerospike.Transaction( 256, 2**32)).to.throw('writesCapacity is out of uint32 range'); + }) + + it('should fail with readsCapacity and writesCapacity range error string', function () { + expect(() => new Aerospike.Transaction( 2**32, 2**32)).to.throw('both readsCapacity and writesCapacity are out of uint32 range'); + }) + + it('Should fail an abort with no arguments', async function () { + try{ + let result: number = await (client as any).abort(); + } + catch(error){ + return + } + + assert.fail('An error should have been caught') + }) + + it('Should fail an commit with no arguments', async function () { + try{ + let result: number = await (client as any).commit(); + } + catch(error){ + return + } + + assert.fail('An error should have been caught') + }) + it('Should fail an abort with incorrect arguments', async function () { + try{ + let result: number = await (client as any).abort("random_string"); + } + catch(error: any){ + expect(error.code).to.eql(Aerospike.status.ERR_CLIENT) + + return + } + + assert.fail('An error should have been caught') + }) + + it('Should fail an commit with incorrect arguments', async function () { + try{ + let result: number = await (client as any).commit("random_string"); + } + catch(error: any){ + expect(error.code).to.eql(Aerospike.status.ERR_CLIENT) + return + } + + assert.fail('An error should have been caught') + }) + + it('Reaps completed transactions', async function () { + let mrt: Transaction = new Aerospike.Transaction(); + + for (let i = 0; i < 129; i++) { + let mrt: Transaction = new Aerospike.Transaction() + await client.abort(mrt) + } + await new Promise(r => setTimeout(r, 1000)); + + let pool: any = _transactionPool + + expect(pool.getLength()).to.be.lessThan(10); + + + + + }) + + it('Hits the capacity limit', async function () { + let mrt: Transaction = new Aerospike.Transaction(4096, 4096); + try{ + for (let i = 0; i < 150; i++) { + new Aerospike.Transaction(4096, 4096) + + } + assert.fail('An error should have been caught') + + } + catch(error: any){ + expect(error.message).to.eql("Maximum capacity for Multi-record transactions has been reached. Avoid setting readsCapacity and writesCapacity too high, and abort/commit open transactions so memory can be cleaned up and reused.") + mrt.destroyAll() + } + + try{ + client.abort(mrt) + assert.fail('An error should have been caught') + + } + catch(error: any) { + expect(error.message).to.eql("The object has been destroyed, please create a new transaction.") + } + + mrt = new Aerospike.Transaction(4096, 4096); + + }) + + it('Expands the pool size', async function () { + + for (let i = 0; i < 150; i++) { + let mrt: Transaction = new Aerospike.Transaction() + } + + let pool: any = _transactionPool + pool.tendTransactions() + expect(pool.getLength()).to.be.greaterThan(140); + expect(pool.getCapacity()).to.eql(256) + }) + +}) \ No newline at end of file diff --git a/ts-test/tests/mrt_backward_compatible.ts b/ts-test/tests/mrt_backward_compatible.ts new file mode 100644 index 00000000..9c5d5db8 --- /dev/null +++ b/ts-test/tests/mrt_backward_compatible.ts @@ -0,0 +1,100 @@ +// ***************************************************************************** +// Copyright 2013-2023 Aerospike, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License") +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ***************************************************************************** + +'use strict' + +/* eslint-env mocha */ +/* global expect */ + +import Aerospike, { Key as K, RecordMetadata, status as statusModule, AerospikeRecord, Client as Cli, WritePolicyOptions, ReadPolicyOptions, AerospikeError } from 'aerospike'; + +import { expect, assert } from 'chai'; +import * as helper from './test_helper'; + +const keygen: any = helper.keygen +const metagen: any = helper.metagen +const recgen: any = helper.recgen + +const status: typeof statusModule = Aerospike.status + +describe('MRT backward compatible tests', function () { + helper.skip(this, 'MRT\'s require version 8.0.0 or greater') + + // helper.skipUnlessVersionAndCommunity('< 8.0.0', this) + + const client: Cli = helper.client + + const key1: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/mrt/1' })() + const key2: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/mrt/2' })() + const key3: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/mrt/3' })() + const key4: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/mrt/4' })() + const key5: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/mrt/5' })() + const key6: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/mrt/6' })() + const key7: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/mrt/7' })() + + const meta: RecordMetadata = metagen.constant({ ttl: 1000 })() + + const record1: AerospikeRecord = recgen.constant({ i: 123, s: 'abc' })() + const record2: AerospikeRecord = recgen.constant({ i: 456, s: 'def' })() + const record3: AerospikeRecord = recgen.constant({ i: 789, s: 'ghi' })() + + + + before(async function () { + await client.put(key1, record1, meta) + + await client.put(key2, record1, meta) + await client.put(key3, record1, meta) + await client.put(key4, record1, meta) + + }) + + it('Should execute a simple multi-record transaction', async function () { + + let mrt: any = new Aerospike.Transaction() + + let policy: any = { + txn: mrt + }; + + await client.put(key1, record2, meta, policy) + + let get_result: AerospikeRecord = await client.get(key1, policy) + expect(get_result.bins).to.eql(record2) + + let result: number = await client.commit(mrt) + expect(result).to.eql(Aerospike.Transaction.commitStatus.ROLL_FORWARD_ABANDONED) + + }) + + it('Should execute a simple multi-record transaction abort', async function () { + + let mrt: any = new Aerospike.Transaction() + + let policy: any = { + txn: mrt + }; + + await client.put(key2, record2, meta, policy) + + let get_result: AerospikeRecord = await client.get(key2, policy) + expect(get_result.bins).to.eql(record2) + + let result: number = await client.abort(mrt) + expect(result).to.eql(Aerospike.Transaction.abortStatus.ROLL_BACK_ABANDONED) + }) + +}) \ No newline at end of file diff --git a/ts-test/tests/mrt_functionality.ts b/ts-test/tests/mrt_functionality.ts new file mode 100644 index 00000000..59b0a65e --- /dev/null +++ b/ts-test/tests/mrt_functionality.ts @@ -0,0 +1,175 @@ +// ***************************************************************************** +// Copyright 2013-2023 Aerospike, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License") +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ***************************************************************************** + +'use strict' + +/* eslint-env mocha */ +/* global expect */ + +import Aerospike, { Key as K, RecordMetadata, status as statusModule, AerospikeRecord, Client as Cli, WritePolicyOptions, ReadPolicyOptions, AerospikeError } from 'aerospike'; + +import { expect, assert } from 'chai'; +import * as helper from './test_helper'; + +const keygen: any = helper.keygen +const metagen: any = helper.metagen +const recgen: any = helper.recgen + +const status: typeof statusModule = Aerospike.status + +describe('MRT functionality tests', function () { + helper.skipUnlessVersionAndEnterprise('>= 8.0.0', this) + + + const client: Cli = helper.client + + const key1: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/mrt/1' })() + const key2: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/mrt/2' })() + const key3: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/mrt/3' })() + const key4: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/mrt/4' })() + const key5: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/mrt/5' })() + const key6: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/mrt/6' })() + const key7: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/mrt/7' })() + + const meta: RecordMetadata = metagen.constant({ ttl: 1000 })() + + const record1: AerospikeRecord = recgen.constant({ i: 123, s: 'abc' })() + const record2: AerospikeRecord = recgen.constant({ i: 456, s: 'def' })() + const record3: AerospikeRecord = recgen.constant({ i: 789, s: 'ghi' })() + + + + before(async function () { + await client.put(key1, record1, meta) + + await client.put(key2, record1, meta) + await client.put(key3, record1, meta) + + await client.put(key4, record1, meta) + await client.put(key5, record1, meta) + + await client.put(key6, record1, meta) + + await client.put(key7, record1, meta) + + }) + + it('Should execute a simple multi-record transaction', async function () { + + let mrt: any = new Aerospike.Transaction() + + let policy: any = { + txn: mrt + }; + + await client.put(key1, record2, meta, policy) + + let get_result: AerospikeRecord = await client.get(key1, policy) + expect(get_result.bins).to.eql(record2) + + let result: number = await client.commit(mrt) + expect(result).to.eql(Aerospike.Transaction.commitStatus.OK) + }) + + it('should fail due to timeout: code MRT_EXPIRED', async function () { + this.timeout(6000) + let mrt: any = new Aerospike.Transaction() + + mrt.setTimeout(1) + + const policy: WritePolicyOptions = { + txn: mrt + } + + await client.put(key2, record2, meta, policy) + await new Promise(r => setTimeout(r, 3000)); + try{ + await client.put(key3, record2, meta, policy) + } + catch (error: any) { + expect(error.code).to.eql(Aerospike.status.MRT_EXPIRED) + + let result: number = await client.abort(mrt) + expect(result).to.eql(Aerospike.Transaction.abortStatus.OK) + + return + } + + assert.fail('An MRT_EXPIRED error should have been thrown') + }) + + it('should abort the MRT and revert changes', async function () { + let mrt: any = new Aerospike.Transaction() + + const policy: WritePolicyOptions = { + txn: mrt + } + + await client.put(key4, record2, meta, policy) + + const policyRead: ReadPolicyOptions = { + txn: mrt + } + + let get_result: AerospikeRecord = await client.get(key4, policy) + expect(get_result.bins).to.eql(record2) + + await client.put(key5, record2, meta, policy) + + let result: number = await client.abort(mrt) + expect(result).to.eql(Aerospike.Transaction.commitStatus.OK) + + get_result = await client.get(key4) + expect(get_result.bins).to.eql(record1) + + get_result = await client.get(key5) + expect(get_result.bins).to.eql(record1) + + }) + + it('should fail to commit after aborting', async function () { + let mrt: any = new Aerospike.Transaction() + + const policy: WritePolicyOptions = { + txn: mrt + } + + await client.put(key6, record1, meta, policy) + + let result: number = await client.abort(mrt) + + result = await client.commit(mrt) + + expect(result).to.eql(Aerospike.Transaction.commitStatus.ALREADY_ABORTED) + }) + + it('should fail to abort after committing', async function () { + let mrt: any = new Aerospike.Transaction() + + const policy: WritePolicyOptions = { + txn: mrt + } + + await client.put(key7, record1, meta, policy) + + let result: number = await client.commit(mrt) + + result = await client.abort(mrt) + expect(result).to.eql(Aerospike.Transaction.abortStatus.ALREADY_COMMITTED) + + }) + +}) \ No newline at end of file diff --git a/ts-test/tests/operate.ts b/ts-test/tests/operate.ts index c19067ef..d42b0da4 100644 --- a/ts-test/tests/operate.ts +++ b/ts-test/tests/operate.ts @@ -303,7 +303,7 @@ context('Operations', function () { let record: AerospikeRecord = await client.operate(new Aerospike.Key('test', 'demo', 'operateTtl1'), ops, null, policy) expect(record.bins).to.eql({ i: 2 }) - expect(record.ttl).to.be.within(7, 8) + expect(record.ttl).to.be.within(6, 8) record = await client.get(new Aerospike.Key('test', 'demo', 'operateTtl1'), policy) expect(record.bins).to.eql({ i: 2 }) @@ -323,7 +323,7 @@ context('Operations', function () { let record: AerospikeRecord = await client.operate(new Aerospike.Key('test', 'demo', 'operateTtl1'), ops, null, policy) expect(record.bins).to.eql({ i: 2 }) - expect(record.ttl).to.be.within(7, 8) + expect(record.ttl).to.be.within(6, 8) record = await client.get(new Aerospike.Key('test', 'demo', 'operateTtl1'), policy) expect(record.bins).to.eql({ i: 2 }) @@ -343,11 +343,11 @@ context('Operations', function () { let record: AerospikeRecord = await client.operate(new Aerospike.Key('test', 'demo', 'operateTtl1'), ops, null, policy) expect(record.bins).to.eql({ i: 2 }) - expect(record.ttl).to.be.within(7, 8) + expect(record.ttl).to.be.within(6, 8) record = await client.get(new Aerospike.Key('test', 'demo', 'operateTtl1'), policy) expect(record.bins).to.eql({ i: 2 }) - expect(record.ttl).to.be.within(7, 8) + expect(record.ttl).to.be.within(6, 8) await client.remove(new Aerospike.Key('test', 'demo', 'operateTtl1')) }) @@ -363,11 +363,11 @@ context('Operations', function () { let record: AerospikeRecord = await client.operate(new Aerospike.Key('test', 'demo', 'operateTtl1'), ops, null, policy) expect(record.bins).to.eql({ i: 2 }) - expect(record.ttl).to.be.within(7, 8) + expect(record.ttl).to.be.within(6, 8) record = await client.get(new Aerospike.Key('test', 'demo', 'operateTtl1'), policy) expect(record.bins).to.eql({ i: 2 }) - expect(record.ttl).to.be.within(7, 8) + expect(record.ttl).to.be.within(6, 8) await client.remove(new Aerospike.Key('test', 'demo', 'operateTtl1')) }) diff --git a/ts-test/tests/query.ts b/ts-test/tests/query.ts index ed78cffd..a30e2b86 100644 --- a/ts-test/tests/query.ts +++ b/ts-test/tests/query.ts @@ -308,7 +308,10 @@ describe('Queries', function () { const query: Query = client.query(helper.namespace, testSet) const stream = query.foreach({ expectedDuration: Aerospike.policy.queryDuration.LONG_RELAX_AP }) const results: AerospikeBins[] = [] - stream.on('error', (error: ASError) => { throw error }) + stream.on('error', (error: ASError) => { + expect(error.message).to.eql('Request protocol invalid, or invalid protocol field.') + done() + }) stream.on('data', (record: AerospikeRecord) => results.push(record.bins)) stream.on('end', () => { expect(results.length).to.be.above(samples.length) @@ -1127,6 +1130,8 @@ describe('Queries', function () { const key = keys[Math.floor(Math.random() * keys.length)] const record = await client.get(key) expect(record.ttl).to.equal(3599) + expect(record.ttl).to.be.within(3599, 3600) + }) it('should set TTL to the specified value using query options #slow', async function () { @@ -1137,7 +1142,7 @@ describe('Queries', function () { const key = keys[Math.floor(Math.random() * keys.length)] const record = await client.get(key) - expect(record.ttl).to.equal(7199) + expect(record.ttl).to.be.within(7199, 7200) }) }) diff --git a/ts-test/tests/scan.ts b/ts-test/tests/scan.ts index 9242d066..45722e99 100644 --- a/ts-test/tests/scan.ts +++ b/ts-test/tests/scan.ts @@ -398,7 +398,7 @@ context('Scans', function () { const key: any = keys[Math.floor(Math.random() * keys.length)] const record = await client.get(key) - expect(record.ttl).to.equal(10799) + expect(record.ttl).to.be.within(10799, 10800) }) it('should set TTL to the specified value with scan options #slow', async function () { @@ -410,6 +410,8 @@ context('Scans', function () { const key: any = keys[Math.floor(Math.random() * keys.length)] const record = await client.get(key) expect(record.ttl).to.equal(14399) + expect(record.ttl).to.be.within(14399, 14400) + }) it('should perform a background scan that executes the touch operation #slow', async function () { @@ -421,7 +423,7 @@ context('Scans', function () { const key: any = keys[Math.floor(Math.random() * keys.length)] const record = await client.get(key) console.log('After scan-op TTL : %d Key TTL: %d', ttl, record.ttl) - expect(record.ttl).to.equal(ttl - 1) + expect(record.ttl).to.be.within(ttl - 1, ttl) }) }) diff --git a/ts-test/tests/stats.ts b/ts-test/tests/stats.ts index f319e7a8..1a50aba6 100644 --- a/ts-test/tests/stats.ts +++ b/ts-test/tests/stats.ts @@ -46,7 +46,7 @@ describe('Client#stats', function () { expect(stats.nodes).to.be.an('array').that.is.not.empty const node: any = stats.nodes.pop() - expect(node.name).to.be.a('string').of.length(15) + expect(node.name).to.be.a('string') for (const connStats of [node.syncConnections, node.asyncConnections]) { expect(connStats.inPool).to.be.at.least(1) expect(connStats.inUse).to.be.at.least(0) diff --git a/ts-test/tests/test_helper.ts b/ts-test/tests/test_helper.ts index 1a39eb73..f23657f4 100644 --- a/ts-test/tests/test_helper.ts +++ b/ts-test/tests/test_helper.ts @@ -241,6 +241,23 @@ Aerospike.setDefaultLogging(config.log ?? {}) skipUnless(ctx, () => this.cluster.isVersionInRange(versionRange), `cluster version does not meet requirements: "${versionRange}"`) } + + export function skipUnlessVersionAndEnterprise (this: any, versionRange: any, ctx: Suite) { + skipUnless(ctx, () => { + console.log(this.cluster.isVersionInRange(versionRange)) + console.log((!this.cluster.isEnterprise())) + return (this.cluster.isVersionInRange(versionRange) && (this.cluster.isEnterprise())) }, `cluster version does not meet requirements: "${versionRange} and/or requires enterprise"`) + } + + export function skipUnlessVersionAndCommunity (this: any, versionRange: any, ctx: Suite) { + skipUnless(ctx, () => { + console.log(this.cluster.isVersionInRange(versionRange)) + console.log((!this.cluster.isEnterprise())) + return (this.cluster.isVersionInRange(versionRange) && (!this.cluster.isEnterprise())) + + }, `cluster version does not meet requirements: "${versionRange} and/or requires enterprise"`) + } + export function skipUnlessSupportsTtl(this: any, ctx: Suite) { skipUnless(ctx, () => this.cluster.supportsTtl(), 'test namespace does not support record TTLs') } diff --git a/tsconfig.tsbuildinfo b/tsconfig.tsbuildinfo new file mode 100644 index 00000000..10c73780 --- /dev/null +++ b/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"fileNames":["../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es5.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2015.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2016.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2017.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2018.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2019.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2020.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.dom.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2015.core.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2017.date.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2017.object.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2017.string.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2019.array.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2019.object.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2019.string.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2020.date.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2020.string.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.es2020.number.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.decorators.d.ts","../../../.nvm/versions/node/v18.20.4/lib/node_modules/typescript/lib/lib.decorators.legacy.d.ts","./typings/index.d.ts","./node_modules/@types/unist/index.d.ts","./node_modules/@types/hast/index.d.ts","./node_modules/@types/json5/index.d.ts","./node_modules/@types/mdast/index.d.ts","./node_modules/@types/node/compatibility/disposable.d.ts","./node_modules/@types/node/compatibility/indexable.d.ts","./node_modules/@types/node/compatibility/iterators.d.ts","./node_modules/@types/node/compatibility/index.d.ts","./node_modules/@types/node/ts5.6/globals.typedarray.d.ts","./node_modules/@types/node/ts5.6/buffer.buffer.d.ts","./node_modules/undici-types/header.d.ts","./node_modules/undici-types/readable.d.ts","./node_modules/undici-types/file.d.ts","./node_modules/undici-types/fetch.d.ts","./node_modules/undici-types/formdata.d.ts","./node_modules/undici-types/connector.d.ts","./node_modules/undici-types/client.d.ts","./node_modules/undici-types/errors.d.ts","./node_modules/undici-types/dispatcher.d.ts","./node_modules/undici-types/global-dispatcher.d.ts","./node_modules/undici-types/global-origin.d.ts","./node_modules/undici-types/pool-stats.d.ts","./node_modules/undici-types/pool.d.ts","./node_modules/undici-types/handlers.d.ts","./node_modules/undici-types/balanced-pool.d.ts","./node_modules/undici-types/agent.d.ts","./node_modules/undici-types/mock-interceptor.d.ts","./node_modules/undici-types/mock-agent.d.ts","./node_modules/undici-types/mock-client.d.ts","./node_modules/undici-types/mock-pool.d.ts","./node_modules/undici-types/mock-errors.d.ts","./node_modules/undici-types/proxy-agent.d.ts","./node_modules/undici-types/env-http-proxy-agent.d.ts","./node_modules/undici-types/retry-handler.d.ts","./node_modules/undici-types/retry-agent.d.ts","./node_modules/undici-types/api.d.ts","./node_modules/undici-types/interceptors.d.ts","./node_modules/undici-types/util.d.ts","./node_modules/undici-types/cookies.d.ts","./node_modules/undici-types/patch.d.ts","./node_modules/undici-types/websocket.d.ts","./node_modules/undici-types/eventsource.d.ts","./node_modules/undici-types/filereader.d.ts","./node_modules/undici-types/diagnostics-channel.d.ts","./node_modules/undici-types/content-type.d.ts","./node_modules/undici-types/cache.d.ts","./node_modules/undici-types/index.d.ts","./node_modules/@types/node/globals.d.ts","./node_modules/@types/node/assert.d.ts","./node_modules/@types/node/assert/strict.d.ts","./node_modules/@types/node/async_hooks.d.ts","./node_modules/@types/node/buffer.d.ts","./node_modules/@types/node/child_process.d.ts","./node_modules/@types/node/cluster.d.ts","./node_modules/@types/node/console.d.ts","./node_modules/@types/node/constants.d.ts","./node_modules/@types/node/crypto.d.ts","./node_modules/@types/node/dgram.d.ts","./node_modules/@types/node/diagnostics_channel.d.ts","./node_modules/@types/node/dns.d.ts","./node_modules/@types/node/dns/promises.d.ts","./node_modules/@types/node/domain.d.ts","./node_modules/@types/node/dom-events.d.ts","./node_modules/@types/node/events.d.ts","./node_modules/@types/node/fs.d.ts","./node_modules/@types/node/fs/promises.d.ts","./node_modules/@types/node/http.d.ts","./node_modules/@types/node/http2.d.ts","./node_modules/@types/node/https.d.ts","./node_modules/@types/node/inspector.d.ts","./node_modules/@types/node/module.d.ts","./node_modules/@types/node/net.d.ts","./node_modules/@types/node/os.d.ts","./node_modules/@types/node/path.d.ts","./node_modules/@types/node/perf_hooks.d.ts","./node_modules/@types/node/process.d.ts","./node_modules/@types/node/punycode.d.ts","./node_modules/@types/node/querystring.d.ts","./node_modules/@types/node/readline.d.ts","./node_modules/@types/node/readline/promises.d.ts","./node_modules/@types/node/repl.d.ts","./node_modules/@types/node/sea.d.ts","./node_modules/@types/node/sqlite.d.ts","./node_modules/@types/node/stream.d.ts","./node_modules/@types/node/stream/promises.d.ts","./node_modules/@types/node/stream/consumers.d.ts","./node_modules/@types/node/stream/web.d.ts","./node_modules/@types/node/string_decoder.d.ts","./node_modules/@types/node/test.d.ts","./node_modules/@types/node/timers.d.ts","./node_modules/@types/node/timers/promises.d.ts","./node_modules/@types/node/tls.d.ts","./node_modules/@types/node/trace_events.d.ts","./node_modules/@types/node/tty.d.ts","./node_modules/@types/node/url.d.ts","./node_modules/@types/node/util.d.ts","./node_modules/@types/node/v8.d.ts","./node_modules/@types/node/vm.d.ts","./node_modules/@types/node/wasi.d.ts","./node_modules/@types/node/worker_threads.d.ts","./node_modules/@types/node/zlib.d.ts","./node_modules/@types/node/ts5.6/index.d.ts"],"fileIdsList":[[56,98],[47,56,98],[56,95,98],[56,97,98],[56,98,103,133],[56,98,99,104,110,111,118,130,141],[56,98,99,100,110,118],[51,52,53,56,98],[56,98,101,142],[56,98,102,103,111,119],[56,98,103,130,138],[56,98,104,106,110,118],[56,97,98,105],[56,98,106,107],[56,98,110],[56,98,108,110],[56,97,98,110],[56,98,110,111,112,130,141],[56,98,110,111,112,125,130,133],[56,93,98,146],[56,93,98,106,110,113,118,130,141],[56,98,110,111,113,114,118,130,138,141],[56,98,113,115,130,138,141],[56,98,110,116],[56,98,117,141,146],[56,98,106,110,118,130],[56,98,119],[56,98,120],[56,97,98,121],[56,95,96,97,98,99,100,101,102,103,104,105,106,107,108,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147],[56,98,123],[56,98,124],[56,98,110,125,126],[56,98,125,127,142,144],[56,98,110,130,131,132,133],[56,98,130,132],[56,98,130,131],[56,98,133],[56,98,134],[56,95,98,130],[56,98,110,136,137],[56,98,136,137],[56,98,103,118,130,138],[56,98,139],[98],[54,55,56,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147],[56,98,118,140],[56,98,113,124,141],[56,98,103,142],[56,98,130,143],[56,98,117,144],[56,98,145],[56,98,103,110,112,121,130,141,144,146],[56,98,130,147],[56,65,69,98,141],[56,65,98,130,141],[56,60,98],[56,62,65,98,138,141],[56,98,118,138],[56,98,148],[56,60,98,148],[56,62,65,98,118,141],[56,57,58,61,64,98,110,130,141],[56,65,72,98],[56,57,63,98],[56,65,86,87,98],[56,61,65,98,133,141,148],[56,86,98,148],[56,59,60,98,148],[56,65,98],[56,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88,89,90,91,92,98],[56,65,80,98],[56,65,72,73,98],[56,63,65,73,74,98],[56,64,98],[56,57,60,65,98],[56,65,69,73,74,98],[56,69,98],[56,63,65,68,98,141],[56,57,62,65,72,98],[56,98,130],[56,60,65,86,98,146,148]],"fileInfos":[{"version":"44e584d4f6444f58791784f1d530875970993129442a847597db702a073ca68c","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"9a68c0c07ae2fa71b44384a839b7b8d81662a236d4b9ac30916718f7510b1b2d","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"9e8ca8ed051c2697578c023d9c29d6df689a083561feba5c14aedee895853999","affectsGlobalScope":true,"impliedFormat":1},{"version":"6920e1448680767498a0b77c6a00a8e77d14d62c3da8967b171f1ddffa3c18e4","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"45d8ccb3dfd57355eb29749919142d4321a0aa4df6acdfc54e30433d7176600a","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"93495ff27b8746f55d19fcbcdbaccc99fd95f19d057aed1bd2c0cafe1335fbf0","affectsGlobalScope":true,"impliedFormat":1},{"version":"6fc23bb8c3965964be8c597310a2878b53a0306edb71d4b5a4dfe760186bcc01","affectsGlobalScope":true,"impliedFormat":1},{"version":"ea011c76963fb15ef1cdd7ce6a6808b46322c527de2077b6cfdf23ae6f5f9ec7","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"4738f2420687fd85629c9efb470793bb753709c2379e5f85bc1815d875ceadcd","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"9fc46429fbe091ac5ad2608c657201eb68b6f1b8341bd6d670047d32ed0a88fa","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"1a94697425a99354df73d9c8291e2ecd4dddd370aed4023c2d6dee6cccb32666","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"bf14a426dbbf1022d11bd08d6b8e709a2e9d246f0c6c1032f3b2edb9a902adbe","affectsGlobalScope":true,"impliedFormat":1},{"version":"e3f9fc0ec0b96a9e642f11eda09c0be83a61c7b336977f8b9fdb1e9788e925fe","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"479553e3779be7d4f68e9f40cdb82d038e5ef7592010100410723ceced22a0f7","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"33358442698bb565130f52ba79bfd3d4d484ac85fe33f3cb1759c54d18201393","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},"3393401d6e8160a105adc80feccd0b57b93198ad5689bcbd90966322f302bb72",{"version":"89121c1bf2990f5219bfd802a3e7fc557de447c62058d6af68d6b6348d64499a","impliedFormat":1},{"version":"79b4369233a12c6fa4a07301ecb7085802c98f3a77cf9ab97eee27e1656f82e6","impliedFormat":1},{"version":"96d14f21b7652903852eef49379d04dbda28c16ed36468f8c9fa08f7c14c9538","impliedFormat":1},{"version":"d4a22007b481fe2a2e6bfd3a42c00cd62d41edb36d30fc4697df2692e9891fc8","impliedFormat":1},{"version":"70521b6ab0dcba37539e5303104f29b721bfb2940b2776da4cc818c07e1fefc1","affectsGlobalScope":true,"impliedFormat":1},{"version":"030e350db2525514580ed054f712ffb22d273e6bc7eddc1bb7eda1e0ba5d395e","affectsGlobalScope":true,"impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"613b21ccdf3be6329d56e6caa13b258c842edf8377be7bc9f014ed14cdcfc308","affectsGlobalScope":true,"impliedFormat":1},{"version":"2d1319e6b5d0efd8c5eae07eb864a00102151e8b9afddd2d45db52e9aae002c4","affectsGlobalScope":true,"impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"24bd580b5743dc56402c440dc7f9a4f5d592ad7a419f25414d37a7bfe11e342b","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"6bdc71028db658243775263e93a7db2fd2abfce3ca569c3cca5aee6ed5eb186d","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"e61be3f894b41b7baa1fbd6a66893f2579bfad01d208b4ff61daef21493ef0a8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"81184fe8e67d78ac4e5374650f0892d547d665d77da2b2f544b5d84729c4a15d","affectsGlobalScope":true,"impliedFormat":1},{"version":"f52e8dacc97d71dcc96af29e49584353f9c54cb916d132e3e768d8b8129c928d","impliedFormat":1},{"version":"7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419","impliedFormat":1},{"version":"76103716ba397bbb61f9fa9c9090dca59f39f9047cb1352b2179c5d8e7f4e8d0","impliedFormat":1},{"version":"53eac70430b30089a3a1959d8306b0f9cfaf0de75224b68ef25243e0b5ad1ca3","affectsGlobalScope":true,"impliedFormat":1},{"version":"4314c7a11517e221f7296b46547dbc4df047115b182f544d072bdccffa57fc72","impliedFormat":1},{"version":"115971d64632ea4742b5b115fb64ed04bcaae2c3c342f13d9ba7e3f9ee39c4e7","impliedFormat":1},{"version":"c2510f124c0293ab80b1777c44d80f812b75612f297b9857406468c0f4dafe29","affectsGlobalScope":true,"impliedFormat":1},{"version":"a40826e8476694e90da94aa008283a7de50d1dafd37beada623863f1901cb7fb","impliedFormat":1},{"version":"86956cc2eb9dd371d6fab493d326a574afedebf76eef3fa7833b8e0d9b52d6f1","affectsGlobalScope":true,"impliedFormat":1},{"version":"24642567d3729bcc545bacb65ee7c0db423400c7f1ef757cab25d05650064f98","impliedFormat":1},{"version":"e6f5a38687bebe43a4cef426b69d34373ef68be9a6b1538ec0a371e69f309354","impliedFormat":1},{"version":"a6bf63d17324010ca1fbf0389cab83f93389bb0b9a01dc8a346d092f65b3605f","impliedFormat":1},{"version":"e009777bef4b023a999b2e5b9a136ff2cde37dc3f77c744a02840f05b18be8ff","impliedFormat":1},{"version":"1e0d1f8b0adfa0b0330e028c7941b5a98c08b600efe7f14d2d2a00854fb2f393","impliedFormat":1},{"version":"ee1ee365d88c4c6c0c0a5a5701d66ebc27ccd0bcfcfaa482c6e2e7fe7b98edf7","affectsGlobalScope":true,"impliedFormat":1},{"version":"875928df2f3e9a3aed4019539a15d04ff6140a06df6cd1b2feb836d22a81eaca","affectsGlobalScope":true,"impliedFormat":1},{"version":"e9ad08a376ac84948fcca0013d6f1d4ae4f9522e26b91f87945b97c99d7cc30b","impliedFormat":1},{"version":"eaf9ee1d90a35d56264f0bf39842282c58b9219e112ac7d0c1bce98c6c5da672","impliedFormat":1},{"version":"c15c4427ae7fd1dcd7f312a8a447ac93581b0d4664ddf151ecd07de4bf2bb9d7","impliedFormat":1},{"version":"5135bdd72cc05a8192bd2e92f0914d7fc43ee077d1293dc622a049b7035a0afb","impliedFormat":1},{"version":"4f80de3a11c0d2f1329a72e92c7416b2f7eab14f67e92cac63bb4e8d01c6edc8","impliedFormat":1},{"version":"6d386bc0d7f3afa1d401afc3e00ed6b09205a354a9795196caed937494a713e6","impliedFormat":1},{"version":"75c3400359d59fae5aed4c4a59fcd8a9760cf451e25dc2174cb5e08b9d4803e2","affectsGlobalScope":true,"impliedFormat":1},{"version":"94c4187083503a74f4544503b5a30e2bd7af0032dc739b0c9a7ce87f8bddc7b9","impliedFormat":1},{"version":"b1b6ee0d012aeebe11d776a155d8979730440082797695fc8e2a5c326285678f","impliedFormat":1},{"version":"45875bcae57270aeb3ebc73a5e3fb4c7b9d91d6b045f107c1d8513c28ece71c0","impliedFormat":1},{"version":"3eb62baae4df08c9173e6903d3ca45942ccec8c3659b0565684a75f3292cffbb","affectsGlobalScope":true,"impliedFormat":1},{"version":"a85683ef86875f4ad4c6b7301bbcc63fb379a8d80d3d3fd735ee57f48ef8a47e","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f16a7e4deafa527ed9995a772bb380eb7d3c2c0fd4ae178c5263ed18394db2c","impliedFormat":1},{"version":"c6b4e0a02545304935ecbf7de7a8e056a31bb50939b5b321c9d50a405b5a0bba","impliedFormat":1},{"version":"fab29e6d649aa074a6b91e3bdf2bff484934a46067f6ee97a30fcd9762ae2213","impliedFormat":1},{"version":"8145e07aad6da5f23f2fcd8c8e4c5c13fb26ee986a79d03b0829b8fce152d8b2","impliedFormat":1},{"version":"e1120271ebbc9952fdc7b2dd3e145560e52e06956345e6fdf91d70ca4886464f","impliedFormat":1},{"version":"15c5e91b5f08be34a78e3d976179bf5b7a9cc28dc0ef1ffebffeb3c7812a2dca","impliedFormat":1},{"version":"a8f06c2382a30b7cb89ad2dfc48fc3b2b490f3dafcd839dadc008e4e5d57031d","impliedFormat":1},{"version":"553870e516f8c772b89f3820576152ebc70181d7994d96917bb943e37da7f8a7","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"93452d394fdd1dc551ec62f5042366f011a00d342d36d50793b3529bfc9bd633","impliedFormat":1},{"version":"745c4240220559bd340c8aeb6e3c5270a709d3565e934dc22a69c304703956bc","affectsGlobalScope":true,"impliedFormat":1},{"version":"2754d8221d77c7b382096651925eb476f1066b3348da4b73fe71ced7801edada","impliedFormat":1},{"version":"9212c6e9d80cb45441a3614e95afd7235a55a18584c2ed32d6c1aca5a0c53d93","affectsGlobalScope":true,"impliedFormat":1},{"version":"bef91efa0baea5d0e0f0f27b574a8bc100ce62a6d7e70220a0d58af6acab5e89","affectsGlobalScope":true,"impliedFormat":1},{"version":"282fd2a1268a25345b830497b4b7bf5037a5e04f6a9c44c840cb605e19fea841","impliedFormat":1},{"version":"5360a27d3ebca11b224d7d3e38e3e2c63f8290cb1fcf6c3610401898f8e68bc3","impliedFormat":1},{"version":"66ba1b2c3e3a3644a1011cd530fb444a96b1b2dfe2f5e837a002d41a1a799e60","impliedFormat":1},{"version":"7e514f5b852fdbc166b539fdd1f4e9114f29911592a5eb10a94bb3a13ccac3c4","impliedFormat":1},{"version":"7d6ff413e198d25639f9f01f16673e7df4e4bd2875a42455afd4ecc02ef156da","affectsGlobalScope":true,"impliedFormat":1},{"version":"6bd91a2a356600dee28eb0438082d0799a18a974a6537c4410a796bab749813c","affectsGlobalScope":true,"impliedFormat":1},{"version":"f689c4237b70ae6be5f0e4180e8833f34ace40529d1acc0676ab8fb8f70457d7","impliedFormat":1},{"version":"ae25afbbf1ed5df63a177d67b9048bf7481067f1b8dc9c39212e59db94fc9fc6","impliedFormat":1},{"version":"ac5ed35e649cdd8143131964336ab9076937fa91802ec760b3ea63b59175c10a","impliedFormat":1},{"version":"52a8e7e8a1454b6d1b5ad428efae3870ffc56f2c02d923467f2940c454aa9aec","affectsGlobalScope":true,"impliedFormat":1},{"version":"78dc0513cc4f1642906b74dda42146bcbd9df7401717d6e89ea6d72d12ecb539","impliedFormat":1},{"version":"171fd8807643c46a9d17e843959abdf10480d57d60d38d061fb44a4c8d4a8cc4","impliedFormat":1}],"root":[46],"options":{"allowJs":true,"alwaysStrict":true,"declaration":true,"emitDeclarationOnly":true,"emitDecoratorMetadata":true,"esModuleInterop":true,"experimentalDecorators":true,"importHelpers":true,"module":1,"noEmitHelpers":true,"noImplicitAny":false,"removeComments":true,"skipLibCheck":true,"strict":true,"target":1},"referencedMap":[[44,1],[45,1],[8,1],[10,1],[9,1],[2,1],[11,1],[12,1],[13,1],[14,1],[15,1],[16,1],[17,1],[18,1],[3,1],[19,1],[4,1],[20,1],[24,1],[21,1],[22,1],[23,1],[25,1],[26,1],[27,1],[5,1],[28,1],[29,1],[30,1],[31,1],[6,1],[35,1],[32,1],[33,1],[34,1],[36,1],[7,1],[37,1],[42,1],[43,1],[38,1],[39,1],[40,1],[41,1],[1,1],[48,2],[49,1],[50,2],[95,3],[96,3],[97,4],[98,5],[99,6],[100,7],[51,1],[54,8],[52,1],[53,1],[101,9],[102,10],[103,11],[104,12],[105,13],[106,14],[107,14],[109,15],[108,16],[110,17],[111,18],[112,19],[94,20],[113,21],[114,22],[115,23],[116,24],[117,25],[118,26],[119,27],[120,28],[121,29],[122,30],[123,31],[124,32],[125,33],[126,33],[127,34],[128,1],[129,1],[130,35],[132,36],[131,37],[133,38],[134,39],[135,40],[136,41],[137,42],[138,43],[139,44],[56,45],[55,1],[148,46],[140,47],[141,48],[142,49],[143,50],[144,51],[145,52],[146,53],[147,54],[47,1],[72,55],[82,56],[71,55],[92,57],[63,58],[62,59],[91,60],[85,61],[90,62],[65,63],[79,64],[64,65],[88,66],[60,67],[59,60],[89,68],[61,69],[66,70],[67,1],[70,70],[57,1],[93,71],[83,72],[74,73],[75,74],[77,75],[73,76],[76,77],[86,60],[68,78],[69,79],[78,80],[58,81],[81,72],[80,70],[84,1],[87,82],[46,81]],"version":"5.6.3"} \ No newline at end of file diff --git a/typings/index.d.ts b/typings/index.d.ts index 381cf4be..08468ffe 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -41,7 +41,6 @@ export enum ScalarOperations { * Represents a basic value in an Aerospike bin. */ export type PartialAerospikeBinValue = null | undefined | boolean | string | number | Double | BigInt | Buffer | GeoJSON | Array | object; - /** * Represents an object containing one or more `AerospikeBinValues` with associated string keys. */ @@ -49,6 +48,8 @@ export type AerospikeBins = { [key: string]: AerospikeBinValue }; +export const _transactionPool: any; + /** * Represents a complete Aerospike bin value. Bin values can included nested lists and maps. */ @@ -282,6 +283,7 @@ export type TypedCallback = (error?: AerospikeError, result?: T) => void; * }) */ export class AerospikeRecord { + /** * Unique record identifier. * @@ -314,6 +316,488 @@ export class AerospikeRecord { constructor(key: KeyOptions, bins: AerospikeBins, metadata?: RecordMetadata); } +/** + * Multi-record transaction (MRT) class. Each command in the MRT must use the same namespace. + * + * note: By default, open transactions are destroyed when the final client in a process is closed. + * If you need your transaction to persist after the last client has been closed, provide `false` for the + * destroy Transactions argument in {@link Client#close}. For more information on memory management, see {@link Transaction.destroyAll}. + * + * @example Commit a simple transaction. + * + * const Aerospike = require('aerospike') + * + * // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE! + * var config = { + * hosts: '192.168.33.10:3000', + * // Timeouts disabled, latency dependent on server location. Configure as needed. + * policies: { + * write : new Aerospike.WritePolicy({socketTimeout : 0, totalTimeout : 0}), + * } + * } + * + * let bins = { + * int: 123, + * double: 3.1415, + * string: 'xyz', + * bytes: Buffer.from('hello world!'), + * list: [1, 2, 3], + * map: {num: 123, str: 'abc', list: ['a', 'b', 'c']} + * } + * let meta = { + * ttl: 386400 // 1 day + * } + * let key = new Aerospike.Key('test', 'demo', 'myKey') + * + * let policy = { + * txn: mrt + * }; + * ;(async () => { + * let client = await Aerospike.connect(config) + + * let mrt = new Aerospike.Transaction() + * + + * + * await client.put(key, bins, meta, policy) + * + * let get_result = await client.get(key1, policy) + * + * let result = await client.commit(mrt) + * await client.close() + * })(); + * + * @example Abort a transaction. + * + * const Aerospike = require('aerospike') + * + * // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE! + * var config = { + * hosts: '192.168.33.10:3000', + * // Timeouts disabled, latency dependent on server location. Configure as needed. + * policies: { + * read : new Aerospike.ReadPolicy({socketTimeout : 0, totalTimeout : 0}), + * write : new Aerospike.WritePolicy({socketTimeout : 0, totalTimeout : 0}), + * } + * } + * + * let key1 = new Aerospike.Key('test', 'demo', 'myKey') + * let key2 = new Aerospike.Key('test', 'demo', 'myKey') + * + * let record1 = {abc: 123} + * let record2 = {def: 456} + * + * ;(async () => { + * let client = await Aerospike.connect(config) + * + * const policy = { + * txn: mrt + * } + * + * await client.put(key4, record2, meta, policy) + * + * const policyRead = { + * txn: mrt + * } + * + * let get_result = await client.get(key1, policy) // Will reflect the new value recently put. + * + * await client.put(key2, record2, meta, policy) + * + * let result = await client.abort(mrt) + * + * get_result = await client.get(key4) // Will reset to the value present before transaction started. + * + * get_result = await client.get(key5) // Will reset to the value present before transaction started. + * + * await client.close() + * })(); + * + * @since v6.0.0 + */ +export class Transaction { + /** + * Construct a new Aerospike Transaction instance. + */ + public constructor(reads_capacity?: number, writes_capacity?: number); + + /** + * Transaction state enumeration + */ + static state: { + /** + * Transaction is still open. + */ + OPEN: 0, + /** + * Transaction was verified. + */ + + VERIFIED: 1, + /** + * Transaction was commited. + */ + COMMITTED: 2, + + /** + * Transaction was aborted. + */ + ABORTED: 3 + }; + + + /** + * Default multi-record transaction capacity values. + */ + static capacity: { + /** + * Contains the default reeadDefault for aerospike.Transaction + */ + READ_DEFAULT: 128, + /** + * Contains the default writeCapacity for aerospike.Transaction + */ + + WRITE_DEFAULT: 128, + }; + + /** + * Multi-record transaction abort status code. + */ + static abortStatus: { + /** + * Abort succeeded. + */ + OK: 0, + + /** + * Transaction has already been committed. + */ + ALREADY_COMMITTED: 1, + /** + * Transaction has already been aborted. + */ + ALREADY_ABORTED: 2, + /** + * Client roll back abandoned. Server will eventually abort the transaction. + */ + ROLL_BACK_ABANDONED: 3, + + /** + * Transaction has been rolled back, but client transaction close was abandoned. + * Server will eventually close the transaction. + */ + CLOSE_ABANDONED: 4 + }; + + + /** + * Multi-record transaction commit status code. + */ + static commitStatus: { + /** + * Commit succeeded. + */ + OK: 0, + + /** + * Transaction has already been committed. + */ + ALREADY_COMMITTED: 1, + /** + * Transaction has already been aborted. + */ + ALREADY_ABORTED: 2, + /** + * Transaction verify failed. Transaction will be aborted. + */ + VERIFY_FAILED: 3, + + /** + * Transaction mark roll forward abandoned. Transaction will be aborted when error is not in doubt. + * If the error is in doubt (usually timeout), the commit is in doubt. + */ + MARK_ROLL_FORWARD_ABANDONED: 4, + + /** + * Client roll forward abandoned. Server will eventually commit the transaction. + */ + ROLL_FORWARD_ABANDONED: 5, + + /** + * Transaction has been rolled forward, but client transaction close was abandoned. + * Server will eventually close the transaction. + */ + CLOSE_ABANDONED: 6 + }; + + private prepareToClose(): void; + private close(): void; + /** + * Destroys all open transactions + * + * @remarks + * + * + * + * Use of this API is only necessary when the client is closed with + * the destroyTransactions parameter set is set to false. + * See example below for usage details. + * + * To avoid using this API, close the final connected client in the process + * with destroyTransactions set to true (default is true), and the transaction will be destroyed automatically. + * + * @example + * + * const Aerospike = require('aerospike') + * const Key = Aerospike.Key + * + * // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE! + * var config = { + * hosts: '192.168.33.10:3000', + * // Timeouts disabled, latency dependent on server location. Configure as needed. + * policies: { + * batch : new Aerospike.BatchPolicy({socketTimeout : 0, totalTimeout : 0}), + * } + * } + * + * ;(async () => { + * let mrt1 = new Aerospike.Transaction() + * let client = await Aerospike.connect(config) + * client.close(false, true) // `destroyTransactions is true`, mrt1 is no longer usable. + * + * let mrt2 = new Aerospike.Transaction() + * client = await Aerospike.connect(config) + * client.close(false, true) // `destroyTransactions is false`, mrt2 can still be used. + * + * // In order to properly manage the memory at this point, do one of two things before the process exits: + * + * // 1: call destroyAll() to destroy all outstanding transactions from this process. + * mrt1.destroyAll() + * + * // 2: reopen and close the final connected client with destroyTransactions + * // client = await Aerospike.connect(config) + * // client.close() // Default will destory the transactions + * + * })(); + * + * @since v6.0.0 + */ + public destroyAll(): void; + /** + * Get ID for this transaction + * + * @returns MRT ID + * + * @example + * + * const Aerospike = require('aerospike') + * const Key = Aerospike.Key + * + * // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE! + * var config = { + * hosts: '192.168.33.10:3000', + * // Timeouts disabled, latency dependent on server location. Configure as needed. + * policies: { + * batch : new Aerospike.BatchPolicy({socketTimeout : 0, totalTimeout : 0}), + * } + * } + * + * ;(async () => { + * // Establishes a connection to the server + * let mrt = new Aerospike.Transaction() + * let id = mrt.getId() + * })(); + * + * @since v6.0.0 + */ + public getId(): number; + + /** + * Get inDoubt status for this transaction. + * + * @returns MRT inDoubt status + * + * @example + * + * const Aerospike = require('aerospike') + * const Key = Aerospike.Key + * + * // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE! + * var config = { + * hosts: '192.168.33.10:3000', + * // Timeouts disabled, latency dependent on server location. Configure as needed. + * policies: { + * batch : new Aerospike.BatchPolicy({socketTimeout : 0, totalTimeout : 0}), + * } + * } + * + * ;(async () => { + * // Establishes a connection to the server + * let mrt = new Aerospike.Transaction() + * let inDoubt = mrt.getInDoubt() + * })(); + * + * @since v6.0.0 + */ + public getInDoubt(): boolean; + /** + * + * Gets the expected number of record reads in the MRT. Minimum value is 16. + * + * @returns number of records reads in the MRT. + * + * @example + * + * const Aerospike = require('aerospike') + * const Key = Aerospike.Key + * + * // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE! + * var config = { + * hosts: '192.168.33.10:3000', + * // Timeouts disabled, latency dependent on server location. Configure as needed. + * policies: { + * batch : new Aerospike.BatchPolicy({socketTimeout : 0, totalTimeout : 0}), + * } + * } + * + * ;(async () => { + * // Establishes a connection to the server + * let mrt = new Aerospike.Transaction() + * let readsCapacity = mrt.getReadsCapacity() + * console.log(readsCapacity) // 128 + * })(); + * + * @since v6.0.0 + */ + public getReadsCapacity(): number; + /** + * + * Gets the current state of the MRT. + * + * @returns MRT timeout in seconds + * + * @example + * + * const Aerospike = require('aerospike') + * const Key = Aerospike.Key + * + * // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE! + * var config = { + * hosts: '192.168.33.10:3000', + * // Timeouts disabled, latency dependent on server location. Configure as needed. + * policies: { + * batch : new Aerospike.BatchPolicy({socketTimeout : 0, totalTimeout : 0}), + * } + * } + * + * ;(async () => { + * // Establishes a connection to the server + * let mrt = new Aerospike.Transaction() + * let state = mrt.getState() + * + * })(); + * + */ + public getState(): number; + /** + * + * Gets the current MRT timeout value. + * + * @returns MRT timeout in seconds + * + * @example + * + * const Aerospike = require('aerospike') + * const Key = Aerospike.Key + * + * // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE! + * var config = { + * hosts: '192.168.33.10:3000', + * // Timeouts disabled, latency dependent on server location. Configure as needed. + * policies: { + * batch : new Aerospike.BatchPolicy({socketTimeout : 0, totalTimeout : 0}), + * } + * } + * + * ;(async () => { + * // Establishes a connection to the server + * let mrt = new Aerospike.Transaction() + * let timeout = mrt.getTimeout() + * })(); + * + * @since v6.0.0 + */ + public getTimeout(): number; + /** + * + * Gets the expected number of record reads in the MRT. Minimum value is 16. + * + * @returns number of records reads in the MRT. + * + * @example + * + * const Aerospike = require('aerospike') + * const Key = Aerospike.Key + * + * // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE! + * var config = { + * hosts: '192.168.33.10:3000', + * // Timeouts disabled, latency dependent on server location. Configure as needed. + * policies: { + * batch : new Aerospike.BatchPolicy({socketTimeout : 0, totalTimeout : 0}), + * } + * } + * + * ;(async () => { + * // Establishes a connection to the server + * let mrt = new Aerospike.Transaction() + * let writesCapacity = mrt.getWritesCapacity() + * console.log(writesCapacity) // 128 + * })(); + * + * @since v6.0.0 + */ + public getWritesCapacity(): number; + /** + * + * Set MRT timeout in seconds. The timer starts when the MRT monitor record is created. This occurs when the first command in the MRT is executed. + * + * If the timeout is reached before a commit or abort is called, the server will expire and rollback the MRT. + * + * If the MRT timeout is zero, the server configuration mrt-duration is used. The default mrt-duration is 10 seconds. + * + * @param timeout - MRT timeout in seconds + * + * @example + * + * const Aerospike = require('aerospike') + * const Key = Aerospike.Key + * + * // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE! + * var config = { + * hosts: '192.168.33.10:3000', + * // Timeouts disabled, latency dependent on server location. Configure as needed. + * policies: { + * batch : new Aerospike.BatchPolicy({socketTimeout : 0, totalTimeout : 0}), + * } + * } + * + * ;(async () => { + * // Establishes a connection to the server + * let mrt = new Aerospike.Transaction() + * mrt.setTimeout(5) // Set timeout for 5 seconds! + * + * console.log(mrt.getTimeout()) // 5 + * })(); + * + */ + public setTimeout(timeout: number): void; +} + + + + /** * In the Aerospike database, each record (similar to a row in a relational database) stores * data using one or more bins (like columns in a relational database). The major difference @@ -1435,12 +1919,18 @@ export namespace policy { * @default 1000 */ public totalTimeout?: number; + /** + * Multi-record command identifier. See {@link Transaction} for more information. + * + * @default null (no transaction) + */ + public txn?: Transaction; + /** * Initializes a new BasePolicy from the provided policy values. * * @param props - BasePolicy values */ - constructor(props?: BasePolicyOptions); } @@ -3944,6 +4434,136 @@ export class Client extends EventEmitter { * result returned by the Record UDF function call. */ public apply(key: KeyOptions, udfArgs: UDF, policy: policy.ApplyPolicy | null, callback: TypedCallback): void; + /** + * + * @param transaction - {@link Transaction} instance. + * @param callback - This function will be called with the + * result returned by the abort function call. + * + * + * @since v6.0.0 + * + * + * @example Abort a transaction. + * + * const Aerospike = require('aerospike') + * + * // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE! + * var config = { + * hosts: '192.168.33.10:3000', + * // Timeouts disabled, latency dependent on server location. Configure as needed. + * policies: { + * read : new Aerospike.ReadPolicy({socketTimeout : 0, totalTimeout : 0}), + * write : new Aerospike.WritePolicy({socketTimeout : 0, totalTimeout : 0}), + * } + * } + * + * let key1 = new Aerospike.Key('test', 'demo', 'myKey') + * let key2 = new Aerospike.Key('test', 'demo', 'myKey') + * + * let record1 = {abc: 123} + * let record2 = {def: 456} + * + * ;(async () => { + * let client = await Aerospike.connect(config) + * + * const policy = { + * txn: mrt + * } + * + * await client.put(key4, record2, meta, policy) + * + * const policyRead = { + * txn: mrt + * } + * + * let get_result = await client.get(key1, policy) // Will reflect the new value recently put. + * + * await client.put(key2, record2, meta, policy) + * + * let result = await client.abort(mrt) + * + * get_result = await client.get(key4) // Will reset to the value present before transaction started. + * + * get_result = await client.get(key5) // Will reset to the value present before transaction started. + * + * await client.close() + * })(); + */ + public abort(transaction: Transaction, callback: Function): void; + /** + * + * @param transaction - {@link Transaction} instance. + * + * @returns A Promise that resolves to the value returned by abort. + * + */ + public abort(transaction: Transaction): Promise< typeof Transaction.abortStatus[keyof typeof Transaction.abortStatus]>; + /** + * + * @param transaction - {@link Transaction} instance. + * @param callback - This function will be called with the + * result returned by the commit function call. + * + * + * @since v6.0.0 + * + * + * @example Commit a simple transaction. + * + * const Aerospike = require('aerospike') + * + * // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE! + * var config = { + * hosts: '192.168.33.10:3000', + * // Timeouts disabled, latency dependent on server location. Configure as needed. + * policies: { + * write : new Aerospike.WritePolicy({socketTimeout : 0, totalTimeout : 0}), + * } + * } + * + * let bins = { + * int: 123, + * double: 3.1415, + * string: 'xyz', + * bytes: Buffer.from('hello world!'), + * list: [1, 2, 3], + * map: {num: 123, str: 'abc', list: ['a', 'b', 'c']} + * } + * let meta = { + * ttl: 386400 // 1 day + * } + * let key1 = new Aerospike.Key('test', 'demo', 'myKey1') + * let key2 = new Aerospike.Key('test', 'demo', 'myKey2') + * + * let policy = { + * txn: mrt + * }; + * ;(async () => { + * let client = await Aerospike.connect(config) + + * let mrt = new Aerospike.Transaction() + * + + * + * await client.put(key1, bins, meta, policy) + * await client.put(key2, bins, meta, policy) + * let get_result = await client.get(key1, policy) + * + * let result = await client.commit(mrt) + * await client.close() + * })(); + */ + public commit(transaction: Transaction, callback: Function): void; + /** + * + * @param transaction - {@link Transaction} instance. + * + * @returns A Promise that resolves to the {@link Transaction.commitStatus} returned by commit. + * + */ + public commit(transaction: Transaction): Promise< typeof Transaction.commitStatus[keyof typeof Transaction.commitStatus]>; + /** * Checks the existance of a record in the database cluster. * @@ -4873,6 +5493,7 @@ export class Client extends EventEmitter { * function is provided, the method returns a Promise instead. */ public select(key: KeyOptions, bins: string[], policy: policy.ReadPolicy | null, callback: TypedCallback): void; + /** * Removes records in specified namespace/set efficiently. * @@ -7763,6 +8384,12 @@ export interface BasePolicyOptions { * @default 1000 */ totalTimeout?: number; + /** + * Multi-record command identifier. See {@link Transaction} for more information. + * + * @default null (no transaction) + */ + txn?: Transaction; } @@ -9842,7 +10469,15 @@ export enum batchType { /** * Indicates that a {@link Record} instance is used in a batch for removal operations. */ - BATCH_REMOVE + BATCH_REMOVE, + /** + * Indicates that a {@link Record} instance is used in a batch for transaction verfication operations. + */ + BATCH_TXN_VERIFY, + /** + * Indicates that a {@link Record} instance is used in a batch for transaction rolling operations. + */ + BATCH_TXN_ROLL } /** @@ -15451,6 +16086,14 @@ export namespace filter { declare namespace statusNamespace { + /** + * Multi-record transaction failed. + */ + export const AEROSPIKE_TXN_FAILED = -17; + /** + * Multi-record transaction failed. + */ + export const TXN_FAILED = -17; /** * One or more keys failed in a batch. */ @@ -15831,6 +16474,14 @@ declare namespace statusNamespace { * Write command loses conflict to XDR. */ export const LOST_CONFLICT = 28; + /** + * Write can't complete until XDR finishes shipping. + */ + export const AEROSPIKE_XDR_KEY_BUSY = 32; + /** + * Write can't complete until XDR finishes shipping. + */ + export const XDR_KEY_BUSY = 32; /** * There are no more records left for query. */ @@ -16031,6 +16682,56 @@ x */ * Generic UDF error. */ export const ERR_UDF = 100; + /** + * MRT record blocked by a different transaction. + */ + export const AEROSPIKE_MRT_BLOCKED = 120; + /** + * MRT record blocked by a different transaction. + */ + export const MRT_BLOCKED = 120; + /** + * MRT read version mismatch identified during commit. + * Some other command changed the record outside of the transaction. + */ + export const AEROSPIKE_MRT_VERSION_MISMATCH = 121; + /** + * MRT read version mismatch identified during commit. + * Some other command changed the record outside of the transaction. + */ + export const MRT_VERSION_MISMATCH = 121; + /** + * MRT deadline reached without a successful commit or abort. + */ + export const AEROSPIKE_MRT_EXPIRED = 122; + /** + * MRT deadline reached without a successful commit or abort. + */ + export const MRT_EXPIRED = 122; + /** + * MRT write command limit (4096) exceeded. + */ + export const AEROSPIKE_MRT_TOO_MANY_WRITES = 123; + /** + * MRT write command limit (4096) exceeded. + */ + export const MRT_TOO_MANY_WRITES = 123; + /** + * MRT was already committed. + */ + export const AEROSPIKE_MRT_COMMITTED = 124; + /** + * MRT was already committed. + */ + export const MRT_COMMITTED = 124; + /** + * MRT was already aborted. + */ + export const AEROSPIKE_MRT_ABORTED = 125; + /** + * MRT was already aborted. + */ + export const MRT_ABORTED = 125; /** * Batch functionality has been disabled. */