diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..add1e2df0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,33 @@ +#.dockerignore +*~ +Dockerfile +.git/ + +#.gitignore +*.dylib +*.so +*.o +*.lo +*.Makefile +*.target.gyp.mk +lib/binding +build +out +Release +Debug +node_modules +.deps +Makefile.gyp +gyp-mac-tool +.dirstamp +npm-debug.log +test/support/big.db +test/tmp +test/nw/app.nw +.DS_Store +.idea +.dtps +local.env +.mason +.eslintrc.js +setup.sh \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..2303c3d4b --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,13 @@ +module.exports = { + "extends": "eslint:recommended", + "env": { + "es2017": true, + "node": true + }, + "rules": { + "indent": ["error", 4], + "linebreak-style": ["error", "unix"], + "semi": ["error", "always"], + "no-cond-assign": ["error", "always"] + } +}; diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 000000000..b007fcc27 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,14 @@ +# Contributing + +General guidelines for contributing to node-sqlite3 + +## Install Help + +If you've landed here due to a failed install of `node-sqlite3` then feel free to create a [new issue](https://github.com/tryghost/node-sqlite3/issues/new) to ask for help. The most likely problem is that we do not yet provide pre-built binaries for your particular platform and so the `node-sqlite3` install attempted a source compile but failed because you are missing the [dependencies for node-gyp](https://github.com/nodejs/node-gyp#installation). Provide as much detail on your problem as possible and we'll try to help. Include: + + - Logs of failed install (preferably from running `npm install sqlite3 --loglevel=info`) + - Version of `node-sqlite3` you tried to install + - Node version you are running + - Operating system and architecture you are running, e.g. `Windows 7 64 bit`. + +The release process is documented in the wiki: https://github.com/TryGhost/node-sqlite3/wiki/Release-process diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 000000000..52634368b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,50 @@ +name: 🐛 Bug report +description: Report a reproducible issue +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + ## Welcome 👋 + Thank you for taking the time to fill out a bug report 🙂 + + The more information you provide, the easier & quicker it is for us to diagnose the problem. + + Please search the existing issues and recent releases to make sure your problem hasn't already been solved. + - type: textarea + id: summary + attributes: + label: Issue Summary + description: Explain what's wrong + validations: + required: true + - type: textarea + id: reproduction + attributes: + label: Steps to Reproduce + description: Also tell us, what did you expect to happen? + placeholder: | + 1. This is the first step... + 2. This is the second step, etc. + validations: + required: true + - type: input + id: version + attributes: + label: Version + description: What version of `node-sqlite3` are you using? + validations: + required: true + - type: input + id: node + attributes: + label: Node.js Version + validations: + required: true + - type: input + id: os + attributes: + label: How did you install the library? + description: Provide details of your operating system and architecture + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..729470a7d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: 📖 API documentation + url: https://github.com/TryGhost/node-sqlite3/wiki/API + about: Documentation for the `node-sqlite3` API diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 000000000..00d389139 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,27 @@ +name: ✨ Feature request +description: Request a desired feature +labels: ["feature request"] +body: + - type: markdown + attributes: + value: | + ## Welcome 👋 + Thank you for taking the time to fill out a feature request + + The more information you provide, the easier it is for us to understand your use case. + - type: textarea + id: summary + attributes: + label: Summary + description: Explain your use case. How would this improve your life? + validations: + required: true + - type: textarea + id: reproduction + attributes: + label: Proposed implementation + description: Give an API proposal. How would the feature work? + placeholder: | + The Database class has a new function called... + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/install_problem.yml b/.github/ISSUE_TEMPLATE/install_problem.yml new file mode 100644 index 000000000..66d6e3279 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/install_problem.yml @@ -0,0 +1,48 @@ +name: ⚙️ Installation problem +description: Report an issue installing the library +labels: ["install problem"] +body: + - type: markdown + attributes: + value: | + ## Welcome 👋 + Thank you for taking the time to fill out a report with installing 🙂 + + The more information you provide, the easier & quicker it is for us to diagnose the problem. + + Please search the existing issues and recent releases to make sure your problem hasn't already been solved. + - type: textarea + id: summary + attributes: + label: Issue Summary + description: Explain what's wrong + validations: + required: true + - type: textarea + id: logs + attributes: + label: Relevant logs or output + placeholder: | + Error when installing `sqlite3` due to... + validations: + required: true + - type: input + id: version + attributes: + label: Version + description: What version of `node-sqlite3` are you using? + validations: + required: true + - type: input + id: node + attributes: + label: Node.js Version + validations: + required: true + - type: input + id: os + attributes: + label: How did you install the library? + description: Provide details of your operating system and architecture + validations: + required: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..99716e839 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,165 @@ +name: CI +on: + workflow_dispatch: + pull_request: + push: + branches: + - master + tags: + - '*' +env: + FORCE_COLOR: 1 +concurrency: + group: ${{ github.head_ref || github.run_id }} + cancel-in-progress: true +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - macos-latest + - ubuntu-24.04 + - windows-latest + host: + - x64 + target: + - x64 + node: + - 20 + - 22 + - 24 + exclude: + # Node 20 x64 crashes under Rosetta 2 on ARM64 macOS runners + - os: macos-latest + node: 20 + host: x64 + include: + - os: macos-latest + node: 20 + host: arm64 + target: arm64 + - os: macos-latest + node: 22 + host: arm64 + target: arm64 + - os: macos-latest + node: 24 + host: arm64 + target: arm64 + - os: ubuntu-24.04-arm + node: 20 + host: arm64 + target: arm64 + - os: ubuntu-24.04-arm + node: 22 + host: arm64 + target: arm64 + - os: ubuntu-24.04-arm + node: 24 + host: arm64 + target: arm64 + name: ${{ matrix.os }} (node=${{ matrix.node }}, host=${{ matrix.host }}, target=${{ matrix.target }}) + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-node@v6 + with: + node-version: ${{ matrix.node }} + architecture: ${{ matrix.host }} + + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v1.3 + if: contains(matrix.os, 'windows') + with: + msbuild-architecture: ${{ matrix.target }} + + - name: Install dependencies + run: yarn install --ignore-scripts + + - name: Check Node compatibility + run: node tools/semver-check.js + + - name: Add env vars + shell: bash + run: | + echo "V=1" >> $GITHUB_ENV + + if [ "${{ matrix.target }}" = "x86" ]; then + echo "TARGET=ia32" >> $GITHUB_ENV + else + echo "TARGET=${{ matrix.target }}" >> $GITHUB_ENV + fi + + - name: Add Linux env vars + if: contains(matrix.os, 'ubuntu') + run: | + echo "CFLAGS=${CFLAGS:-} -include ../src/gcc-preinclude.h" >> $GITHUB_ENV + echo "CXXFLAGS=${CXXFLAGS:-} -include ../src/gcc-preinclude.h" >> $GITHUB_ENV + + - name: Build binaries + run: yarn prebuild -a ${{ env.TARGET }} + + - name: Print binary info + if: contains(matrix.os, 'ubuntu') + run: | + ldd build/**/node_sqlite3.node + echo "---" + nm build/**/node_sqlite3.node | grep "GLIBC_" | c++filt || true + echo "---" + file build/**/node_sqlite3.node + + - name: Run tests + run: yarn test + + - name: Upload binaries to commit artifacts + uses: actions/upload-artifact@v7 + if: matrix.node == 24 + with: + name: prebuilt-binaries-${{ matrix.os }}-${{ matrix.host }} + path: prebuilds/* + retention-days: 7 + + - name: Upload binaries to GitHub Release + run: yarn upload --upload-all ${{ github.token }} + if: matrix.node == 24 && startsWith(github.ref, 'refs/tags/') + + build-musl: + if: github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/') + strategy: + fail-fast: false + matrix: + include: + - runner: ubuntu-24.04-arm + platform: linux/arm64 + arch: arm64 + - runner: ubuntu-24.04 + platform: linux/amd64 + arch: amd64 + runs-on: ${{ matrix.runner }} + name: musl ${{ matrix.arch }} + steps: + - uses: actions/checkout@v6 + + - name: Build binaries and test + run: | + docker build \ + --file ./tools/BinaryBuilder.Dockerfile \ + --tag sqlite-builder \ + --no-cache \ + --build-arg VARIANT=alpine3.20 \ + --build-arg NODE_VERSION=24 \ + . + CONTAINER_ID=$(docker create -it sqlite-builder) + docker cp $CONTAINER_ID:/usr/src/build/prebuilds/ ./prebuilds + + - name: Upload binaries to commit artifacts + uses: actions/upload-artifact@v7 + with: + name: prebuilt-binaries-musl-${{ matrix.arch }} + path: prebuilds/* + retention-days: 7 + + - name: Upload binaries to GitHub Release + run: yarn install --ignore-scripts && yarn upload --upload-all ${{ github.token }} + if: startsWith(github.ref, 'refs/tags/') diff --git a/.gitignore b/.gitignore index 1197bbe86..4dadec34b 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,12 @@ test/tmp test/nw/app.nw .DS_Store .idea +.dtps +local.env +.mason +setup.sh +/build-tmp-napi-v3 +/build-tmp-napi-v6 +*.tgz +package-lock.json +prebuilds diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 733dbe72a..000000000 --- a/.npmignore +++ /dev/null @@ -1,12 +0,0 @@ -.gitignore -.npmignore -node_modules -lib/binding -build -test -benchmark -configure -Makefile -scripts -.travis.yml -examples diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 429dd4bf5..000000000 --- a/.travis.yml +++ /dev/null @@ -1,125 +0,0 @@ -sudo: false - -language: generic - -git: - depth: 10 - -addons: - apt: - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-precise-3.5 - packages: - - clang-3.5 - -# don't re-build for tags so that [publish binary] is not re-run -# https://github.com/travis-ci/travis-ci/issues/1532 -branches: - except: - - /^v[0-9]/ - -matrix: - include: - # Linux - - os: linux - compiler: clang - env: NODE_VERSION="6" - addons: - apt: - sources: [ 'ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5', 'gcc-multilib', 'g++-multilib', 'libsqlite3-dev:i386' ] - packages: [ 'clang-3.5'] - - os: linux - compiler: clang - env: NODE_VERSION="5" - addons: - apt: - sources: [ 'ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5', 'gcc-multilib', 'g++-multilib', 'libsqlite3-dev:i386' ] - packages: [ 'clang-3.5'] - - os: linux - compiler: clang - env: NODE_VERSION="4" - addons: - apt: - sources: [ 'ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5', 'gcc-multilib', 'g++-multilib', 'libsqlite3-dev:i386' ] - packages: [ 'clang-3.5'] - - os: linux - compiler: clang - env: NODE_VERSION="0.12" - addons: - apt: - sources: [ 'ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5', 'gcc-multilib', 'g++-multilib', 'libsqlite3-dev:i386' ] - packages: [ 'clang-3.5'] - - os: linux - compiler: clang - env: NODE_VERSION="0.10" - addons: - apt: - sources: [ 'ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5', 'gcc-multilib', 'g++-multilib', 'libsqlite3-dev:i386' ] - packages: [ 'clang-3.5'] - # test building against external sqlite - - os: linux - compiler: clang - env: NODE_VERSION="0.10.40" EXTERNAL_SQLITE=true PUBLISHABLE=false - addons: - apt: - sources: [ 'ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5', 'gcc-multilib', 'g++-multilib', 'libsqlite3-dev:i386' ] - packages: [ 'clang-3.5','libsqlite3-dev'] - # OS X - - os: osx - compiler: clang - env: NODE_VERSION="5" COVERAGE=true PUBLISHABLE=false # node abi 47 - - os: osx - compiler: clang - env: NODE_VERSION="6" # node abi 48 - - os: osx - compiler: clang - env: NODE_VERSION="5" # node abi 47 - - os: osx - compiler: clang - env: NODE_VERSION="4" # node abi 46 - - os: osx - compiler: clang - env: NODE_VERSION="0.12" # node abi 14 - - os: osx - compiler: clang - env: NODE_VERSION="0.10" # node abi 11 - -env: - global: - - JOBS: "8" - - secure: PifMOSnn+mWR1RUptXse+fLvWiTrzg0R/mazO7RWhXHWBKv0uAJ/qV3dI0GIRBLtjG10Iy+tT5RNh1TIbBzB9Y67wMcGvylUPG1+3EOKoBMEPnOD9AgCEQw4SOXfGPx0cq2N6ueSKieCgu1yKN9Wq7XCbE+zTk/DiRNIdLirVoo= - - secure: cc4esJY1vPXL31IeumAJoKWDDO2BTGFiltwfO1jbTbiV7QT911QUjTUasxXIVpOaHNCpxSTyevPwwTWfzt2EtF92Lli+qhQ2bbzMiDSBZstSrHdAe62Ai2M1oYYUwk/0cABB/2nO9uRyYwITCxpTSNzZBrYhn3C29WqBhPeVDmM= - -before_install: -- export PUBLISHABLE=${PUBLISHABLE:-true} -- export COVERAGE=${COVERAGE:-false} -- if [[ $(uname -s) == 'Linux' ]]; then - export CXX="clang++-3.5"; - export CC="clang-3.5"; - export PYTHONPATH=$(pwd)/py-local/lib/python2.7/site-packages; - else - export PYTHONPATH=$(pwd)/py-local/lib/python/site-packages; - fi; -- scripts/validate_tag.sh -- source ./scripts/install_node.sh ${NODE_VERSION} - -install: -# put node-pre-gyp on path -- export PATH=./node_modules/.bin/:$PATH - -before_script: -# get commit message -- export COMMIT_MESSAGE=$(git show -s --format=%B $TRAVIS_COMMIT | tr -d '\n') -- if [[ ${COVERAGE} == true ]]; then - if [[ $(uname -s) == 'Linux' ]]; then - PYTHONUSERBASE=$(pwd)/py-local pip install --user cpp-coveralls; - else - PYTHONUSERBASE=$(pwd)/py-local easy_install --user cpp-coveralls; - fi; - fi - -script: -- if [[ "${NODE_VERSION}" ]]; then ./scripts/build_against_node.sh; fi; -# disabled for now: need to port to sudo:false -#- if [[ "${NODE_WEBKIT}" ]]; then ./scripts/build_against_node_webkit.sh; fi; diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 58a4e1f2a..000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,184 +0,0 @@ -# Changelog - -## 3.1.6 - -- Starts bundling node-pre-gyp again to avoid #720 - -## 3.1.5 - -- [Added support for sqlite3_interrupt](https://github.com/mapbox/node-sqlite3/pull/518): this makes - it possible to interrupt a long-running query. -- [Fixes uv_ref race](https://github.com/mapbox/node-sqlite3/pull/705). - -## 3.1.4 - - - Added support for node v6 - -## 3.1.3 - - - Upgrade to node-pre-gyp@0.6.26 with better support for Electron - -## 3.1.2 - - - Only providing binaries for node v0.10x, v0.12.x, v4, and v5 - - Upgrade to nan@2.2.x - - Upgrade to node-pre-gyp@0.6.24 - - -## 3.1.1 - - - Support for node 5.x - - Upgraded SQLite to 3.9.1: https://www.sqlite.org/releaselog/3_9_1.html - - Enabled json1 extension by default - -## 3.1.0 - - - Support for node 3.x and 4.x - - Stopped producing binaries for node-webkit and 32 bit linux - -## 3.0.11 - - - Support for io.js 3.x (upgrade to Nan 2.x) @kkoopa - -## 3.0.10 - - - Upgraded SQLite to 3.8.11.1: https://www.sqlite.org/releaselog/3_8_11_1.html - - Fixed binary compatibility regression with old centos/rhel glibc GLIBC_2.14 (re-introduced alpine linux (musl) build regression) - - Now providing binaries against Visual Studio 2015 (pass --toolset=v140) and use binaries from https://github.com/mapbox/node-cpp11 - -## 3.0.9 - - - Fixed build regression against alpine linux (musl) - - Upgraded node-pre-gyp@0.6.8 - -## 3.0.8 - - - Fixed build regression against FreeBSD - - Upgraded node-pre-gyp@0.6.7 - -## 3.0.7 - - - Fixed build regression against ARM and i386 linux - - Upgraded node-pre-gyp@0.6.6 - - Added support for io.js 2.0.0 - -## 3.0.6 - - - Upgraded node-pre-gyp@0.6.5 - - Upgraded nan@1.8.4 - - Fixed binaries to work on older linux systems (circa GLIBC_2.2.5 like centos 6) @bnoordhuis - - Updated internal libsqlite3 from 3.8.7.1 -> 3.8.9 (http://www.sqlite.org/news.html) - -## 3.0.5 - - - IO.js and Node v0.12.x support. - - Node-webkit v0.11.x support regressed in this release, sorry (https://github.com/mapbox/node-sqlite3/issues/404). - -## 3.0.4 - - - Upgraded node-pre-gyp@0.6.1 - -## 3.0.3 - - - Upgraded to node-pre-gyp@0.6.0 which should fix crashes against node v0.11.14 - - Now providing binaries against Visual Studio 2014 (pass --toolset=v140) and use binaries from https://github.com/mapbox/node-cpp11 - -## 3.0.2 - - - Republish for possibly busted npm package. - -## 3.0.1 - - - Use ~ in node-pre-gyp semver for more flexible dep management. - -## 3.0.0 - -Released September 20nd, 2014 - - - Backwards-incompatible change: node versions 0.8.x are no longer supported. - - Updated to node-pre-gyp@0.5.27 - - Updated NAN to 1.3.0 - - Updated internal libsqlite3 to v3.8.6 - -## 2.2.7 - -Released August 6th, 2014 - - - Removed usage of `npm ls` with `prepublish` target (which breaks node v0.8.x) - -## 2.2.6 - -Released August 6th, 2014 - - - Fix bundled version of node-pre-gyp - -## 2.2.5 - -Released August 5th, 2014 - - - Fix leak in complete() callback of Database.each() (#307) - - Started using `engineStrict` and improved `engines` declaration to make clear only >= 0.11.13 is supported for the 0.11.x series. - -## 2.2.4 - -Released July 14th, 2014 - - - Now supporting node v0.11.x (specifically >=0.11.13) - - Fix db opening error with absolute path on windows - - Updated to node-pre-gyp@0.5.18 - - updated internal libsqlite3 from 3.8.4.3 -> 3.8.5 (http://www.sqlite.org/news.html) - -## 2.2.3 - - - Fixed regression in v2.2.2 for installing from binaries on windows. - -## 2.2.2 - - - Fixed packaging problem whereby a `config.gypi` was unintentially packaged and could cause breakages for OS X builds. - -## 2.2.1 - - - Now shipping with 64bit FreeBSD binaries against both node v0.10.x and node v0.8.x. - - Fixed solaris/smartos source compile by passing `-std=c99` when building internally bundled libsqlite3 (#201) - - Reduced size of npm package by ignoring tests and examples. - - Various fixes and improvements for building against node-webkit - - Upgraded to node-pre-gyp@0.5.x from node-pre-gyp@0.2.5 - - Improved ability to build from source against `sqlcipher` by passing custom library name: `--sqlite_libname=sqlcipher` - - No changes to C++ Core / Existing binaries are exactly the same - -## 2.2.0 - -Released Jan 13th, 2014 - - - updated internal libsqlite3 from 3.7.17 -> 3.8.2 (http://www.sqlite.org/news.html) which includes the next-generation query planner http://www.sqlite.org/queryplanner-ng.html - - improved binary deploy system using https://github.com/springmeyer/node-pre-gyp - - binary install now supports http proxies - - source compile now supports freebsd - - fixed support for node-webkit - -## 2.1.19 - -Released October 31st, 2013 - - - Started respecting `process.env.npm_config_tmp` as location to download binaries - - Removed uneeded `progress` dependency - -## 2.1.18 - -Released October 22nd, 2013 - - - `node-sqlite3` moved to mapbox github group - - Fixed reporting of node-gyp errors - - Fixed support for node v0.6.x - -## 2.1.17 - - Minor fixes to binary deployment - -## 2.1.16 - - Support for binary deployment - -## 2.1.15 - -Released August 7th, 2013 - - - Minor readme additions and code optimizations diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 3801e3031..000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,57 +0,0 @@ -# Contributing - -General guidelines for contributing to node-sqlite3 - -## Install Help - -If you've landed here due to a failed install of `node-sqlite3` then feel free to create a [new issue](https://github.com/mapbox/node-sqlite3/issues/new) to ask for help. The most likely problem is that we do not yet provide pre-built binaries for your particular platform and so the `node-sqlite3` install attempted a source compile but failed because you are missing the [dependencies for node-gyp](https://github.com/TooTallNate/node-gyp#installation). But please provide as much detail on your problem as possible and we'll try to help. Please include: - - terminal logs of failed install (preferably from running `npm install sqlite3 --loglevel=info`) - - `node-sqlite3` version you tried to install - - node version you are running - - operating system and architecture you are running, e.g. `Windows 7 64 bit`. - -## Developing / Pre-release - -Create a milestone for the next release on github. If all anticipated changes are back compatible then a `patch` release is in order. If minor API changes are needed then a `minor` release is in order. And a `major` bump is warranted if major API changes are needed. - -Assign tickets and pull requests you are working to the milestone you created. - -## Releasing - -To release a new version: - -**1)** Ensure tests are passing - -Before considering a release all the tests need to be passing on appveyor and travis. - -**2)** Bump commit - -Bump the version in `package.json` like https://github.com/mapbox/node-sqlite3/commit/77d51d5785b047ff40f6a8225051488a0d96f7fd - -What if you already committed the `package.json` bump and you have no changes to commit but want to publish binaries? In this case you can do: - -```sh -git commit --allow-empty -m "[publish binary]" -``` - -**3)** Ensure binaries built - -Check the travis and appveyor pages to ensure they are all green as an indication that the `[publish binary]` command worked. - -If you need to republish binaries you can do this with the command below, however this should not be a common thing for you to do! - -```sh -git commit --allow-empty -m "[republish binary]" -``` - -Note: NEVER republish binaries for an existing released version. - -**7)** Officially release - -An official release requires: - - - Updating the CHANGELOG.md - - Create and push github tag like `git tag v3.1.1` -m "v3.1.1" && git push --tags` - - Ensure you have a clean checkout (no extra files in your check that are not known by git). You need to be careful, for instance, to avoid a large accidental file being packaged by npm. You can get a view of what npm will publish by running `make testpack` - - Fully rebuild and ensure install from binary works: `make clean && npm install --fallback-to-build=false` - - Then publish the module to npm repositories by running `npm publish` diff --git a/LICENSE b/LICENSE index 6c4ce40d5..6c1066101 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) MapBox +Copyright (c) 2013-2026 Mapbox & Ghost Foundation All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/Makefile b/Makefile deleted file mode 100644 index 56fcb276a..000000000 --- a/Makefile +++ /dev/null @@ -1,46 +0,0 @@ -#http://www.gnu.org/prep/standards/html_node/Standard-Targets.html#Standard-Targets - -all: build - -./node_modules: - npm install --build-from-source - -build: ./node_modules - ./node_modules/.bin/node-pre-gyp build --loglevel=silent - -debug: - ./node_modules/.bin/node-pre-gyp rebuild --debug - -verbose: - ./node_modules/.bin/node-pre-gyp rebuild --loglevel=verbose - -clean: - @rm -rf ./build - rm -rf lib/binding/ - rm -f test/support/big.db-journal - rm -rf ./node_modules/ - -grind: - valgrind --leak-check=full node node_modules/.bin/_mocha - -testpack: - rm -f ./*tgz - npm pack - tar -ztvf *tgz - rm -f ./*tgz - -rebuild: - @make clean - @make - -ifndef only -test: - @PATH="./node_modules/mocha/bin:${PATH}" && NODE_PATH="./lib:$(NODE_PATH)" mocha -R spec -else -test: - @PATH="./node_modules/mocha/bin:${PATH}" && NODE_PATH="./lib:$(NODE_PATH)" mocha -R spec test/${only}.test.js -endif - -check: test - -.PHONY: test clean build diff --git a/README.md b/README.md index 8aa9482dd..644664e02 100644 --- a/README.md +++ b/README.md @@ -1,117 +1,148 @@ -Asynchronous, non-blocking [SQLite3](http://sqlite.org/) bindings for [Node.js](http://nodejs.org/). +# :no_entry: [DEPRECATED] node-sqlite3 -[![NPM](https://nodei.co/npm/sqlite3.png?downloads=true&downloadRank=true)](https://nodei.co/npm/sqlite3/) +**Note:** This repository is currently unmaintained. We will not update any of its issues or pull requests. -[![Build Status](https://travis-ci.org/mapbox/node-sqlite3.svg?branch=master)](https://travis-ci.org/mapbox/node-sqlite3) -[![Build status](https://ci.appveyor.com/api/projects/status/gvm7ul0hpmdawqom)](https://ci.appveyor.com/project/Mapbox/node-sqlite3) -[![Coverage Status](https://coveralls.io/repos/mapbox/node-sqlite3/badge.svg?branch=master&service=github)](https://coveralls.io/github/mapbox/node-sqlite3?branch=master) -[![Dependencies](https://david-dm.org/mapbox/node-sqlite3.svg)](https://david-dm.org/mapbox/node-sqlite3) +--- +Asynchronous, non-blocking [SQLite3](https://sqlite.org/) bindings for [Node.js](http://nodejs.org/). +[![Latest release](https://img.shields.io/github/release/TryGhost/node-sqlite3.svg)](https://www.npmjs.com/package/sqlite3) +![Build Status](https://github.com/TryGhost/node-sqlite3/workflows/CI/badge.svg?branch=master) +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmapbox%2Fnode-sqlite3.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmapbox%2Fnode-sqlite3?ref=badge_shield) +[![N-API v3 Badge](https://img.shields.io/badge/N--API-v3-green.svg)](https://nodejs.org/dist/latest/docs/api/n-api.html#n_api_n_api) +[![N-API v6 Badge](https://img.shields.io/badge/N--API-v6-green.svg)](https://nodejs.org/dist/latest/docs/api/n-api.html#n_api_n_api) -## Supported platforms +# Features -The `sqlite3` module works with Node.js v0.10.x, v0.12.x, v4.x, and v5.x. + - Straightforward query and parameter binding interface + - Full Buffer/Blob support + - Extensive [debugging support](https://github.com/tryghost/node-sqlite3/wiki/Debugging) + - [Query serialization](https://github.com/tryghost/node-sqlite3/wiki/Control-Flow) API + - [Extension support](https://github.com/TryGhost/node-sqlite3/wiki/API#databaseloadextensionpath-callback), including bundled support for the [json1 extension](https://www.sqlite.org/json1.html) + - Big test suite + - Written in modern C++ and tested for memory leaks + - Bundles SQLite v3.52.0, or you can build using a local SQLite -Binaries for most Node versions and platforms are provided by default via [node-pre-gyp](https://github.com/mapbox/node-pre-gyp). +# Installing -The `sqlite3` module also works with [node-webkit](https://github.com/rogerwang/node-webkit) if node-webkit contains a supported version of Node.js engine. [(See below.)](#building-for-node-webkit) +You can use [`npm`](https://github.com/npm/cli) or [`yarn`](https://github.com/yarnpkg/yarn) to install `sqlite3`: -SQLite's [SQLCipher extension](https://github.com/sqlcipher/sqlcipher) is also supported. [(See below.)](#building-for-sqlcipher) +* (recommended) Latest published package: +```bash +npm install sqlite3 +# or +yarn add sqlite3 +``` +* GitHub's `master` branch: `npm install https://github.com/tryghost/node-sqlite3/tarball/master` -# Usage +### Prebuilt binaries -**Note:** the module must be [installed](#installing) before use. +`sqlite3` v5+ was rewritten to use [Node-API](https://nodejs.org/api/n-api.html) so prebuilt binaries do not need to be built for specific Node versions. `sqlite3` currently builds for both Node-API v3 and v6. Check the [Node-API version matrix](https://nodejs.org/api/n-api.html#node-api-version-matrix) to ensure your Node version supports one of these. The prebuilt binaries should be supported on Node v20.17.0+. -``` js -var sqlite3 = require('sqlite3').verbose(); -var db = new sqlite3.Database(':memory:'); +The module uses [`prebuild-install`](https://github.com/prebuild/prebuild-install) to download the prebuilt binary for your platform, if it exists. These binaries are hosted on GitHub Releases for `sqlite3` versions above 5.0.2, and they are hosted on S3 otherwise. The following targets are currently provided: -db.serialize(function() { - db.run("CREATE TABLE lorem (info TEXT)"); +* `darwin-arm64` +* `darwin-x64` +* `linux-arm64` +* `linux-x64` +* `linuxmusl-arm64` +* `linuxmusl-x64` +* `win32-x64` - var stmt = db.prepare("INSERT INTO lorem VALUES (?)"); - for (var i = 0; i < 10; i++) { - stmt.run("Ipsum " + i); - } - stmt.finalize(); +Unfortunately, [prebuild](https://github.com/prebuild/prebuild/issues/174) cannot differentiate between `armv6` and `armv7`, and instead uses `arm` as the `{arch}`. Until that is fixed, you will still need to install `sqlite3` from [source](#source-install). - db.each("SELECT rowid AS id, info FROM lorem", function(err, row) { - console.log(row.id + ": " + row.info); - }); -}); +Support for other platforms and architectures may be added in the future if CI supports building on them. -db.close(); -``` +If your environment isn't supported, it'll use `node-gyp` to build SQLite, but you will need to install a C++ compiler and linker. -# Features +### Other ways to install - - Straightforward query and parameter binding interface - - Full Buffer/Blob support - - Extensive [debugging support](https://github.com/mapbox/node-sqlite3/wiki/Debugging) - - [Query serialization](https://github.com/mapbox/node-sqlite3/wiki/Control-Flow) API - - [Extension support](https://github.com/mapbox/node-sqlite3/wiki/Extensions) - - Big test suite - - Written in modern C++ and tested for memory leaks - - Bundles Sqlite3 3.9.1 as a fallback if the installing system doesn't include SQLite +It is also possible to make your own build of `sqlite3` from its source instead of its npm package ([See below.](#source-install)). +The `sqlite3` module also works with [node-webkit](https://github.com/rogerwang/node-webkit) if node-webkit contains a supported version of Node.js engine. [(See below.)](#building-for-node-webkit) -# API +SQLite's [SQLCipher extension](https://github.com/sqlcipher/sqlcipher) is also supported. [(See below.)](#building-for-sqlcipher) -See the [API documentation](https://github.com/mapbox/node-sqlite3/wiki) in the wiki. +# API +See the [API documentation](https://github.com/TryGhost/node-sqlite3/wiki/API) in the wiki. -# Installing +# Usage -You can use [`npm`](https://github.com/isaacs/npm) to download and install: +**Note:** the module must be [installed](#installing) before use. -* The latest `sqlite3` package: `npm install sqlite3` +``` js +const sqlite3 = require('sqlite3').verbose(); +const db = new sqlite3.Database(':memory:'); -* GitHub's `master` branch: `npm install https://github.com/mapbox/node-sqlite3/tarball/master` +db.serialize(() => { + db.run("CREATE TABLE lorem (info TEXT)"); -The module uses [node-pre-gyp](https://github.com/mapbox/node-pre-gyp) to download a pre-compiled binary for your platform, if it exists. Otherwise, it uses `node-gyp` to build the extension. + const stmt = db.prepare("INSERT INTO lorem VALUES (?)"); + for (let i = 0; i < 10; i++) { + stmt.run("Ipsum " + i); + } + stmt.finalize(); -It is also possible to make your own build of `sqlite3` from its source instead of its npm package ([see below](#building-from-the-source)). + db.each("SELECT rowid AS id, info FROM lorem", (err, row) => { + console.log(row.id + ": " + row.info); + }); +}); -It is possible to use the installed package in [node-webkit](https://github.com/rogerwang/node-webkit) instead of the vanilla Node.js. See [Building for node-webkit](#building-for-node-webkit) for details. +db.close(); +``` ## Source install To skip searching for pre-compiled binaries, and force a build from source, use - npm install --build-from-source +```bash +npm install --build-from-source +``` The sqlite3 module depends only on libsqlite3. However, by default, an internal/bundled copy of sqlite will be built and statically linked, so an externally installed sqlite3 is not required. If you wish to install against an external sqlite then you need to pass the `--sqlite` argument to `npm` wrapper: - npm install --build-from-source --sqlite=/usr/local +```bash +npm install --build-from-source --sqlite=/usr/local +``` If building against an external sqlite3 make sure to have the development headers available. Mac OS X ships with these by default. If you don't have them installed, install the `-dev` package with your package manager, e.g. `apt-get install libsqlite3-dev` for Debian/Ubuntu. Make sure that you have at least `libsqlite3` >= 3.6. Note, if building against homebrew-installed sqlite on OS X you can do: - npm install --build-from-source --sqlite=/usr/local/opt/sqlite/ +```bash +npm install --build-from-source --sqlite=/usr/local/opt/sqlite/ +``` + +## Custom file header (magic) + +The default sqlite file header is "SQLite format 3". You can specify a different magic, though this will make standard tools and libraries unable to work with your files. + +```bash +npm install --build-from-source --sqlite_magic="MyCustomMagic15" +``` + +Note that the magic *must* be exactly 15 characters long (16 bytes including null terminator). ## Building for node-webkit Because of ABI differences, `sqlite3` must be built in a custom to be used with [node-webkit](https://github.com/rogerwang/node-webkit). -To build node-sqlite3 for node-webkit: +To build `sqlite3` for node-webkit: 1. Install [`nw-gyp`](https://github.com/rogerwang/nw-gyp) globally: `npm install nw-gyp -g` *(unless already installed)* 2. Build the module with the custom flags of `--runtime`, `--target_arch`, and `--target`: -```sh +```bash NODE_WEBKIT_VERSION="0.8.6" # see latest version at https://github.com/rogerwang/node-webkit#downloads npm install sqlite3 --build-from-source --runtime=node-webkit --target_arch=ia32 --target=$(NODE_WEBKIT_VERSION) ``` -This command internally calls out to [`node-pre-gyp`](https://github.com/mapbox/node-pre-gyp) which itself calls out to [`nw-gyp`](https://github.com/rogerwang/nw-gyp) when the `--runtime=node-webkit` option is passed. - -You can also run this command from within a `node-sqlite3` checkout: +You can also run this command from within a `sqlite3` checkout: -```sh +```bash npm install --build-from-source --runtime=node-webkit --target_arch=ia32 --target=$(NODE_WEBKIT_VERSION) ``` @@ -124,53 +155,68 @@ Remember the following: Visit the “[Using Node modules](https://github.com/rogerwang/node-webkit/wiki/Using-Node-modules)” article in the node-webkit's wiki for more details. -## Building for sqlcipher +## Building for SQLCipher -For instructions for building sqlcipher see -[Building SQLCipher for node.js](https://coolaj86.com/articles/building-sqlcipher-for-node-js-on-raspberry-pi-2/) +For instructions on building SQLCipher, see [Building SQLCipher for Node.js](https://coolaj86.com/articles/building-sqlcipher-for-node-js-on-raspberry-pi-2/). Alternatively, you can install it with your local package manager. -To run node-sqlite3 against sqlcipher you need to compile from source by passing build options like: +To run against SQLCipher, you need to compile `sqlite3` from source by passing build options like: - npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --sqlite=/usr/ - - node -e 'require("sqlite3")' +```bash +npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --sqlite=/usr/ -If your sqlcipher is installed in a custom location (if you compiled and installed it yourself), -you'll also need to to set some environment variables: +node -e 'require("sqlite3")' +``` + +If your SQLCipher is installed in a custom location (if you compiled and installed it yourself), you'll need to set some environment variables: ### On OS X with Homebrew Set the location where `brew` installed it: - export LDFLAGS="-L`brew --prefix`/opt/sqlcipher/lib" - export CPPFLAGS="-I`brew --prefix`/opt/sqlcipher/include" - npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --sqlite=`brew --prefix` - - node -e 'require("sqlite3")' +```bash +export LDFLAGS="-L`brew --prefix`/opt/sqlcipher/lib" +export CPPFLAGS="-I`brew --prefix`/opt/sqlcipher/include/sqlcipher" +npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --sqlite=`brew --prefix` + +node -e 'require("sqlite3")' +``` ### On most Linuxes (including Raspberry Pi) Set the location where `make` installed it: - export LDFLAGS="-L/usr/local/lib" - export CPPFLAGS="-I/usr/local/include -I/usr/local/include/sqlcipher" - export CXXFLAGS="$CPPFLAGS" - npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --sqlite=/usr/local --verbose - - node -e 'require("sqlite3")' +```bash +export LDFLAGS="-L/usr/local/lib" +export CPPFLAGS="-I/usr/local/include -I/usr/local/include/sqlcipher" +export CXXFLAGS="$CPPFLAGS" +npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --sqlite=/usr/local --verbose -# Testing +node -e 'require("sqlite3")' +``` + +### Custom builds and Electron + +Running `sqlite3` through [electron-rebuild](https://github.com/electron/electron-rebuild) does not preserve the SQLCipher extension, so some additional flags are needed to make this build Electron compatible. Your `npm install sqlite3 --build-from-source` command needs these additional flags (be sure to replace the target version with the current Electron version you are working with): + +```bash +--runtime=electron --target=18.2.1 --dist-url=https://electronjs.org/headers +``` -[mocha](https://github.com/visionmedia/mocha) is required to run unit tests. +In the case of MacOS with Homebrew, the command should look like the following: -In sqlite3's directory (where its `package.json` resides) run the following: +```bash +npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --sqlite=`brew --prefix` --runtime=electron --target=18.2.1 --dist-url=https://electronjs.org/headers +``` - npm install mocha - npm test +# Testing +```bash +npm test +``` # Contributors +* [Daniel Lockyer](https://github.com/daniellockyer) * [Konstantin Käfer](https://github.com/kkaefer) * [Dane Springmeyer](https://github.com/springmeyer) * [Will White](https://github.com/willwhite) @@ -184,7 +230,7 @@ In sqlite3's directory (where its `package.json` resides) run the following: * [Audrius Kažukauskas](https://github.com/audriusk) * [Johannes Schauer](https://github.com/pyneo) * [Mithgol](https://github.com/Mithgol) - +* [Kewde](https://github.com/kewde) # Acknowledgments @@ -192,9 +238,16 @@ Thanks to [Orlando Vazquez](https://github.com/orlandov), [Eric Fredricksen](https://github.com/grumdrig) and [Ryan Dahl](https://github.com/ry) for their SQLite bindings for node, and to mraleph on Freenode's #v8 for answering questions. -Development of this module is sponsored by [MapBox](http://mapbox.org/). +This module was originally created by [Mapbox](https://mapbox.com/) & is now maintained by [Ghost](https://ghost.org). + +# Changelog + +We use [GitHub releases](https://github.com/TryGhost/node-sqlite3/releases) for notes on the latest versions. See [CHANGELOG.md](https://github.com/TryGhost/node-sqlite3/blob/b05f4594cf8b0de64743561fcd2cfe6f4571754d/CHANGELOG.md) in git history for details on older versions. + +# Copyright & license +Copyright (c) 2013-2026 Mapbox & Ghost Foundation -# License +`node-sqlite3` is [BSD licensed](https://github.com/tryghost/node-sqlite3/raw/master/LICENSE). -`node-sqlite3` is [BSD licensed](https://github.com/mapbox/node-sqlite3/raw/master/LICENSE). +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmapbox%2Fnode-sqlite3.svg?type=large)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmapbox%2Fnode-sqlite3?ref=badge_large) diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 1f63dab13..000000000 --- a/appveyor.yml +++ /dev/null @@ -1,62 +0,0 @@ -environment: - node_pre_gyp_accessKeyId: - secure: 7DrSVc5eIGtmMcki5H+iRft+Tk3MJTwDBQEUuJHWaQ4= - node_pre_gyp_secretAccessKey: - secure: 1amwJJw9fu0j6dXnc5KsAQbSYf7Cjw/dapT6OZWABa6nc52grkKeLQ+DGaOfQz8i - matrix: - - nodejs_version: 0.10.40 - platform: x86 - msvs_toolset: 12 - - nodejs_version: 0.10.40 - platform: x64 - msvs_toolset: 12 - - nodejs_version: 0.12.7 - platform: x86 - msvs_toolset: 12 - - nodejs_version: 0.12.7 - platform: x64 - msvs_toolset: 12 - - nodejs_version: 4.0.0 - platform: x64 - msvs_toolset: 12 - - nodejs_version: 4.0.0 - platform: x86 - msvs_toolset: 12 - - nodejs_version: 5.0.0 - platform: x64 - msvs_toolset: 12 - - nodejs_version: 5.0.0 - platform: x86 - msvs_toolset: 12 - - nodejs_version: 6.0.0 - platform: x64 - msvs_toolset: 12 - - nodejs_version: 6.0.0 - platform: x86 - msvs_toolset: 12 - # custom visual studio 2015 builds - - nodejs_version: 0.10.40 - platform: x86 - msvs_toolset: 14 - TOOLSET_ARGS: --dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --toolset=v140 - - nodejs_version: 0.10.40 - platform: x64 - msvs_toolset: 14 - TOOLSET_ARGS: --dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --toolset=v140 - - nodejs_version: 0.12.7 - platform: x86 - msvs_toolset: 14 - TOOLSET_ARGS: --dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --toolset=v140 - - nodejs_version: 0.12.7 - platform: x64 - msvs_toolset: 14 - TOOLSET_ARGS: --dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --toolset=v140 - -os: Visual Studio 2015 - -install: - - scripts\build-appveyor.bat - -build: OFF -test: OFF -deploy: OFF diff --git a/binding.gyp b/binding.gyp index a0c5faa53..a8fccd0c4 100644 --- a/binding.gyp +++ b/binding.gyp @@ -2,20 +2,34 @@ "includes": [ "deps/common-sqlite.gypi" ], "variables": { "sqlite%":"internal", - "sqlite_libname%":"sqlite3" + "sqlite_libname%":"sqlite3", + "module_name": "node_sqlite3", }, "targets": [ { "target_name": "<(module_name)", - "include_dirs": ["= 3.49 ships a VERSION file that conflicts with the C++20 +// header on case-insensitive filesystems (macOS/Windows). +const base = path.basename(tarball, ".tar.gz"); +const versionFile = path.join(dirname, base, "VERSION"); +if (fs.existsSync(versionFile)) { + fs.unlinkSync(versionFile); +} diff --git a/deps/extract.py b/deps/extract.py deleted file mode 100644 index 410c931e5..000000000 --- a/deps/extract.py +++ /dev/null @@ -1,9 +0,0 @@ -import sys -import tarfile -import os - -tarball = os.path.abspath(sys.argv[1]) -dirname = os.path.abspath(sys.argv[2]) -tfile = tarfile.open(tarball,'r:gz'); -tfile.extractall(dirname) -sys.exit(0) diff --git a/deps/sqlite-autoconf-3090100.tar.gz b/deps/sqlite-autoconf-3090100.tar.gz deleted file mode 100644 index 92d8a4690..000000000 Binary files a/deps/sqlite-autoconf-3090100.tar.gz and /dev/null differ diff --git a/deps/sqlite-autoconf-3520000.tar.gz b/deps/sqlite-autoconf-3520000.tar.gz new file mode 100644 index 000000000..83ed17601 Binary files /dev/null and b/deps/sqlite-autoconf-3520000.tar.gz differ diff --git a/deps/sqlite3.gyp b/deps/sqlite3.gyp index 45a642308..660b3b07e 100755 --- a/deps/sqlite3.gyp +++ b/deps/sqlite3.gyp @@ -1,5 +1,10 @@ { 'includes': [ 'common-sqlite.gypi' ], + + 'variables': { + 'sqlite_magic%': '', + }, + 'target_defaults': { 'default_configuration': 'Release', 'cflags':[ @@ -55,7 +60,7 @@ 'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/sqlite-autoconf-<@(sqlite_version)/sqlite3.c' ], - 'action': ['python','./extract.py','./sqlite-autoconf-<@(sqlite_version).tar.gz','<(SHARED_INTERMEDIATE_DIR)'] + 'action': ['node','./extract.js','./sqlite-autoconf-<@(sqlite_version).tar.gz','<(SHARED_INTERMEDIATE_DIR)'] } ], 'direct_dependent_settings': { @@ -71,7 +76,6 @@ 'dependencies': [ 'action_before_build' ], - 'cflags': [ '-include ../src/gcc-preinclude.h' ], 'sources': [ '<(SHARED_INTERMEDIATE_DIR)/sqlite-autoconf-<@(sqlite_version)/sqlite3.c' ], @@ -79,25 +83,39 @@ 'include_dirs': [ '<(SHARED_INTERMEDIATE_DIR)/sqlite-autoconf-<@(sqlite_version)/' ], 'defines': [ 'SQLITE_THREADSAFE=1', + 'HAVE_USLEEP=1', 'SQLITE_ENABLE_FTS3', - 'SQLITE_ENABLE_JSON1', - 'SQLITE_ENABLE_RTREE' + 'SQLITE_ENABLE_FTS4', + 'SQLITE_ENABLE_FTS5', + 'SQLITE_ENABLE_RTREE', + 'SQLITE_ENABLE_DBSTAT_VTAB=1', + 'SQLITE_ENABLE_MATH_FUNCTIONS' ], }, 'cflags_cc': [ - '-Wno-unused-value', - '-include ../src/gcc-preinclude.h' + '-Wno-unused-value' ], 'defines': [ '_REENTRANT=1', 'SQLITE_THREADSAFE=1', + 'HAVE_USLEEP=1', 'SQLITE_ENABLE_FTS3', - 'SQLITE_ENABLE_JSON1', - 'SQLITE_ENABLE_RTREE' + 'SQLITE_ENABLE_FTS4', + 'SQLITE_ENABLE_FTS5', + 'SQLITE_ENABLE_RTREE', + 'SQLITE_ENABLE_DBSTAT_VTAB=1', + 'SQLITE_ENABLE_MATH_FUNCTIONS' ], 'export_dependent_settings': [ 'action_before_build', - ] + ], + 'conditions': [ + ["sqlite_magic != ''", { + 'defines': [ + 'SQLITE_FILE_HEADER="<(sqlite_magic)"' + ] + }] + ], } ] } diff --git a/examples/simple-chaining.js b/examples/simple-chaining.js deleted file mode 100644 index 17a78785b..000000000 --- a/examples/simple-chaining.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Shows how to use chaining rather than the `serialize` method. - */ -"use strict"; - -var sqlite3 = require('sqlite3').verbose(); -var db; - -function createDb() { - console.log("createDb chain"); - db = new sqlite3.Database('chain.sqlite3', createTable); -} - - -function createTable() { - console.log("createTable lorem"); - db.run("CREATE TABLE IF NOT EXISTS lorem (info TEXT)", insertRows); -} - -function insertRows() { - console.log("insertRows Ipsum i"); - var stmt = db.prepare("INSERT INTO lorem VALUES (?)"); - - for (var i = 0; i < 10; i++) { - stmt.run("Ipsum " + i); - } - - stmt.finalize(readAllRows); -} - -function readAllRows() { - console.log("readAllRows lorem"); - db.all("SELECT rowid AS id, info FROM lorem", function(err, rows) { - rows.forEach(function (row) { - console.log(row.id + ": " + row.info); - }); - closeDb(); - }); -} - -function closeDb() { - console.log("closeDb"); - db.close(); -} - -function runChainExample() { - createDb(); -} - -runChainExample(); diff --git a/lib/index.js b/lib/index.js deleted file mode 100644 index 3f8eeb3e2..000000000 --- a/lib/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./sqlite3'); diff --git a/lib/sqlite3-binding.js b/lib/sqlite3-binding.js new file mode 100644 index 000000000..98d1b91b7 --- /dev/null +++ b/lib/sqlite3-binding.js @@ -0,0 +1 @@ +module.exports = require('bindings')('node_sqlite3.node'); diff --git a/lib/sqlite3.d.ts b/lib/sqlite3.d.ts new file mode 100644 index 000000000..15e66230e --- /dev/null +++ b/lib/sqlite3.d.ts @@ -0,0 +1,205 @@ +// Type definitions for sqlite3 +// Project: http://github.com/tryghost/node-sqlite3 + +/// + +import events = require("events"); + +export const OPEN_READONLY: number; +export const OPEN_READWRITE: number; +export const OPEN_CREATE: number; +export const OPEN_FULLMUTEX: number; +export const OPEN_SHAREDCACHE: number; +export const OPEN_PRIVATECACHE: number; +export const OPEN_URI: number; + +export const VERSION: string; +export const SOURCE_ID: string; +export const VERSION_NUMBER: number; + +export const OK: number; +export const ERROR: number; +export const INTERNAL: number; +export const PERM: number; +export const ABORT: number; +export const BUSY: number; +export const LOCKED: number; +export const NOMEM: number; +export const READONLY: number; +export const INTERRUPT: number +export const IOERR: number; +export const CORRUPT: number +export const NOTFOUND: number; +export const FULL: number; +export const CANTOPEN: number; +export const PROTOCOL: number; +export const EMPTY: number; +export const SCHEMA: number; +export const TOOBIG: number +export const CONSTRAINT: number +export const MISMATCH: number; +export const MISUSE: number; +export const NOLFS: number; +export const AUTH: number +export const FORMAT: number; +export const RANGE: number +export const NOTADB: number; + +export const LIMIT_LENGTH: number; +export const LIMIT_SQL_LENGTH: number; +export const LIMIT_COLUMN: number; +export const LIMIT_EXPR_DEPTH: number; +export const LIMIT_COMPOUND_SELECT: number; +export const LIMIT_VDBE_OP: number; +export const LIMIT_FUNCTION_ARG: number; +export const LIMIT_ATTACHED: number; +export const LIMIT_LIKE_PATTERN_LENGTH: number; +export const LIMIT_VARIABLE_NUMBER: number; +export const LIMIT_TRIGGER_DEPTH: number; +export const LIMIT_WORKER_THREADS: number; + +export const cached: { + Database(filename: string, callback?: (this: Database, err: Error | null) => void): Database; + Database(filename: string, mode?: number, callback?: (this: Database, err: Error | null) => void): Database; +}; + +export interface RunResult extends Statement { + lastID: number; + changes: number; +} + +export class Statement extends events.EventEmitter { + bind(callback?: (err: Error | null) => void): this; + bind(...params: any[]): this; + + reset(callback?: (err: null) => void): this; + + finalize(callback?: (err: Error) => void): Database; + + run(callback?: (err: Error | null) => void): this; + run(params: any, callback?: (this: RunResult, err: Error | null) => void): this; + run(...params: any[]): this; + + get(callback?: (err: Error | null, row?: T) => void): this; + get(params: any, callback?: (this: RunResult, err: Error | null, row?: T) => void): this; + get(...params: any[]): this; + + all(callback?: (err: Error | null, rows: T[]) => void): this; + all(params: any, callback?: (this: RunResult, err: Error | null, rows: T[]) => void): this; + all(...params: any[]): this; + + each(callback?: (err: Error | null, row: T) => void, complete?: (err: Error | null, count: number) => void): this; + each(params: any, callback?: (this: RunResult, err: Error | null, row: T) => void, complete?: (err: Error | null, count: number) => void): this; + each(...params: any[]): this; +} + +export class Database extends events.EventEmitter { + constructor(filename: string, callback?: (err: Error | null) => void); + constructor(filename: string, mode?: number, callback?: (err: Error | null) => void); + + close(callback?: (err: Error | null) => void): void; + + run(sql: string, callback?: (this: RunResult, err: Error | null) => void): this; + run(sql: string, params: any, callback?: (this: RunResult, err: Error | null) => void): this; + run(sql: string, ...params: any[]): this; + + get(sql: string, callback?: (this: Statement, err: Error | null, row: T) => void): this; + get(sql: string, params: any, callback?: (this: Statement, err: Error | null, row: T) => void): this; + get(sql: string, ...params: any[]): this; + + all(sql: string, callback?: (this: Statement, err: Error | null, rows: T[]) => void): this; + all(sql: string, params: any, callback?: (this: Statement, err: Error | null, rows: T[]) => void): this; + all(sql: string, ...params: any[]): this; + + each(sql: string, callback?: (this: Statement, err: Error | null, row: T) => void, complete?: (err: Error | null, count: number) => void): this; + each(sql: string, params: any, callback?: (this: Statement, err: Error | null, row: T) => void, complete?: (err: Error | null, count: number) => void): this; + each(sql: string, ...params: any[]): this; + + exec(sql: string, callback?: (this: Statement, err: Error | null) => void): this; + + prepare(sql: string, callback?: (this: Statement, err: Error | null) => void): Statement; + prepare(sql: string, params: any, callback?: (this: Statement, err: Error | null) => void): Statement; + prepare(sql: string, ...params: any[]): Statement; + + serialize(callback?: () => void): void; + parallelize(callback?: () => void): void; + + on(event: "trace", listener: (sql: string) => void): this; + on(event: "profile", listener: (sql: string, time: number) => void): this; + on(event: "change", listener: (type: string, database: string, table: string, rowid: number) => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "open" | "close", listener: () => void): this; + on(event: string, listener: (...args: any[]) => void): this; + + configure(option: "busyTimeout", value: number): void; + configure(option: "limit", id: number, value: number): void; + + loadExtension(filename: string, callback?: (err: Error | null) => void): this; + + wait(callback?: (param: null) => void): this; + + interrupt(): void; +} + +export function verbose(): sqlite3; + +export interface sqlite3 { + OPEN_READONLY: number; + OPEN_READWRITE: number; + OPEN_CREATE: number; + OPEN_FULLMUTEX: number; + OPEN_SHAREDCACHE: number; + OPEN_PRIVATECACHE: number; + OPEN_URI: number; + + VERSION: string; + SOURCE_ID: string; + VERSION_NUMBER: number; + + OK: number; + ERROR: number; + INTERNAL: number; + PERM: number; + ABORT: number; + BUSY: number; + LOCKED: number; + NOMEM: number; + READONLY: number; + INTERRUPT: number + IOERR: number; + CORRUPT: number + NOTFOUND: number; + FULL: number; + CANTOPEN: number; + PROTOCOL: number; + EMPTY: number; + SCHEMA: number; + TOOBIG: number + CONSTRAINT: number + MISMATCH: number; + MISUSE: number; + NOLFS: number; + AUTH: number + FORMAT: number; + RANGE: number + NOTADB: number; + + LIMIT_LENGTH: number; + LIMIT_SQL_LENGTH: number; + LIMIT_COLUMN: number; + LIMIT_EXPR_DEPTH: number; + LIMIT_COMPOUND_SELECT: number; + LIMIT_VDBE_OP: number; + LIMIT_FUNCTION_ARG: number; + LIMIT_ATTACHED: number; + LIMIT_LIKE_PATTERN_LENGTH: number; + LIMIT_VARIABLE_NUMBER: number; + LIMIT_TRIGGER_DEPTH: number; + LIMIT_WORKER_THREADS: number; + + cached: typeof cached; + RunResult: RunResult; + Statement: typeof Statement; + Database: typeof Database; + verbose(): this; +} \ No newline at end of file diff --git a/lib/sqlite3.js b/lib/sqlite3.js index 466b90230..430a2b88a 100644 --- a/lib/sqlite3.js +++ b/lib/sqlite3.js @@ -1,30 +1,29 @@ -var binary = require('node-pre-gyp'); -var path = require('path'); -var binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json'))); -var binding = require(binding_path); -var sqlite3 = module.exports = exports = binding; -var EventEmitter = require('events').EventEmitter; +const path = require('path'); +const sqlite3 = require('./sqlite3-binding.js'); +const EventEmitter = require('events').EventEmitter; +module.exports = exports = sqlite3; function normalizeMethod (fn) { return function (sql) { - var errBack; - var args = Array.prototype.slice.call(arguments, 1); + let errBack; + const args = Array.prototype.slice.call(arguments, 1); + if (typeof args[args.length - 1] === 'function') { - var callback = args[args.length - 1]; + const callback = args[args.length - 1]; errBack = function(err) { if (err) { callback(err); } }; } - var statement = new Statement(this, sql, errBack); + const statement = new Statement(this, sql, errBack); return fn.call(this, statement, args); - } + }; } function inherits(target, source) { - for (var k in source.prototype) - target.prototype[k] = source.prototype[k]; + for (const k in source.prototype) + target.prototype[k] = source.prototype[k]; } sqlite3.cached = { @@ -34,15 +33,16 @@ sqlite3.cached = { return new Database(file, a, b); } + let db; file = path.resolve(file); if (!sqlite3.cached.objects[file]) { - var db =sqlite3.cached.objects[file] = new Database(file, a, b); + db = sqlite3.cached.objects[file] = new Database(file, a, b); } else { // Make sure the callback is called. - var db = sqlite3.cached.objects[file]; - var callback = (typeof a === 'number') ? b : a; + db = sqlite3.cached.objects[file]; + const callback = (typeof a === 'number') ? b : a; if (typeof callback === 'function') { function cb() { callback.call(db, null); } if (db.open) process.nextTick(cb); @@ -56,11 +56,13 @@ sqlite3.cached = { }; -var Database = sqlite3.Database; -var Statement = sqlite3.Statement; +const Database = sqlite3.Database; +const Statement = sqlite3.Statement; +const Backup = sqlite3.Backup; inherits(Database, EventEmitter); inherits(Statement, EventEmitter); +inherits(Backup, EventEmitter); // Database#prepare(sql, [bind1, bind2, ...], [callback]) Database.prototype.prepare = normalizeMethod(function(statement, params) { @@ -98,23 +100,41 @@ Database.prototype.map = normalizeMethod(function(statement, params) { return this; }); +// Database#backup(filename, [callback]) +// Database#backup(filename, destName, sourceName, filenameIsDest, [callback]) +Database.prototype.backup = function() { + let backup; + if (arguments.length <= 2) { + // By default, we write the main database out to the main database of the named file. + // This is the most likely use of the backup api. + backup = new Backup(this, arguments[0], 'main', 'main', true, arguments[1]); + } else { + // Otherwise, give the user full control over the sqlite3_backup_init arguments. + backup = new Backup(this, arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]); + } + // Per the sqlite docs, exclude the following errors as non-fatal by default. + backup.retryErrors = [sqlite3.BUSY, sqlite3.LOCKED]; + return backup; +}; + Statement.prototype.map = function() { - var params = Array.prototype.slice.call(arguments); - var callback = params.pop(); + const params = Array.prototype.slice.call(arguments); + const callback = params.pop(); params.push(function(err, rows) { if (err) return callback(err); - var result = {}; + const result = {}; if (rows.length) { - var keys = Object.keys(rows[0]), key = keys[0]; + const keys = Object.keys(rows[0]); + const key = keys[0]; if (keys.length > 2) { // Value is an object - for (var i = 0; i < rows.length; i++) { + for (let i = 0; i < rows.length; i++) { result[rows[i][key]] = rows[i]; } } else { - var value = keys[1]; + const value = keys[1]; // Value is a plain value - for (var i = 0; i < rows.length; i++) { + for (let i = 0; i < rows.length; i++) { result[rows[i][key]] = rows[i][value]; } } @@ -124,12 +144,12 @@ Statement.prototype.map = function() { return this.all.apply(this, params); }; -var isVerbose = false; +let isVerbose = false; -var supportedEvents = [ 'trace', 'profile', 'insert', 'update', 'delete' ]; +const supportedEvents = [ 'trace', 'profile', 'change' ]; Database.prototype.addListener = Database.prototype.on = function(type) { - var val = EventEmitter.prototype.addListener.apply(this, arguments); + const val = EventEmitter.prototype.addListener.apply(this, arguments); if (supportedEvents.indexOf(type) >= 0) { this.configure(type, true); } @@ -137,7 +157,7 @@ Database.prototype.addListener = Database.prototype.on = function(type) { }; Database.prototype.removeListener = function(type) { - var val = EventEmitter.prototype.removeListener.apply(this, arguments); + const val = EventEmitter.prototype.removeListener.apply(this, arguments); if (supportedEvents.indexOf(type) >= 0 && !this._events[type]) { this.configure(type, false); } @@ -145,7 +165,7 @@ Database.prototype.removeListener = function(type) { }; Database.prototype.removeAllListeners = function(type) { - var val = EventEmitter.prototype.removeAllListeners.apply(this, arguments); + const val = EventEmitter.prototype.removeAllListeners.apply(this, arguments); if (supportedEvents.indexOf(type) >= 0) { this.configure(type, false); } @@ -155,7 +175,7 @@ Database.prototype.removeAllListeners = function(type) { // Save the stack trace over EIO callbacks. sqlite3.verbose = function() { if (!isVerbose) { - var trace = require('./trace'); + const trace = require('./trace'); [ 'prepare', 'get', @@ -183,5 +203,5 @@ sqlite3.verbose = function() { isVerbose = true; } - return this; + return sqlite3; }; diff --git a/lib/trace.js b/lib/trace.js index 3ea20bd7f..1d84cb011 100644 --- a/lib/trace.js +++ b/lib/trace.js @@ -1,32 +1,28 @@ // Inspired by https://github.com/tlrobinson/long-stack-traces -var EventEmitter = require('events').EventEmitter; -var util = require('util'); +const util = require('util'); function extendTrace(object, property, pos) { - var old = object[property]; + const old = object[property]; object[property] = function() { - var error = new Error(); - var name = object.constructor.name + '#' + property + '(' + + const error = new Error(); + const name = object.constructor.name + '#' + property + '(' + Array.prototype.slice.call(arguments).map(function(el) { return util.inspect(el, false, 0); }).join(', ') + ')'; if (typeof pos === 'undefined') pos = -1; if (pos < 0) pos += arguments.length; - var cb = arguments[pos]; + const cb = arguments[pos]; if (typeof arguments[pos] === 'function') { arguments[pos] = function replacement() { - try { - return cb.apply(this, arguments); - } catch (err) { - if (err && err.stack && !err.__augmented) { - err.stack = filter(err).join('\n'); - err.stack += '\n--> in ' + name; - err.stack += '\n' + filter(error).slice(1).join('\n'); - err.__augmented = true; - } - throw err; + const err = arguments[0]; + if (err && err.stack && !err.__augmented) { + err.stack = filter(err).join('\n'); + err.stack += '\n--> in ' + name; + err.stack += '\n' + filter(error).slice(1).join('\n'); + err.__augmented = true; } + return cb.apply(this, arguments); }; } return old.apply(this, arguments); diff --git a/package.json b/package.json index 17d3a6081..08f4b7e18 100644 --- a/package.json +++ b/package.json @@ -1,64 +1,92 @@ { - "name": "sqlite3", - "description": "Asynchronous, non-blocking SQLite3 bindings", - "version": "3.1.6", - "homepage": "http://github.com/mapbox/node-sqlite3", - "author": { - "name": "MapBox", - "url": "https://mapbox.com/" - }, - "binary": { - "module_name" : "node_sqlite3", - "module_path" : "./lib/binding/{node_abi}-{platform}-{arch}", - "host" : "https://mapbox-node-binary.s3.amazonaws.com", - "remote_path" : "./{name}/v{version}/{toolset}/", - "package_name": "{node_abi}-{platform}-{arch}.tar.gz" - }, - "contributors": [ - "Konstantin Käfer ", - "Dane Springmeyer ", - "Will White ", - "Orlando Vazquez ", - "Artem Kustikov ", - "Eric Fredricksen ", - "John Wright ", - "Ryan Dahl ", - "Tom MacWright ", - "Carter Thaxton ", - "Audrius Kažukauskas ", - "Johannes Schauer ", - "Nathan Rajlich ", - "AJ ONeal ", - "Mithgol", - "Ben Noordhuis " - ], - "repository": { - "type": "git", - "url": "git://github.com/mapbox/node-sqlite3.git" - }, - "dependencies": { - "nan": "~2.3.3", - "node-pre-gyp": "~0.6.28" - }, - "bundledDependencies": [ - "node-pre-gyp" - ], - "devDependencies": { - "mocha": "2.x", - "aws-sdk": "2.x" - }, - "scripts": { - "prepublish":"npm ls", - "install": "node-pre-gyp install --fallback-to-build", - "pretest": "node test/support/createdb.js", - "test": "mocha -R spec --timeout 480000" - }, - "license": "BSD-3-Clause", - "keywords": [ - "sql", - "sqlite", - "sqlite3", - "database" - ], - "main": "./lib/sqlite3" + "name": "sqlite3", + "description": "Asynchronous, non-blocking SQLite3 bindings", + "version": "6.0.1", + "homepage": "https://github.com/TryGhost/node-sqlite3", + "author": { + "name": "Mapbox", + "url": "https://mapbox.com/" + }, + "binary": { + "napi_versions": [ + 3, + 6 + ] + }, + "contributors": [ + "Daniel Lockyer ", + "Konstantin Käfer ", + "Dane Springmeyer ", + "Will White ", + "Orlando Vazquez ", + "Artem Kustikov ", + "Eric Fredricksen ", + "John Wright ", + "Ryan Dahl ", + "Tom MacWright ", + "Carter Thaxton ", + "Audrius Kažukauskas ", + "Johannes Schauer ", + "Nathan Rajlich ", + "AJ ONeal ", + "Mithgol", + "Ben Noordhuis " + ], + "files": [ + "binding.gyp", + "deps/", + "lib/*.js", + "lib/*.d.ts", + "src/" + ], + "repository": { + "type": "git", + "url": "https://github.com/TryGhost/node-sqlite3.git" + }, + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^8.0.0", + "prebuild-install": "^7.1.3", + "tar": "^7.5.10" + }, + "devDependencies": { + "eslint": "8.56.0", + "mocha": "10.2.0", + "prebuild": "13.0.1" + }, + "peerDependencies": { + "node-gyp": "12.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + }, + "optionalDependencies": { + "node-gyp": "12.x" + }, + "engines": { + "node": ">=20.17.0" + }, + "scripts": { + "install": "prebuild-install -r napi || node-gyp rebuild", + "prebuild": "prebuild --runtime napi --all --verbose", + "rebuild": "node-gyp rebuild", + "upload": "prebuild --verbose --prerelease", + "test": "node test/support/createdb.js && mocha -R spec --timeout 480000" + }, + "license": "BSD-3-Clause", + "keywords": [ + "sql", + "sqlite", + "sqlite3", + "database" + ], + "main": "./lib/sqlite3", + "types": "./lib/sqlite3.d.ts", + "renovate": { + "extends": [ + "@tryghost:base" + ] + } } diff --git a/scripts/build-appveyor.bat b/scripts/build-appveyor.bat deleted file mode 100644 index 020508927..000000000 --- a/scripts/build-appveyor.bat +++ /dev/null @@ -1,181 +0,0 @@ -@ECHO OFF -SETLOCAL -SET EL=0 - -ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -SET PATH=%CD%;%PATH% -SET msvs_version=2013 -IF "%msvs_toolset%"=="14" SET msvs_version=2015 - -ECHO APPVEYOR^: %APPVEYOR% -ECHO nodejs_version^: %nodejs_version% -ECHO platform^: %platform% -ECHO msvs_toolset^: %msvs_toolset% -ECHO msvs_version^: %msvs_version% -ECHO TOOLSET_ARGS^: %TOOLSET_ARGS% - - -ECHO activating VS command prompt -:: NOTE this call makes the x64 -> X64 -IF /I "%platform%"=="x64" ECHO x64 && CALL "C:\Program Files (x86)\Microsoft Visual Studio %msvs_toolset%.0\VC\vcvarsall.bat" amd64 -IF /I "%platform%"=="x86" ECHO x86 && CALL "C:\Program Files (x86)\Microsoft Visual Studio %msvs_toolset%.0\VC\vcvarsall.bat" x86 -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -ECHO using compiler^: && CALL cl -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -ECHO using MSBuild^: && CALL msbuild /version && ECHO. -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - - -ECHO downloading/installing node -::only use Install-Product when using VS2013 -::IF /I "%APPVEYOR%"=="True" IF /I "%msvs_toolset%"=="12" powershell Install-Product node $env:nodejs_version $env:Platform -::TESTING: -::always install (get npm matching node), but delete installed programfiles node.exe afterwards for VS2015 (using custom node.exe) -IF /I "%APPVEYOR%"=="True" GOTO APPVEYOR_INSTALL -GOTO SKIP_APPVEYOR_INSTALL - -:APPVEYOR_INSTALL -IF /I "%platform%"=="x64" powershell Install-Product node $env:nodejs_version x64 -IF /I "%platform%"=="x86" powershell Install-Product node $env:nodejs_version x86 -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -SET NODE_MAJOR=%nodejs_version:~0,1% -ECHO node major version^: %NODE_MAJOR% -IF %NODE_MAJOR% GTR 0 ECHO node version greater than zero, not updating npm && GOTO SKIP_APPVEYOR_INSTALL - -powershell Set-ExecutionPolicy Unrestricted -Scope CurrentUser -Force -IF %ERRORLEVEL% NEQ 0 GOTO ERROR -CALL npm install --global --production npm-windows-upgrade -IF %ERRORLEVEL% NEQ 0 GOTO ERROR -REM https://ci.appveyor.com/project/Mapbox/node-sqlite3/build/1.0.500/job/n2y9fo4eg316db56#L289 -REM error C2373: '__pfnDliNotifyHook2': redefinition; different type modifiers -REM at least 2.15.9 is needed: https://github.com/nodejs/node-gyp/issues/972#issuecomment-231055109 -CALL npm-windows-upgrade --npm-version 2.15.9 --no-dns-check --no-prompt -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -:SKIP_APPVEYOR_INSTALL -IF /I "%msvs_toolset%"=="12" GOTO NODE_INSTALLED - - -::custom node for VS2015 -SET ARCHPATH= -IF "%platform%"=="X64" (SET ARCHPATH=x64/) -IF "%platform%"=="x64" (SET ARCHPATH=x64/) -SET NODE_URL=https://mapbox.s3.amazonaws.com/node-cpp11/v%nodejs_version%/%ARCHPATH%node.exe -ECHO downloading node^: %NODE_URL% -powershell Invoke-WebRequest "${env:NODE_URL}" -OutFile node.exe -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -ECHO deleting node ... -SET NODE_EXE_PRG=%ProgramFiles%\nodejs\node.exe -IF EXIST "%NODE_EXE_PRG%" ECHO found %NODE_EXE_PRG%, deleting... && DEL /F "%NODE_EXE_PRG%" -IF %ERRORLEVEL% NEQ 0 GOTO ERROR -IF EXIST "%ProgramFiles%\nodejs" ECHO copy custom node.exe to %ProgramFiles%\nodejs\ && COPY node.exe "%ProgramFiles%\nodejs\" -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -SET NODE_EXE_PRG=%ProgramFiles(x86)%\nodejs\node.exe -IF EXIST "%NODE_EXE_PRG%" ECHO found %NODE_EXE_PRG%, deleting... && DEL /F "%NODE_EXE_PRG%" -IF %ERRORLEVEL% NEQ 0 GOTO ERROR -IF EXIST "%ProgramFiles(x86)%\nodejs" ECHO copy custom node.exe to %ProgramFiles(x86)%\nodejs\ && COPY node.exe "%ProgramFiles(x86)%\nodejs\" -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -ECHO delete node.exe in current directory && DEL node.exe -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -:NODE_INSTALLED - -ECHO available node.exe^: -call where node -ECHO available npm^: -call where npm - -ECHO node^: && call node -v -call node -e "console.log(' - arch:',process.arch,'\n - argv:',process.argv,'\n - execPath:',process.execPath)" -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -ECHO npm^: && CALL npm -v -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -ECHO ===== where npm puts stuff START ============ -ECHO npm root && CALL npm root -IF %ERRORLEVEL% NEQ 0 GOTO ERROR -ECHO npm root -g && CALL npm root -g -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -ECHO npm bin && CALL npm bin -IF %ERRORLEVEL% NEQ 0 GOTO ERROR -ECHO npm bin -g && CALL npm bin -g -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -SET NPM_BIN_DIR= -FOR /F "tokens=*" %%i in ('CALL npm bin -g') DO SET NPM_BIN_DIR=%%i -IF %ERRORLEVEL% NEQ 0 GOTO ERROR -IF /I "%NPM_BIN_DIR%"=="%CD%" ECHO ERROR npm bin -g equals local directory && SET ERRORLEVEL=1 && GOTO ERROR -ECHO ===== where npm puts stuff END ============ - - -ECHO installing node-gyp -CALL npm install -g node-gyp -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -CALL npm install --build-from-source --msvs_version=%msvs_version% %TOOLSET_ARGS% --loglevel=http -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -FOR /F "tokens=*" %%i in ('CALL node_modules\.bin\node-pre-gyp reveal module --silent') DO SET MODULE=%%i -IF %ERRORLEVEL% NEQ 0 GOTO ERROR -FOR /F "tokens=*" %%i in ('node -e "console.log(process.execPath)"') DO SET NODE_EXE=%%i -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -dumpbin /DEPENDENTS "%NODE_EXE%" -IF %ERRORLEVEL% NEQ 0 GOTO ERROR -dumpbin /DEPENDENTS "%MODULE%" -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - - -::skipping check for errorlevel npm test result when using io.js -::@springmeyer: how to proceed? -IF NOT "%nodejs_version%"=="1.8.1" IF NOT "%nodejs_version%"=="2.0.0" GOTO CHECK_NPM_TEST_ERRORLEVEL - -ECHO calling npm test -CALL npm test -ECHO ========================================== -ECHO ========================================== -ECHO ========================================== -ECHO using iojs, not checking test result!!!!!!!!! -ECHO ========================================== -ECHO ========================================== -ECHO ========================================== - -GOTO NPM_TEST_FINISHED - - -:CHECK_NPM_TEST_ERRORLEVEL -ECHO calling npm test -CALL npm test -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -:NPM_TEST_FINISHED - - -CALL node_modules\.bin\node-pre-gyp package %TOOLSET_ARGS% -::make commit message env var shorter -SET CM=%APPVEYOR_REPO_COMMIT_MESSAGE% -IF NOT "%CM%" == "%CM:[publish binary]=%" (ECHO publishing && CALL node_modules\.bin\node-pre-gyp --msvs_version=%msvs_version% publish %TOOLSET_ARGS%) ELSE (ECHO not publishing) -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -GOTO DONE - - - -:ERROR -ECHO ~~~~~~~~~~~~~~~~~~~~~~ ERROR %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -ECHO ERRORLEVEL^: %ERRORLEVEL% -SET EL=%ERRORLEVEL% - -:DONE -ECHO ~~~~~~~~~~~~~~~~~~~~~~ DONE %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -EXIT /b %EL% diff --git a/scripts/build-local.bat b/scripts/build-local.bat deleted file mode 100644 index 615aa4a96..000000000 --- a/scripts/build-local.bat +++ /dev/null @@ -1,65 +0,0 @@ -@ECHO OFF -SETLOCAL -SET EL=0 - -ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -SET PATH=C:\Python27;%PATH% - -SET APPVEYOR_REPO_COMMIT_MESSAGE=local build - -IF EXIST lib\binding ECHO deleting lib/binding && RD /Q /S lib\binding -IF %ERRORLEVEL% NEQ 0 GOTO ERROR -IF EXIST node_modules ECHO deleting node_modules && RD /Q /S node_modules -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -GOTO VS2015 - -ECHO ============================ -ECHO VS2013 -ECHO ============================ -SET nodejs_version=4.4.2 -SET platform=x86 -SET msvs_toolset=12 -SET TOOLSET_ARGS= - -CALL scripts\build-appveyor.bat -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -GOTO DONE - -:VS2015 - -IF EXIST lib\binding ECHO deleting lib/binding && RD /Q /S lib\binding -IF %ERRORLEVEL% NEQ 0 GOTO ERROR -IF EXIST node_modules ECHO deleting node_modules && RD /Q /S node_modules -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - -ECHO ============================ -ECHO VS2015 -ECHO ============================ -SET nodejs_version=0.10.40 -ECHO SET nodejs_version^: %nodejs_version% -SET platform=x64 -ECHO SET platform^: %platform% -SET msvs_toolset=14 -ECHO SET msvs_toolset^: %msvs_toolset% -::SET TOOLSET_ARGS=--dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --toolset=v140 - -CALL scripts\build-appveyor.bat -IF %ERRORLEVEL% NEQ 0 GOTO ERROR - - - - -GOTO DONE - -:ERROR -ECHO ~~~~~~~~~~~~~~~~~~~~~~ ERROR %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -ECHO ERRORLEVEL^: %ERRORLEVEL% -SET EL=%ERRORLEVEL% - -:DONE -ECHO ~~~~~~~~~~~~~~~~~~~~~~ DONE %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -EXIT /b %EL% diff --git a/scripts/build_against_node.sh b/scripts/build_against_node.sh deleted file mode 100755 index 2982740f2..000000000 --- a/scripts/build_against_node.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env bash - -source ~/.nvm/nvm.sh - -set -e -u - -function publish() { - if [[ ${PUBLISHABLE:-false} == true ]] && [[ ${COMMIT_MESSAGE} =~ "[publish binary]" ]]; then - node-pre-gyp package testpackage - node-pre-gyp publish - node-pre-gyp info - make clean - fi -} - -# test installing from source -if [[ ${COVERAGE} == true ]]; then - CXXFLAGS="--coverage" LDFLAGS="--coverage" npm install --build-from-source --clang=1 - npm test - ./py-local/bin/cpp-coveralls --exclude node_modules --exclude tests --build-root build --gcov-options '\-lp' --exclude docs --exclude build/Release/obj/gen --exclude deps > /dev/null -else - npm install --build-from-source --clang=1 - npm test -fi - - -publish - -# now test building against shared sqlite -export NODE_SQLITE3_JSON1=no -if [[ $(uname -s) == 'Darwin' ]]; then - brew install sqlite - npm install --build-from-source --sqlite=$(brew --prefix) --clang=1 -else - npm install --build-from-source --sqlite=/usr --clang=1 -fi -npm test -export NODE_SQLITE3_JSON1=yes - -platform=$(uname -s | sed "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/") - -: ' -if [[ $(uname -s) == 'Linux' ]]; then - # node v0.8 and above provide pre-built 32 bit and 64 bit binaries - # so here we use the 32 bit ones to also test 32 bit builds - NVER=`node -v` - # enable 32 bit node - export PATH=$(pwd)/node-${NVER}-${platform}-x86/bin:$PATH - if [[ ${NODE_VERSION:0:4} == 'iojs' ]]; then - wget https://iojs.org/download/release/${NVER}/iojs-${NVER}-${platform}-x86.tar.gz - tar xf iojs-${NVER}-${platform}-x86.tar.gz - # enable 32 bit iojs - export PATH=$(pwd)/iojs-${NVER}-${platform}-x86/bin:$(pwd)/iojs-${NVER}-${platform}-ia32/bin:$PATH - else - wget http://nodejs.org/dist/${NVER}/node-${NVER}-${platform}-x86.tar.gz - tar xf node-${NVER}-${platform}-x86.tar.gz - # enable 32 bit node - export PATH=$(pwd)/node-${NVER}-${platform}-x86/bin:$(pwd)/node-${NVER}-${platform}-ia32/bin:$PATH - fi - which node - ls -l $(which node) - #node -e "console.log(process.arch,process.execPath)" - # install 32 bit compiler toolchain and X11 - # test source compile in 32 bit mode with internal libsqlite3 - CC=gcc-4.6 CXX=g++-4.6 npm install --build-from-source --clang=1 - node-pre-gyp package testpackage - npm test - publish - make clean - # broken for some unknown reason against io.js - if [[ ${NODE_VERSION:0:4} != 'iojs' ]]; then - # test source compile in 32 bit mode against external libsqlite3 - export NODE_SQLITE3_JSON1=no - CC=gcc-4.6 CXX=g++-4.6 npm install --build-from-source --sqlite=/usr --clang=1 - npm test - fi -fi - -' diff --git a/scripts/build_against_node_webkit.sh b/scripts/build_against_node_webkit.sh deleted file mode 100755 index 94706b4fd..000000000 --- a/scripts/build_against_node_webkit.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env bash - - -if [[ ! -d ../.nvm ]]; then - git clone https://github.com/creationix/nvm.git ../.nvm -fi -source ../.nvm/nvm.sh -nvm install 0.10 - -set -u -e - -npm install nw-gyp -g - -OLD_PATH="$PATH" - -GYP_ARGS="--runtime=node-webkit --target=${NODE_WEBKIT} --target_arch=${TARGET_ARCH}" -if [[ $(uname -s) == 'Darwin' ]]; then - if [[ '${TARGET_ARCH}' == 'x64' ]]; then - # do not build on Mac OS X x64 until node-webkit 0.10.1 is released - false - fi -fi - -if [[ $(uname -s) == 'Darwin' ]]; then - export NW_DOWNLOAD=node-webkit-v${NODE_WEBKIT}-osx-${TARGET_ARCH} - wget http://dl.node-webkit.org/v${NODE_WEBKIT}/${NW_DOWNLOAD}.zip - unzip -q ${NW_DOWNLOAD}.zip - export PATH=$(pwd)/node-webkit.app/Contents/MacOS/:${PATH} - # v0.10.0-rc1 unzips with extra folder - export PATH=$(pwd)/${NW_DOWNLOAD}/node-webkit.app/Contents/MacOS/:${PATH} - npm install --build-from-source ${GYP_ARGS} -else - sudo apt-get install build-essential - # Linux - export NW_DOWNLOAD=node-webkit-v${NODE_WEBKIT}-linux-${TARGET_ARCH} - # for testing node-webkit, launch a virtual display - export DISPLAY=:99.0 - # NOTE: travis already has xvfb installed - # http://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-xvfb-to-Run-Tests-That-Require-GUI-%28e.g.-a-Web-browser%29 - sh -e /etc/init.d/xvfb start +extension RANDR - wget http://dl.node-webkit.org/v${NODE_WEBKIT}/${NW_DOWNLOAD}.tar.gz - tar xf ${NW_DOWNLOAD}.tar.gz - export PATH=$(pwd)/${NW_DOWNLOAD}:${PATH} - if [[ "${TARGET_ARCH}" == 'ia32' ]]; then - # for nw >= 0.11.0 on ia32 we need gcc/g++ 4.8 - IFS='.' read -a NODE_WEBKIT_VERSION <<< "${NODE_WEBKIT}" - if test ${NODE_WEBKIT_VERSION[0]} -ge 0 -a ${NODE_WEBKIT_VERSION[1]} -ge 11; then - # travis-ci runs ubuntu 12.04, so we need this ppa for gcc/g++ 4.8 - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test - export CC=gcc-4.8 - export CXX=g++-4.8 - export CXXFLAGS="-fpermissive" - COMPILER_PACKAGES="gcc-4.8-multilib g++-4.8-multilib" - else - export CC=gcc-4.6 - export CXX=g++-4.6 - export CXXFLAGS="-fpermissive" - COMPILER_PACKAGES="gcc-multilib g++-multilib" - fi - # need to update to avoid 404 for linux-libc-dev_3.2.0-64.97_amd64.deb - sudo apt-get update - # prepare packages for 32-bit builds on Linux - sudo apt-get -y install $COMPILER_PACKAGES libx11-6:i386 libnotify4:i386 libxtst6:i386 libcap2:i386 libglib2.0-0:i386 libgtk2.0-0:i386 libatk1.0-0:i386 libgdk-pixbuf2.0-0:i386 libcairo2:i386 libfreetype6:i386 libfontconfig1:i386 libxcomposite1:i386 libasound2:i386 libxdamage1:i386 libxext6:i386 libxfixes3:i386 libnss3:i386 libnspr4:i386 libgconf-2-4:i386 libexpat1:i386 libdbus-1-3:i386 libudev0:i386 - # also use ldd to find out if some necessary apt-get is missing - ldd $(pwd)/${NW_DOWNLOAD}/nw - npm install --build-from-source ${GYP_ARGS} - else - npm install --build-from-source ${GYP_ARGS} - fi -fi - -# test the package -node-pre-gyp package testpackage ${GYP_ARGS} - -PUBLISH_BINARY=false -if test "${COMMIT_MESSAGE#*'[publish binary]'}" != "$COMMIT_MESSAGE"; then - node-pre-gyp publish ${GYP_ARGS} - node-pre-gyp info ${GYP_ARGS} - node-pre-gyp clean ${GYP_ARGS} - make clean - # now install from binary - INSTALL_RESULT=$(npm install ${GYP_ARGS} --fallback-to-build=false > /dev/null)$? || true - # if install returned non zero (errored) then we first unpublish and then call false so travis will bail at this line - if [[ $INSTALL_RESULT != 0 ]]; then echo "returned $INSTALL_RESULT";node-pre-gyp unpublish ${GYP_ARGS};false; fi - # If success then we arrive here so lets clean up - node-pre-gyp clean ${GYP_ARGS} -fi - -# restore PATH -export PATH="$OLD_PATH" -rm -rf ${NW_DOWNLOAD} diff --git a/scripts/build_for_node_webkit.cmd b/scripts/build_for_node_webkit.cmd deleted file mode 100644 index 2a0878fc4..000000000 --- a/scripts/build_for_node_webkit.cmd +++ /dev/null @@ -1,15 +0,0 @@ -echo Platform: %1 -echo The list of environment variables: -set -if not "%1" == "x86" goto end -if "%nw_version%" == "" goto end -call npm install nw-gyp -call cinst wget 7zip.commandline -call wget http://dl.node-webkit.org/v%nw_version%/node-webkit-v%nw_version%-win-ia32.zip -call 7z e -onw node-webkit-v%nw_version%-win-ia32.zip -dir nw -set PATH=nw;%PATH% -call node-pre-gyp rebuild --runtime=node-webkit --target=%nw_version% --target_arch=ia32 -call node-pre-gyp package testpackage --runtime=node-webkit --target=%nw_version% --target_arch=ia32 -if not "%CM%" == "%CM:[publish binary]=%" call node-pre-gyp publish --msvs_version=2013 --runtime=node-webkit --target=%nw_version% --target_arch=ia32 -:end \ No newline at end of file diff --git a/scripts/install_node.sh b/scripts/install_node.sh deleted file mode 100755 index d534f77a5..000000000 --- a/scripts/install_node.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -if [[ ${1:-false} == 'false' ]]; then - echo "Error: pass node version as first argument" - exit 1 -fi - -NODE_VERSION=$1 - -# if an existing nvm is already installed we need to unload it -nvm unload || true - -# here we set up the node version on the fly based on the matrix value. -# This is done manually so that the build works the same on OS X -rm -rf ./__nvm/ && git clone --depth 1 https://github.com/creationix/nvm.git ./__nvm -source ./__nvm/nvm.sh -nvm install ${NODE_VERSION} -nvm use ${NODE_VERSION} -node --version -npm --version -which node \ No newline at end of file diff --git a/scripts/validate_tag.sh b/scripts/validate_tag.sh deleted file mode 100755 index 67d039b70..000000000 --- a/scripts/validate_tag.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -set -u - -# let's catch the case where we tag but -# forget to increment the package.json version - -# check if we are on a tag -if [ `git describe --tags --always HEAD` ]; then - echo 'looks like we are on a tag' - if [[ $TRAVIS_BRANCH == `git describe --tags --always HEAD` ]]; then - echo 'git reports the same tag as travis' - # now check to make sure package.json `version` matches - MODULE_VERSION=$(node -e "console.log(require('./package.json').version)") - if [[ $MODULE_VERSION != $TRAVIS_BRANCH ]] && [[ v$MODULE_VERSION != $TRAVIS_BRANCH ]]; then - echo "package.json version ($MODULE_VERSION) does not match tag ($TRAVIS_BRANCH)" - exit 1 - else - echo "Validation success: package.json ($MODULE_VERSION) matches tag ($TRAVIS_BRANCH)" - fi - else - echo "warning: travis thinks the tag ($TRAVIS_BRANCH) differs from git (`git describe --tags --always HEAD`)" - fi -fi diff --git a/sqlite3.js b/sqlite3.js deleted file mode 100644 index c4b587d07..000000000 --- a/sqlite3.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./lib/sqlite3'); diff --git a/src/async.h b/src/async.h index 5232c127d..f36e4cbc2 100644 --- a/src/async.h +++ b/src/async.h @@ -1,13 +1,10 @@ #ifndef NODE_SQLITE3_SRC_ASYNC_H #define NODE_SQLITE3_SRC_ASYNC_H -#include "threading.h" -#include - -#if defined(NODE_SQLITE3_BOOST_THREADING) -#include -#endif +#include +#include +#include "threading.h" // Generic uv_async handler. template class Async { @@ -26,24 +23,25 @@ template class Async { : callback(cb_), parent(parent_) { watcher.data = this; NODE_SQLITE3_MUTEX_INIT - uv_async_init(uv_default_loop(), &watcher, reinterpret_cast(listener)); + uv_loop_t *loop; + napi_get_uv_event_loop(parent_->Env(), &loop); + uv_async_init(loop, &watcher, reinterpret_cast(listener)); } - static void listener(uv_async_t* handle, int status) { - Async* async = static_cast(handle->data); + static void listener(uv_async_t* handle) { + auto* async = static_cast(handle->data); std::vector rows; NODE_SQLITE3_MUTEX_LOCK(&async->mutex) rows.swap(async->data); NODE_SQLITE3_MUTEX_UNLOCK(&async->mutex) - for (unsigned int i = 0, size = rows.size(); i < size; i++) { - async->callback(async->parent, rows[i]); - } + for(auto row : rows) + async->callback(async->parent, row); } static void close(uv_handle_t* handle) { assert(handle != NULL); assert(handle->data != NULL); - Async* async = static_cast(handle->data); + auto* async = static_cast(handle->data); delete async; } @@ -51,13 +49,13 @@ template class Async { // Need to call the listener again to ensure all items have been // processed. Is this a bug in uv_async? Feels like uv_close // should handle that. - listener(&watcher, 0); + listener(&watcher); uv_close((uv_handle_t*)&watcher, close); } void add(Item* item) { NODE_SQLITE3_MUTEX_LOCK(&mutex); - data.push_back(item); + data.emplace_back(item); NODE_SQLITE3_MUTEX_UNLOCK(&mutex) } diff --git a/src/backup.cc b/src/backup.cc new file mode 100644 index 000000000..0f971f5e9 --- /dev/null +++ b/src/backup.cc @@ -0,0 +1,418 @@ +#include +#include +#include "macros.h" +#include "database.h" +#include "backup.h" + +using namespace node_sqlite3; + +Napi::Object Backup::Init(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); + + // declare napi_default_method here as it is only available in Node v14.12.0+ + auto napi_default_method = static_cast(napi_writable | napi_configurable); + + auto t = DefineClass(env, "Backup", { + InstanceMethod("step", &Backup::Step, napi_default_method), + InstanceMethod("finish", &Backup::Finish, napi_default_method), + InstanceAccessor("idle", &Backup::IdleGetter, nullptr), + InstanceAccessor("completed", &Backup::CompletedGetter, nullptr), + InstanceAccessor("failed", &Backup::FailedGetter, nullptr), + InstanceAccessor("remaining", &Backup::RemainingGetter, nullptr), + InstanceAccessor("pageCount", &Backup::PageCountGetter, nullptr), + InstanceAccessor("retryErrors", &Backup::RetryErrorGetter, &Backup::RetryErrorSetter), + }); + + exports.Set("Backup", t); + return exports; +} + +void Backup::Process() { + if (finished && !queue.empty()) { + return CleanQueue(); + } + + while (inited && !locked && !queue.empty()) { + auto call = std::move(queue.front()); + queue.pop(); + + call->callback(call->baton); + } +} + +void Backup::Schedule(Work_Callback callback, Baton* baton) { + if (finished) { + queue.emplace(new Call(callback, baton)); + CleanQueue(); + } + else if (!inited || locked || !queue.empty()) { + queue.emplace(new Call(callback, baton)); + } + else { + callback(baton); + } +} + +template void Backup::Error(T* baton) { + auto env = baton->backup->Env(); + Napi::HandleScope scope(env); + + Backup* backup = baton->backup; + // Fail hard on logic errors. + assert(backup->status != 0); + EXCEPTION(Napi::String::New(env, backup->message), backup->status, exception); + + Napi::Function cb = baton->callback.Value(); + + if (!cb.IsEmpty() && cb.IsFunction()) { + Napi::Value argv[] = { exception }; + TRY_CATCH_CALL(backup->Value(), cb, 1, argv); + } + else { + Napi::Value argv[] = { Napi::String::New(env, "error"), exception }; + EMIT_EVENT(backup->Value(), 2, argv); + } +} + +void Backup::CleanQueue() { + auto env = this->Env(); + Napi::HandleScope scope(env); + + if (inited && !queue.empty()) { + // This backup has already been initialized and is now finished. + // Fire error for all remaining items in the queue. + EXCEPTION(Napi::String::New(env, "Backup is already finished"), SQLITE_MISUSE, exception); + Napi::Value argv[] = { exception }; + bool called = false; + + // Clear out the queue so that this object can get GC'ed. + while (!queue.empty()) { + auto call = std::move(queue.front()); + queue.pop(); + + std::unique_ptr baton(call->baton); + Napi::Function cb = baton->callback.Value(); + + if (inited && !cb.IsEmpty() && + cb.IsFunction()) { + TRY_CATCH_CALL(Value(), cb, 1, argv); + called = true; + } + } + + // When we couldn't call a callback function, emit an error on the + // Backup object. + if (!called) { + Napi::Value info[] = { Napi::String::New(env, "error"), exception }; + EMIT_EVENT(Value(), 2, info); + } + } + else while (!queue.empty()) { + // Just delete all items in the queue; we already fired an event when + // initializing the backup failed. + auto call = std::move(queue.front()); + queue.pop(); + + // We don't call the actual callback, so we have to make sure that + // the baton gets destroyed. + delete call->baton; + } +} + +Backup::Backup(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info) { + auto env = info.Env(); + if (!info.IsConstructCall()) { + Napi::TypeError::New(env, "Use the new operator to create new Backup objects").ThrowAsJavaScriptException(); + return; + } + + auto length = info.Length(); + + if (length <= 0 || !Database::HasInstance(info[0])) { + Napi::TypeError::New(env, "Database object expected").ThrowAsJavaScriptException(); + return; + } + else if (length <= 1 || !info[1].IsString()) { + Napi::TypeError::New(env, "Filename expected").ThrowAsJavaScriptException(); + return; + } + else if (length <= 2 || !info[2].IsString()) { + Napi::TypeError::New(env, "Source database name expected").ThrowAsJavaScriptException(); + return; + } + else if (length <= 3 || !info[3].IsString()) { + Napi::TypeError::New(env, "Destination database name expected").ThrowAsJavaScriptException(); + return; + } + else if (length <= 4 || !info[4].IsBoolean()) { + Napi::TypeError::New(env, "Direction flag expected").ThrowAsJavaScriptException(); + return; + } + else if (length > 5 && !info[5].IsUndefined() && !info[5].IsFunction()) { + Napi::TypeError::New(env, "Callback expected").ThrowAsJavaScriptException(); + return; + } + + this->db = Napi::ObjectWrap::Unwrap(info[0].As()); + this->db->Ref(); + + auto filename = info[1].As(); + auto sourceName = info[2].As(); + auto destName = info[3].As(); + auto filenameIsDest = info[4].As(); + + info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("filename", filename)); + info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("sourceName", sourceName)); + info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("destName", destName)); + info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("filenameIsDest", filenameIsDest)); + + auto* baton = new InitializeBaton(this->db, info[5].As(), this); + baton->filename = filename.Utf8Value(); + baton->sourceName = sourceName.Utf8Value(); + baton->destName = destName.Utf8Value(); + baton->filenameIsDest = filenameIsDest.Value(); + + this->db->Schedule(Work_BeginInitialize, baton); +} + +void Backup::Work_BeginInitialize(Database::Baton* baton) { + assert(baton->db->open); + baton->db->pending++; + auto env = baton->db->Env(); + CREATE_WORK("sqlite3.Backup.Initialize", Work_Initialize, Work_AfterInitialize); +} + +void Backup::Work_Initialize(napi_env e, void* data) { + BACKUP_INIT(InitializeBaton); + + // In case stepping fails, we use a mutex to make sure we get the associated + // error message. + auto* mtx = sqlite3_db_mutex(baton->db->_handle); + sqlite3_mutex_enter(mtx); + + backup->status = sqlite3_open(baton->filename.c_str(), &backup->_otherDb); + + if (backup->status == SQLITE_OK) { + backup->_handle = sqlite3_backup_init( + baton->filenameIsDest ? backup->_otherDb : backup->db->_handle, + baton->destName.c_str(), + baton->filenameIsDest ? backup->db->_handle : backup->_otherDb, + baton->sourceName.c_str()); + } + backup->_destDb = baton->filenameIsDest ? backup->_otherDb : backup->db->_handle; + + if (backup->status != SQLITE_OK) { + backup->message = std::string(sqlite3_errmsg(backup->_destDb)); + sqlite3_close(backup->_otherDb); + backup->_otherDb = NULL; + backup->_destDb = NULL; + } + + sqlite3_mutex_leave(mtx); +} + +void Backup::Work_AfterInitialize(napi_env e, napi_status status, void* data) { + std::unique_ptr baton(static_cast(data)); + auto* backup = baton->backup; + + auto env = backup->Env(); + Napi::HandleScope scope(env); + + if (backup->status != SQLITE_OK) { + Error(baton.get()); + backup->FinishAll(); + } + else { + backup->inited = true; + Napi::Function cb = baton->callback.Value(); + if (!cb.IsEmpty() && cb.IsFunction()) { + Napi::Value argv[] = { env.Null() }; + TRY_CATCH_CALL(backup->Value(), cb, 1, argv); + } + } + BACKUP_END(); +} + +Napi::Value Backup::Step(const Napi::CallbackInfo& info) { + auto* backup = this; + auto env = backup->Env(); + + REQUIRE_ARGUMENT_INTEGER(0, pages); + OPTIONAL_ARGUMENT_FUNCTION(1, callback); + + auto* baton = new StepBaton(backup, callback, pages); + backup->GetRetryErrors(baton->retryErrorsSet); + backup->Schedule(Work_BeginStep, baton); + return info.This(); +} + +void Backup::Work_BeginStep(Baton* baton) { + BACKUP_BEGIN(Step); +} + +void Backup::Work_Step(napi_env e, void* data) { + BACKUP_INIT(StepBaton); + if (backup->_handle) { + backup->status = sqlite3_backup_step(backup->_handle, baton->pages); + backup->remaining = sqlite3_backup_remaining(backup->_handle); + backup->pageCount = sqlite3_backup_pagecount(backup->_handle); + } + if (backup->status != SQLITE_OK) { + // Text of message is a little awkward to get, since the error is not associated + // with a db connection. +#if SQLITE_VERSION_NUMBER >= 3007015 + // sqlite3_errstr is a relatively new method + backup->message = std::string(sqlite3_errstr(backup->status)); +#else + backup->message = "Sqlite error"; +#endif + if (baton->retryErrorsSet.size() > 0) { + if (baton->retryErrorsSet.find(backup->status) == baton->retryErrorsSet.end()) { + backup->FinishSqlite(); + } + } + } +} + +void Backup::Work_AfterStep(napi_env e, napi_status status, void* data) { + std::unique_ptr baton(static_cast(data)); + auto* backup = baton->backup; + + auto env = backup->Env(); + Napi::HandleScope scope(env); + + if (backup->status == SQLITE_DONE) { + backup->completed = true; + } else if (!backup->_handle) { + backup->failed = true; + } + + if (backup->status != SQLITE_OK && backup->status != SQLITE_DONE) { + Error(baton.get()); + } + else { + // Fire callbacks. + Napi::Function cb = baton->callback.Value(); + if (!cb.IsEmpty() && cb.IsFunction()) { + Napi::Value argv[] = { env.Null(), Napi::Boolean::New(env, backup->status == SQLITE_DONE) }; + TRY_CATCH_CALL(backup->Value(), cb, 2, argv); + } + } + + BACKUP_END(); +} + +Napi::Value Backup::Finish(const Napi::CallbackInfo& info) { + auto* backup = this; + auto env = backup->Env(); + + OPTIONAL_ARGUMENT_FUNCTION(0, callback); + + auto* baton = new Baton(backup, callback); + backup->Schedule(Work_BeginFinish, baton); + return info.This(); +} + +void Backup::Work_BeginFinish(Baton* baton) { + BACKUP_BEGIN(Finish); +} + +void Backup::Work_Finish(napi_env e, void* data) { + BACKUP_INIT(Baton); + backup->FinishSqlite(); +} + +void Backup::Work_AfterFinish(napi_env e, napi_status status, void* data) { + std::unique_ptr baton(static_cast(data)); + auto* backup = baton->backup; + + auto env = backup->Env(); + Napi::HandleScope scope(env); + + backup->FinishAll(); + + // Fire callback in case there was one. + Napi::Function cb = baton->callback.Value(); + if (!cb.IsEmpty() && cb.IsFunction()) { + TRY_CATCH_CALL(backup->Value(), cb, 0, NULL); + } + + BACKUP_END(); +} + +void Backup::FinishAll() { + assert(!finished); + if (!completed && !failed) { + failed = true; + } + finished = true; + CleanQueue(); + FinishSqlite(); + db->Unref(); +} + +void Backup::FinishSqlite() { + if (_handle) { + sqlite3_backup_finish(_handle); + _handle = NULL; + } + if (_otherDb) { + sqlite3_close(_otherDb); + _otherDb = NULL; + } + _destDb = NULL; +} + +Napi::Value Backup::IdleGetter(const Napi::CallbackInfo& info) { + auto* backup = this; + bool idle = backup->inited && !backup->locked && backup->queue.empty(); + return Napi::Boolean::New(this->Env(), idle); +} + +Napi::Value Backup::CompletedGetter(const Napi::CallbackInfo& info) { + auto* backup = this; + return Napi::Boolean::New(this->Env(), backup->completed); +} + +Napi::Value Backup::FailedGetter(const Napi::CallbackInfo& info) { + auto* backup = this; + return Napi::Boolean::New(this->Env(), backup->failed); +} + +Napi::Value Backup::RemainingGetter(const Napi::CallbackInfo& info) { + auto* backup = this; + return Napi::Number::New(this->Env(), backup->remaining); +} + +Napi::Value Backup::PageCountGetter(const Napi::CallbackInfo& info) { + auto* backup = this; + return Napi::Number::New(this->Env(), backup->pageCount); +} + +Napi::Value Backup::RetryErrorGetter(const Napi::CallbackInfo& info) { + auto* backup = this; + return backup->retryErrors.Value(); +} + +void Backup::RetryErrorSetter(const Napi::CallbackInfo& info, const Napi::Value& value) { + auto* backup = this; + auto env = backup->Env(); + if (!value.IsArray()) { + Napi::Error::New(env, "retryErrors must be an array").ThrowAsJavaScriptException(); + return; + } + Napi::Array array = value.As(); + backup->retryErrors.Reset(array, 1); +} + +void Backup::GetRetryErrors(std::set& retryErrorsSet) { + retryErrorsSet.clear(); + Napi::Array array = retryErrors.Value(); + auto length = array.Length(); + for (size_t i = 0; i < length; i++) { + Napi::Value code = (array).Get(static_cast(i)); + if (code.IsNumber()) { + retryErrorsSet.insert(code.As().Int32Value()); + } + } +} diff --git a/src/backup.h b/src/backup.h new file mode 100644 index 000000000..b894aca1a --- /dev/null +++ b/src/backup.h @@ -0,0 +1,209 @@ +#ifndef NODE_SQLITE3_SRC_BACKUP_H +#define NODE_SQLITE3_SRC_BACKUP_H + +#include "database.h" + +#include +#include +#include + +#include +#include + +using namespace Napi; + +namespace node_sqlite3 { + +/** + * + * A class for managing an sqlite3_backup object. For consistency + * with other node-sqlite3 classes, it maintains an internal queue + * of calls. + * + * Intended usage from node: + * + * var db = new sqlite3.Database('live.db'); + * var backup = db.backup('backup.db'); + * ... + * // in event loop, move backup forward when we have time. + * if (backup.idle) { backup.step(NPAGES); } + * if (backup.completed) { ... success ... } + * if (backup.failed) { ... sadness ... } + * // do other work in event loop - fine to modify live.db + * ... + * + * Here is how sqlite's backup api is exposed: + * + * - `sqlite3_backup_init`: This is implemented as + * `db.backup(filename, [callback])` or + * `db.backup(filename, destDbName, sourceDbName, filenameIsDest, [callback])`. + * - `sqlite3_backup_step`: `backup.step(pages, [callback])`. + * - `sqlite3_backup_finish`: `backup.finish([callback])`. + * - `sqlite3_backup_remaining`: `backup.remaining`. + * - `sqlite3_backup_pagecount`: `backup.pageCount`. + * + * There are the following read-only properties: + * + * - `backup.completed` is set to `true` when the backup + * succeeeds. + * - `backup.failed` is set to `true` when the backup + * has a fatal error. + * - `backup.idle` is set to `true` when no operation + * is currently in progress or queued for the backup. + * - `backup.remaining` is an integer with the remaining + * number of pages after the last call to `backup.step` + * (-1 if `step` not yet called). + * - `backup.pageCount` is an integer with the total number + * of pages measured during the last call to `backup.step` + * (-1 if `step` not yet called). + * + * There is the following writable property: + * + * - `backup.retryErrors`: an array of sqlite3 error codes + * that are treated as non-fatal - meaning, if they occur, + * backup.failed is not set, and the backup may continue. + * By default, this is `[sqlite3.BUSY, sqlite3.LOCKED]`. + * + * The `db.backup(filename, [callback])` shorthand is sufficient + * for making a backup of a database opened by node-sqlite3. If + * using attached or temporary databases, or moving data in the + * opposite direction, the more complete (but daunting) + * `db.backup(filename, destDbName, sourceDbName, filenameIsDest, [callback])` + * signature is provided. + * + * A backup will finish automatically when it succeeds or a fatal + * error occurs, meaning it is not necessary to call `db.finish()`. + * By default, SQLITE_LOCKED and SQLITE_BUSY errors are not + * treated as failures, and the backup will continue if they + * occur. The set of errors that are tolerated can be controlled + * by setting `backup.retryErrors`. To disable automatic + * finishing and stick strictly to sqlite's raw api, set + * `backup.retryErrors` to `[]`. In that case, it is necessary + * to call `backup.finish()`. + * + * In the same way as node-sqlite3 databases and statements, + * backup methods can be called safely without callbacks, due + * to an internal call queue. So for example this naive code + * will correctly back up a db, if there are no errors: + * + * var backup = db.backup('backup.db'); + * backup.step(-1); + * backup.finish(); + * + */ +class Backup : public Napi::ObjectWrap { +public: + static Napi::Object Init(Napi::Env env, Napi::Object exports); + + struct Baton { + napi_async_work request = NULL; + Backup* backup; + Napi::FunctionReference callback; + + Baton(Backup* backup_, Napi::Function cb_) : backup(backup_) { + backup->Ref(); + callback.Reset(cb_, 1); + } + virtual ~Baton() { + if (request) napi_delete_async_work(backup->Env(), request); + backup->Unref(); + callback.Reset(); + } + }; + + struct InitializeBaton : Database::Baton { + Backup* backup; + std::string filename; + std::string sourceName; + std::string destName; + bool filenameIsDest; + InitializeBaton(Database* db_, Napi::Function cb_, Backup* backup_) : + Baton(db_, cb_), backup(backup_), filenameIsDest(true) { + backup->Ref(); + } + virtual ~InitializeBaton() override { + backup->Unref(); + if (!db->IsOpen() && db->IsLocked()) { + // The database handle was closed before the backup could be opened. + backup->FinishAll(); + } + } + }; + + struct StepBaton : Baton { + int pages; + std::set retryErrorsSet; + StepBaton(Backup* backup_, Napi::Function cb_, int pages_) : + Baton(backup_, cb_), pages(pages_) {} + virtual ~StepBaton() override = default; + }; + + typedef void (*Work_Callback)(Baton* baton); + + struct Call { + Call(Work_Callback cb_, Baton* baton_) : callback(cb_), baton(baton_) {}; + Work_Callback callback; + Baton* baton; + }; + + Backup(const Napi::CallbackInfo& info); + + ~Backup() { + if (!finished) { + FinishAll(); + } + retryErrors.Reset(); + } + + WORK_DEFINITION(Step) + WORK_DEFINITION(Finish) + + Napi::Value IdleGetter(const Napi::CallbackInfo& info); + Napi::Value CompletedGetter(const Napi::CallbackInfo& info); + Napi::Value FailedGetter(const Napi::CallbackInfo& info); + Napi::Value PageCountGetter(const Napi::CallbackInfo& info); + Napi::Value RemainingGetter(const Napi::CallbackInfo& info); + Napi::Value FatalErrorGetter(const Napi::CallbackInfo& info); + Napi::Value RetryErrorGetter(const Napi::CallbackInfo& info); + + void FatalErrorSetter(const Napi::CallbackInfo& info, const Napi::Value& value); + void RetryErrorSetter(const Napi::CallbackInfo& info, const Napi::Value& value); + +protected: + static void Work_BeginInitialize(Database::Baton* baton); + static void Work_Initialize(napi_env env, void* data); + static void Work_AfterInitialize(napi_env env, napi_status status, void* data); + + void Schedule(Work_Callback callback, Baton* baton); + void Process(); + void CleanQueue(); + template static void Error(T* baton); + + void FinishAll(); + void FinishSqlite(); + void GetRetryErrors(std::set& retryErrorsSet); + + Database* db; + + sqlite3_backup* _handle = NULL; + sqlite3* _otherDb = NULL; + sqlite3* _destDb = NULL; + + bool inited = false; + bool locked = true; + bool completed = false; + bool failed = false; + int remaining = -1; + int pageCount = -1; + bool finished = false; + + int status; + std::string message; + std::queue> queue; + + Napi::Reference retryErrors; +}; + +} + +#endif diff --git a/src/database.cc b/src/database.cc index e7891cbd2..d495ce98f 100644 --- a/src/database.cc +++ b/src/database.cc @@ -1,4 +1,5 @@ -#include +#include +#include #include "macros.h" #include "database.h" @@ -6,100 +7,109 @@ using namespace node_sqlite3; -Nan::Persistent Database::constructor_template; - -NAN_MODULE_INIT(Database::Init) { - Nan::HandleScope scope; - - Local t = Nan::New(New); - - t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(Nan::New("Database").ToLocalChecked()); - - Nan::SetPrototypeMethod(t, "close", Close); - Nan::SetPrototypeMethod(t, "exec", Exec); - Nan::SetPrototypeMethod(t, "wait", Wait); - Nan::SetPrototypeMethod(t, "loadExtension", LoadExtension); - Nan::SetPrototypeMethod(t, "serialize", Serialize); - Nan::SetPrototypeMethod(t, "parallelize", Parallelize); - Nan::SetPrototypeMethod(t, "configure", Configure); - Nan::SetPrototypeMethod(t, "interrupt", Interrupt); - - NODE_SET_GETTER(t, "open", OpenGetter); - - constructor_template.Reset(t); - - Nan::Set(target, Nan::New("Database").ToLocalChecked(), - Nan::GetFunction(t).ToLocalChecked()); +#if NAPI_VERSION < 6 +Napi::FunctionReference Database::constructor; +#endif + +Napi::Object Database::Init(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); + // declare napi_default_method here as it is only available in Node v14.12.0+ + auto napi_default_method = static_cast(napi_writable | napi_configurable); + + auto t = DefineClass(env, "Database", { + InstanceMethod("close", &Database::Close, napi_default_method), + InstanceMethod("exec", &Database::Exec, napi_default_method), + InstanceMethod("wait", &Database::Wait, napi_default_method), + InstanceMethod("loadExtension", &Database::LoadExtension, napi_default_method), + InstanceMethod("serialize", &Database::Serialize, napi_default_method), + InstanceMethod("parallelize", &Database::Parallelize, napi_default_method), + InstanceMethod("configure", &Database::Configure, napi_default_method), + InstanceMethod("interrupt", &Database::Interrupt, napi_default_method), + InstanceAccessor("open", &Database::Open, nullptr) + }); + +#if NAPI_VERSION < 6 + constructor = Napi::Persistent(t); + constructor.SuppressDestruct(); +#else + Napi::FunctionReference* constructor = new Napi::FunctionReference(); + *constructor = Napi::Persistent(t); + env.SetInstanceData(constructor); +#endif + + exports.Set("Database", t); + return exports; } void Database::Process() { - Nan::HandleScope scope; + auto env = this->Env(); + Napi::HandleScope scope(env); if (!open && locked && !queue.empty()) { - EXCEPTION(Nan::New("Database handle is closed").ToLocalChecked(), SQLITE_MISUSE, exception); - Local argv[] = { exception }; + EXCEPTION(Napi::String::New(env, "Database handle is closed"), SQLITE_MISUSE, exception); + Napi::Value argv[] = { exception }; bool called = false; // Call all callbacks with the error object. while (!queue.empty()) { - Call* call = queue.front(); - Local cb = Nan::New(call->baton->callback); - if (!cb.IsEmpty() && cb->IsFunction()) { - TRY_CATCH_CALL(this->handle(), cb, 1, argv); + auto call = std::unique_ptr(queue.front()); + queue.pop(); + auto baton = std::unique_ptr(call->baton); + Napi::Function cb = baton->callback.Value(); + if (IS_FUNCTION(cb)) { + TRY_CATCH_CALL(this->Value(), cb, 1, argv); called = true; } - queue.pop(); - // We don't call the actual callback, so we have to make sure that - // the baton gets destroyed. - delete call->baton; - delete call; } // When we couldn't call a callback function, emit an error on the // Database object. if (!called) { - Local info[] = { Nan::New("error").ToLocalChecked(), exception }; - EMIT_EVENT(handle(), 2, info); + Napi::Value info[] = { Napi::String::New(env, "error"), exception }; + EMIT_EVENT(Value(), 2, info); } return; } while (open && (!locked || pending == 0) && !queue.empty()) { - Call* call = queue.front(); + Call *c = queue.front(); - if (call->exclusive && pending > 0) { + if (c->exclusive && pending > 0) { break; } queue.pop(); + std::unique_ptr call(c); locked = call->exclusive; call->callback(call->baton); - delete call; if (locked) break; } } void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) { - Nan::HandleScope scope; + auto env = this->Env(); + Napi::HandleScope scope(env); if (!open && locked) { - EXCEPTION(Nan::New("Database is closed").ToLocalChecked(), SQLITE_MISUSE, exception); - Local cb = Nan::New(baton->callback); - if (!cb.IsEmpty() && cb->IsFunction()) { - Local argv[] = { exception }; - TRY_CATCH_CALL(handle(), cb, 1, argv); + EXCEPTION(Napi::String::New(env, "Database is closed"), SQLITE_MISUSE, exception); + Napi::Function cb = baton->callback.Value(); + // We don't call the actual callback, so we have to make sure that + // the baton gets destroyed. + delete baton; + if (IS_FUNCTION(cb)) { + Napi::Value argv[] = { exception }; + TRY_CATCH_CALL(Value(), cb, 1, argv); } else { - Local argv[] = { Nan::New("error").ToLocalChecked(), exception }; - EMIT_EVENT(handle(), 2, argv); + Napi::Value argv[] = { Napi::String::New(env, "error"), exception }; + EMIT_EVENT(Value(), 2, argv); } return; } if (!open || ((locked || exclusive || serialize) && pending > 0)) { - queue.push(new Call(callback, baton, exclusive || serialize)); + queue.emplace(new Call(callback, baton, exclusive || serialize)); } else { locked = exclusive; @@ -107,48 +117,46 @@ void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) { } } -NAN_METHOD(Database::New) { - if (!info.IsConstructCall()) { - return Nan::ThrowTypeError("Use the new operator to create new Database objects"); +Database::Database(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info) { + auto env = info.Env(); + + if (info.Length() <= 0 || !info[0].IsString()) { + Napi::TypeError::New(env, "String expected").ThrowAsJavaScriptException(); + return; } + auto filename = info[0].As().Utf8Value(); - REQUIRE_ARGUMENT_STRING(0, filename); - int pos = 1; + unsigned int pos = 1; int mode; - if (info.Length() >= pos && info[pos]->IsInt32()) { - mode = Nan::To(info[pos++]).FromJust(); - } else { + if (info.Length() >= pos && info[pos].IsNumber() && OtherIsInt(info[pos].As())) { + mode = info[pos++].As().Int32Value(); + } + else { mode = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX; } - Local callback; - if (info.Length() >= pos && info[pos]->IsFunction()) { - callback = Local::Cast(info[pos++]); + Napi::Function callback; + if (info.Length() >= pos && info[pos].IsFunction()) { + callback = info[pos++].As(); } - Database* db = new Database(); - db->Wrap(info.This()); - - info.This()->ForceSet(Nan::New("filename").ToLocalChecked(), info[0].As(), ReadOnly); - info.This()->ForceSet(Nan::New("mode").ToLocalChecked(), Nan::New(mode), ReadOnly); + info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("filename", info[0].As(), napi_default)); + info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("mode", Napi::Number::New(env, mode), napi_default)); // Start opening the database. - OpenBaton* baton = new OpenBaton(db, callback, *filename, mode); + auto* baton = new OpenBaton(this, callback, filename.c_str(), mode); Work_BeginOpen(baton); - - info.GetReturnValue().Set(info.This()); } void Database::Work_BeginOpen(Baton* baton) { - int status = uv_queue_work(uv_default_loop(), - &baton->request, Work_Open, (uv_after_work_cb)Work_AfterOpen); - assert(status == 0); + auto env = baton->db->Env(); + CREATE_WORK("sqlite3.Database.Open", Work_Open, Work_AfterOpen); } -void Database::Work_Open(uv_work_t* req) { - OpenBaton* baton = static_cast(req->data); - Database* db = baton->db; +void Database::Work_Open(napi_env e, void* data) { + auto* baton = static_cast(data); + auto* db = baton->db; baton->status = sqlite3_open_v2( baton->filename.c_str(), @@ -168,54 +176,56 @@ void Database::Work_Open(uv_work_t* req) { } } -void Database::Work_AfterOpen(uv_work_t* req) { - Nan::HandleScope scope; +void Database::Work_AfterOpen(napi_env e, napi_status status, void* data) { + std::unique_ptr baton(static_cast(data)); + + auto* db = baton->db; - OpenBaton* baton = static_cast(req->data); - Database* db = baton->db; + auto env = db->Env(); + Napi::HandleScope scope(env); - Local argv[1]; + Napi::Value argv[1]; if (baton->status != SQLITE_OK) { - EXCEPTION(Nan::New(baton->message.c_str()).ToLocalChecked(), baton->status, exception); + EXCEPTION(Napi::String::New(env, baton->message.c_str()), baton->status, exception); argv[0] = exception; } else { db->open = true; - argv[0] = Nan::Null(); + argv[0] = env.Null(); } - Local cb = Nan::New(baton->callback); + Napi::Function cb = baton->callback.Value(); - if (!cb.IsEmpty() && cb->IsFunction()) { - TRY_CATCH_CALL(db->handle(), cb, 1, argv); + if (IS_FUNCTION(cb)) { + TRY_CATCH_CALL(db->Value(), cb, 1, argv); } else if (!db->open) { - Local info[] = { Nan::New("error").ToLocalChecked(), argv[0] }; - EMIT_EVENT(db->handle(), 2, info); + Napi::Value info[] = { Napi::String::New(env, "error"), argv[0] }; + EMIT_EVENT(db->Value(), 2, info); } if (db->open) { - Local info[] = { Nan::New("open").ToLocalChecked() }; - EMIT_EVENT(db->handle(), 1, info); + Napi::Value info[] = { Napi::String::New(env, "open") }; + EMIT_EVENT(db->Value(), 1, info); db->Process(); } - - delete baton; } -NAN_GETTER(Database::OpenGetter) { - Database* db = Nan::ObjectWrap::Unwrap(info.This()); - info.GetReturnValue().Set(db->open); +Napi::Value Database::Open(const Napi::CallbackInfo& info) { + auto env = this->Env(); + auto* db = this; + return Napi::Boolean::New(env, db->open); } -NAN_METHOD(Database::Close) { - Database* db = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Database::Close(const Napi::CallbackInfo& info) { + auto env = info.Env(); + auto* db = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); - Baton* baton = new Baton(db, callback); + auto* baton = new Baton(db, callback); db->Schedule(Work_BeginClose, baton, true); - info.GetReturnValue().Set(info.This()); + return info.This(); } void Database::Work_BeginClose(Baton* baton) { @@ -224,17 +234,17 @@ void Database::Work_BeginClose(Baton* baton) { assert(baton->db->_handle); assert(baton->db->pending == 0); + baton->db->pending++; baton->db->RemoveCallbacks(); baton->db->closing = true; - int status = uv_queue_work(uv_default_loop(), - &baton->request, Work_Close, (uv_after_work_cb)Work_AfterClose); - assert(status == 0); + auto env = baton->db->Env(); + CREATE_WORK("sqlite3.Database.Close", Work_Close, Work_AfterClose); } -void Database::Work_Close(uv_work_t* req) { - Baton* baton = static_cast(req->data); - Database* db = baton->db; +void Database::Work_Close(napi_env e, void* data) { + auto* baton = static_cast(data); + auto* db = baton->db; baton->status = sqlite3_close(db->_handle); @@ -246,145 +256,184 @@ void Database::Work_Close(uv_work_t* req) { } } -void Database::Work_AfterClose(uv_work_t* req) { - Nan::HandleScope scope; +void Database::Work_AfterClose(napi_env e, napi_status status, void* data) { + std::unique_ptr baton(static_cast(data)); + + auto* db = baton->db; - Baton* baton = static_cast(req->data); - Database* db = baton->db; + auto env = db->Env(); + Napi::HandleScope scope(env); + db->pending--; db->closing = false; - Local argv[1]; + Napi::Value argv[1]; if (baton->status != SQLITE_OK) { - EXCEPTION(Nan::New(baton->message.c_str()).ToLocalChecked(), baton->status, exception); + EXCEPTION(Napi::String::New(env, baton->message.c_str()), baton->status, exception); argv[0] = exception; } else { db->open = false; // Leave db->locked to indicate that this db object has reached // the end of its life. - argv[0] = Nan::Null(); + argv[0] = env.Null(); } - Local cb = Nan::New(baton->callback); + Napi::Function cb = baton->callback.Value(); // Fire callbacks. - if (!cb.IsEmpty() && cb->IsFunction()) { - TRY_CATCH_CALL(db->handle(), cb, 1, argv); + if (IS_FUNCTION(cb)) { + TRY_CATCH_CALL(db->Value(), cb, 1, argv); } else if (db->open) { - Local info[] = { Nan::New("error").ToLocalChecked(), argv[0] }; - EMIT_EVENT(db->handle(), 2, info); + Napi::Value info[] = { Napi::String::New(env, "error"), argv[0] }; + EMIT_EVENT(db->Value(), 2, info); } if (!db->open) { - Local info[] = { Nan::New("close").ToLocalChecked(), argv[0] }; - EMIT_EVENT(db->handle(), 1, info); + Napi::Value info[] = { Napi::String::New(env, "close") }; + EMIT_EVENT(db->Value(), 1, info); db->Process(); } - - delete baton; } -NAN_METHOD(Database::Serialize) { - Database* db = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Database::Serialize(const Napi::CallbackInfo& info) { + auto env = this->Env(); + auto* db = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); bool before = db->serialize; db->serialize = true; - if (!callback.IsEmpty() && callback->IsFunction()) { - TRY_CATCH_CALL(info.This(), callback, 0, NULL); + if (!callback.IsEmpty() && callback.IsFunction()) { + TRY_CATCH_CALL(info.This(), callback, 0, NULL, info.This()); db->serialize = before; } db->Process(); - info.GetReturnValue().Set(info.This()); + return info.This(); } -NAN_METHOD(Database::Parallelize) { - Database* db = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Database::Parallelize(const Napi::CallbackInfo& info) { + auto env = this->Env(); + auto* db = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); - bool before = db->serialize; + auto before = db->serialize; db->serialize = false; - if (!callback.IsEmpty() && callback->IsFunction()) { - TRY_CATCH_CALL(info.This(), callback, 0, NULL); + if (!callback.IsEmpty() && callback.IsFunction()) { + TRY_CATCH_CALL(info.This(), callback, 0, NULL, info.This()); db->serialize = before; } db->Process(); - info.GetReturnValue().Set(info.This()); + return info.This(); } -NAN_METHOD(Database::Configure) { - Database* db = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Database::Configure(const Napi::CallbackInfo& info) { + auto env = this->Env(); + auto* db = this; REQUIRE_ARGUMENTS(2); - if (Nan::Equals(info[0], Nan::New("trace").ToLocalChecked()).FromJust()) { - Local handle; - Baton* baton = new Baton(db, handle); + Napi::Function handle; + if (info[0].StrictEquals( Napi::String::New(env, "trace"))) { + auto* baton = new Baton(db, handle); db->Schedule(RegisterTraceCallback, baton); } - else if (Nan::Equals(info[0], Nan::New("profile").ToLocalChecked()).FromJust()) { - Local handle; - Baton* baton = new Baton(db, handle); + else if (info[0].StrictEquals( Napi::String::New(env, "profile"))) { + auto* baton = new Baton(db, handle); db->Schedule(RegisterProfileCallback, baton); } - else if (Nan::Equals(info[0], Nan::New("busyTimeout").ToLocalChecked()).FromJust()) { - if (!info[1]->IsInt32()) { - return Nan::ThrowTypeError("Value must be an integer"); + else if (info[0].StrictEquals( Napi::String::New(env, "busyTimeout"))) { + if (!info[1].IsNumber()) { + Napi::TypeError::New(env, "Value must be an integer").ThrowAsJavaScriptException(); + return env.Null(); } - Local handle; - Baton* baton = new Baton(db, handle); - baton->status = Nan::To(info[1]).FromJust(); + auto* baton = new Baton(db, handle); + baton->status = info[1].As().Int32Value(); db->Schedule(SetBusyTimeout, baton); } + else if (info[0].StrictEquals( Napi::String::New(env, "limit"))) { + REQUIRE_ARGUMENTS(3); + if (!info[1].IsNumber()) { + Napi::TypeError::New(env, "limit id must be an integer").ThrowAsJavaScriptException(); + return env.Null(); + } + if (!info[2].IsNumber()) { + Napi::TypeError::New(env, "limit value must be an integer").ThrowAsJavaScriptException(); + return env.Null(); + } + int id = info[1].As().Int32Value(); + int value = info[2].As().Int32Value(); + Baton* baton = new LimitBaton(db, handle, id, value); + db->Schedule(SetLimit, baton); + } + else if (info[0].StrictEquals(Napi::String::New(env, "change"))) { + auto* baton = new Baton(db, handle); + db->Schedule(RegisterUpdateCallback, baton); + } else { - return Nan::ThrowError(Exception::Error(String::Concat( - Nan::To(info[0]).ToLocalChecked(), - Nan::New(" is not a valid configuration option").ToLocalChecked() - ))); + Napi::TypeError::New(env, (StringConcat( +#if V8_MAJOR_VERSION > 6 + info.GetIsolate(), +#endif + info[0].As(), + Napi::String::New(env, " is not a valid configuration option") + )).Utf8Value().c_str()).ThrowAsJavaScriptException(); + return env.Null(); } db->Process(); - info.GetReturnValue().Set(info.This()); + return info.This(); } -NAN_METHOD(Database::Interrupt) { - Database* db = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Database::Interrupt(const Napi::CallbackInfo& info) { + auto env = this->Env(); + auto* db = this; if (!db->open) { - return Nan::ThrowError("Database is not open"); + Napi::Error::New(env, "Database is not open").ThrowAsJavaScriptException(); + return env.Null(); } if (db->closing) { - return Nan::ThrowError("Database is closing"); + Napi::Error::New(env, "Database is closing").ThrowAsJavaScriptException(); + return env.Null(); } sqlite3_interrupt(db->_handle); - info.GetReturnValue().Set(info.This()); + return info.This(); } -void Database::SetBusyTimeout(Baton* baton) { +void Database::SetBusyTimeout(Baton* b) { + auto baton = std::unique_ptr(b); + assert(baton->db->open); assert(baton->db->_handle); // Abuse the status field for passing the timeout. sqlite3_busy_timeout(baton->db->_handle, baton->status); +} + +void Database::SetLimit(Baton* b) { + std::unique_ptr baton(static_cast(b)); - delete baton; + assert(baton->db->open); + assert(baton->db->_handle); + + sqlite3_limit(baton->db->_handle, baton->id, baton->value); } -void Database::RegisterTraceCallback(Baton* baton) { +void Database::RegisterTraceCallback(Baton* b) { + auto baton = std::unique_ptr(b); assert(baton->db->open); assert(baton->db->_handle); - Database* db = baton->db; + auto* db = baton->db; if (db->debug_trace == NULL) { // Add it. @@ -397,8 +446,6 @@ void Database::RegisterTraceCallback(Baton* baton) { db->debug_trace->finish(); db->debug_trace = NULL; } - - delete baton; } void Database::TraceCallback(void* db, const char* sql) { @@ -407,22 +454,24 @@ void Database::TraceCallback(void* db, const char* sql) { static_cast(db)->debug_trace->send(new std::string(sql)); } -void Database::TraceCallback(Database* db, std::string* sql) { +void Database::TraceCallback(Database* db, std::string* s) { + std::unique_ptr sql(s); // Note: This function is called in the main V8 thread. - Nan::HandleScope scope; + auto env = db->Env(); + Napi::HandleScope scope(env); - Local argv[] = { - Nan::New("trace").ToLocalChecked(), - Nan::New(sql->c_str()).ToLocalChecked() + Napi::Value argv[] = { + Napi::String::New(env, "trace"), + Napi::String::New(env, sql->c_str()) }; - EMIT_EVENT(db->handle(), 2, argv); - delete sql; + EMIT_EVENT(db->Value(), 2, argv); } -void Database::RegisterProfileCallback(Baton* baton) { +void Database::RegisterProfileCallback(Baton* b) { + auto baton = std::unique_ptr(b); assert(baton->db->open); assert(baton->db->_handle); - Database* db = baton->db; + auto* db = baton->db; if (db->debug_profile == NULL) { // Add it. @@ -435,35 +484,35 @@ void Database::RegisterProfileCallback(Baton* baton) { db->debug_profile->finish(); db->debug_profile = NULL; } - - delete baton; } void Database::ProfileCallback(void* db, const char* sql, sqlite3_uint64 nsecs) { // Note: This function is called in the thread pool. // Note: Some queries, such as "EXPLAIN" queries, are not sent through this. - ProfileInfo* info = new ProfileInfo(); + auto* info = new ProfileInfo(); info->sql = std::string(sql); info->nsecs = nsecs; static_cast(db)->debug_profile->send(info); } -void Database::ProfileCallback(Database *db, ProfileInfo* info) { - Nan::HandleScope scope; +void Database::ProfileCallback(Database *db, ProfileInfo* i) { + auto info = std::unique_ptr(i); + auto env = db->Env(); + Napi::HandleScope scope(env); - Local argv[] = { - Nan::New("profile").ToLocalChecked(), - Nan::New(info->sql.c_str()).ToLocalChecked(), - Nan::New((double)info->nsecs / 1000000.0) + Napi::Value argv[] = { + Napi::String::New(env, "profile"), + Napi::String::New(env, info->sql.c_str()), + Napi::Number::New(env, (double)info->nsecs / 1000000.0) }; - EMIT_EVENT(db->handle(), 3, argv); - delete info; + EMIT_EVENT(db->Value(), 3, argv); } -void Database::RegisterUpdateCallback(Baton* baton) { +void Database::RegisterUpdateCallback(Baton* b) { + auto baton = std::unique_ptr(b); assert(baton->db->open); assert(baton->db->_handle); - Database* db = baton->db; + auto* db = baton->db; if (db->update_event == NULL) { // Add it. @@ -476,15 +525,13 @@ void Database::RegisterUpdateCallback(Baton* baton) { db->update_event->finish(); db->update_event = NULL; } - - delete baton; } void Database::UpdateCallback(void* db, int type, const char* database, const char* table, sqlite3_int64 rowid) { // Note: This function is called in the thread pool. // Note: Some queries, such as "EXPLAIN" queries, are not sent through this. - UpdateInfo* info = new UpdateInfo(); + auto* info = new UpdateInfo(); info->type = type; info->database = std::string(database); info->table = std::string(table); @@ -492,29 +539,32 @@ void Database::UpdateCallback(void* db, int type, const char* database, static_cast(db)->update_event->send(info); } -void Database::UpdateCallback(Database *db, UpdateInfo* info) { - Nan::HandleScope scope; +void Database::UpdateCallback(Database *db, UpdateInfo* i) { + auto info = std::unique_ptr(i); + auto env = db->Env(); + Napi::HandleScope scope(env); - Local argv[] = { - Nan::New(sqlite_authorizer_string(info->type)).ToLocalChecked(), - Nan::New(info->database.c_str()).ToLocalChecked(), - Nan::New(info->table.c_str()).ToLocalChecked(), - Nan::New(info->rowid), + Napi::Value argv[] = { + Napi::String::New(env, "change"), + Napi::String::New(env, sqlite_authorizer_string(info->type)), + Napi::String::New(env, info->database.c_str()), + Napi::String::New(env, info->table.c_str()), + Napi::Number::New(env, info->rowid), }; - EMIT_EVENT(db->handle(), 4, argv); - delete info; + EMIT_EVENT(db->Value(), 5, argv); } -NAN_METHOD(Database::Exec) { - Database* db = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Database::Exec(const Napi::CallbackInfo& info) { + auto env = this->Env(); + auto* db = this; REQUIRE_ARGUMENT_STRING(0, sql); OPTIONAL_ARGUMENT_FUNCTION(1, callback); - Baton* baton = new ExecBaton(db, callback, *sql); + Baton* baton = new ExecBaton(db, callback, sql.c_str()); db->Schedule(Work_BeginExec, baton, true); - info.GetReturnValue().Set(info.This()); + return info.This(); } void Database::Work_BeginExec(Baton* baton) { @@ -522,13 +572,14 @@ void Database::Work_BeginExec(Baton* baton) { assert(baton->db->open); assert(baton->db->_handle); assert(baton->db->pending == 0); - int status = uv_queue_work(uv_default_loop(), - &baton->request, Work_Exec, (uv_after_work_cb)Work_AfterExec); - assert(status == 0); + baton->db->pending++; + + auto env = baton->db->Env(); + CREATE_WORK("sqlite3.Database.Exec", Work_Exec, Work_AfterExec); } -void Database::Work_Exec(uv_work_t* req) { - ExecBaton* baton = static_cast(req->data); +void Database::Work_Exec(napi_env e, void* data) { + auto* baton = static_cast(data); char* message = NULL; baton->status = sqlite3_exec( @@ -545,76 +596,80 @@ void Database::Work_Exec(uv_work_t* req) { } } -void Database::Work_AfterExec(uv_work_t* req) { - Nan::HandleScope scope; +void Database::Work_AfterExec(napi_env e, napi_status status, void* data) { + std::unique_ptr baton(static_cast(data)); + + auto* db = baton->db; + db->pending--; - ExecBaton* baton = static_cast(req->data); - Database* db = baton->db; + auto env = db->Env(); + Napi::HandleScope scope(env); - Local cb = Nan::New(baton->callback); + Napi::Function cb = baton->callback.Value(); if (baton->status != SQLITE_OK) { - EXCEPTION(Nan::New(baton->message.c_str()).ToLocalChecked(), baton->status, exception); + EXCEPTION(Napi::String::New(env, baton->message.c_str()), baton->status, exception); - if (!cb.IsEmpty() && cb->IsFunction()) { - Local argv[] = { exception }; - TRY_CATCH_CALL(db->handle(), cb, 1, argv); + if (IS_FUNCTION(cb)) { + Napi::Value argv[] = { exception }; + TRY_CATCH_CALL(db->Value(), cb, 1, argv); } else { - Local info[] = { Nan::New("error").ToLocalChecked(), exception }; - EMIT_EVENT(db->handle(), 2, info); + Napi::Value info[] = { Napi::String::New(env, "error"), exception }; + EMIT_EVENT(db->Value(), 2, info); } } - else if (!cb.IsEmpty() && cb->IsFunction()) { - Local argv[] = { Nan::Null() }; - TRY_CATCH_CALL(db->handle(), cb, 1, argv); + else if (IS_FUNCTION(cb)) { + Napi::Value argv[] = { env.Null() }; + TRY_CATCH_CALL(db->Value(), cb, 1, argv); } db->Process(); - - delete baton; } -NAN_METHOD(Database::Wait) { - Database* db = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Database::Wait(const Napi::CallbackInfo& info) { + auto env = info.Env(); + auto* db = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); - Baton* baton = new Baton(db, callback); + auto* baton = new Baton(db, callback); db->Schedule(Work_Wait, baton, true); - info.GetReturnValue().Set(info.This()); + return info.This(); } -void Database::Work_Wait(Baton* baton) { - Nan::HandleScope scope; +void Database::Work_Wait(Baton* b) { + auto baton = std::unique_ptr(b); + + auto env = baton->db->Env(); + Napi::HandleScope scope(env); assert(baton->db->locked); assert(baton->db->open); assert(baton->db->_handle); assert(baton->db->pending == 0); - Local cb = Nan::New(baton->callback); - if (!cb.IsEmpty() && cb->IsFunction()) { - Local argv[] = { Nan::Null() }; - TRY_CATCH_CALL(baton->db->handle(), cb, 1, argv); + Napi::Function cb = baton->callback.Value(); + if (IS_FUNCTION(cb)) { + Napi::Value argv[] = { env.Null() }; + TRY_CATCH_CALL(baton->db->Value(), cb, 1, argv); } baton->db->Process(); - - delete baton; } -NAN_METHOD(Database::LoadExtension) { - Database* db = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Database::LoadExtension(const Napi::CallbackInfo& info) { + auto env = this->Env(); + auto* db = this; REQUIRE_ARGUMENT_STRING(0, filename); OPTIONAL_ARGUMENT_FUNCTION(1, callback); - Baton* baton = new LoadExtensionBaton(db, callback, *filename); + Baton* baton = new LoadExtensionBaton(db, callback, filename.c_str()); db->Schedule(Work_BeginLoadExtension, baton, true); - info.GetReturnValue().Set(info.This()); + return info.This(); } void Database::Work_BeginLoadExtension(Baton* baton) { @@ -622,13 +677,14 @@ void Database::Work_BeginLoadExtension(Baton* baton) { assert(baton->db->open); assert(baton->db->_handle); assert(baton->db->pending == 0); - int status = uv_queue_work(uv_default_loop(), - &baton->request, Work_LoadExtension, reinterpret_cast(Work_AfterLoadExtension)); - assert(status == 0); + baton->db->pending++; + + auto env = baton->db->Env(); + CREATE_WORK("sqlite3.Database.LoadExtension", Work_LoadExtension, Work_AfterLoadExtension); } -void Database::Work_LoadExtension(uv_work_t* req) { - LoadExtensionBaton* baton = static_cast(req->data); +void Database::Work_LoadExtension(napi_env e, void* data) { + auto* baton = static_cast(data); sqlite3_enable_load_extension(baton->db->_handle, 1); @@ -648,33 +704,35 @@ void Database::Work_LoadExtension(uv_work_t* req) { } } -void Database::Work_AfterLoadExtension(uv_work_t* req) { - Nan::HandleScope scope; +void Database::Work_AfterLoadExtension(napi_env e, napi_status status, void* data) { + std::unique_ptr baton(static_cast(data)); + + auto* db = baton->db; + db->pending--; + + auto env = db->Env(); + Napi::HandleScope scope(env); - LoadExtensionBaton* baton = static_cast(req->data); - Database* db = baton->db; - Local cb = Nan::New(baton->callback); + Napi::Function cb = baton->callback.Value(); if (baton->status != SQLITE_OK) { - EXCEPTION(Nan::New(baton->message.c_str()).ToLocalChecked(), baton->status, exception); + EXCEPTION(Napi::String::New(env, baton->message.c_str()), baton->status, exception); - if (!cb.IsEmpty() && cb->IsFunction()) { - Local argv[] = { exception }; - TRY_CATCH_CALL(db->handle(), cb, 1, argv); + if (IS_FUNCTION(cb)) { + Napi::Value argv[] = { exception }; + TRY_CATCH_CALL(db->Value(), cb, 1, argv); } else { - Local info[] = { Nan::New("error").ToLocalChecked(), exception }; - EMIT_EVENT(db->handle(), 2, info); + Napi::Value info[] = { Napi::String::New(env, "error"), exception }; + EMIT_EVENT(db->Value(), 2, info); } } - else if (!cb.IsEmpty() && cb->IsFunction()) { - Local argv[] = { Nan::Null() }; - TRY_CATCH_CALL(db->handle(), cb, 1, argv); + else if (IS_FUNCTION(cb)) { + Napi::Value argv[] = { env.Null() }; + TRY_CATCH_CALL(db->Value(), cb, 1, argv); } db->Process(); - - delete baton; } void Database::RemoveCallbacks() { @@ -686,4 +744,8 @@ void Database::RemoveCallbacks() { debug_profile->finish(); debug_profile = NULL; } + if (update_event) { + update_event->finish(); + update_event = NULL; + } } diff --git a/src/database.h b/src/database.h index c5455abe3..8ffd300d2 100644 --- a/src/database.h +++ b/src/database.h @@ -3,47 +3,59 @@ #define NODE_SQLITE3_SRC_DATABASE_H +#include #include #include #include -#include +#include #include "async.h" -using namespace v8; +using namespace Napi; namespace node_sqlite3 { class Database; -class Database : public Nan::ObjectWrap { +class Database : public Napi::ObjectWrap { public: - static Nan::Persistent constructor_template; - static NAN_MODULE_INIT(Init); - - static inline bool HasInstance(Local val) { - Nan::HandleScope scope; - if (!val->IsObject()) return false; - Local obj = val.As(); - return Nan::New(constructor_template)->HasInstance(obj); +#if NAPI_VERSION < 6 + static Napi::FunctionReference constructor; +#endif + static Napi::Object Init(Napi::Env env, Napi::Object exports); + + static inline bool HasInstance(Napi::Value val) { + auto env = val.Env(); + Napi::HandleScope scope(env); + if (!val.IsObject()) return false; + auto obj = val.As(); +#if NAPI_VERSION < 6 + return obj.InstanceOf(constructor.Value()); +#else + auto constructor = + env.GetInstanceData(); + return obj.InstanceOf(constructor->Value()); +#endif } struct Baton { - uv_work_t request; + napi_async_work request = NULL; Database* db; - Nan::Persistent callback; + Napi::FunctionReference callback; int status; std::string message; - Baton(Database* db_, Local cb_) : + Baton(Database* db_, Napi::Function cb_) : db(db_), status(SQLITE_OK) { db->Ref(); - request.data = this; - callback.Reset(cb_); + if (!cb_.IsUndefined() && cb_.IsFunction()) { + callback.Reset(cb_, 1); + } } virtual ~Baton() { + if (request) napi_delete_async_work(db->Env(), request); db->Unref(); callback.Reset(); } @@ -52,20 +64,31 @@ class Database : public Nan::ObjectWrap { struct OpenBaton : Baton { std::string filename; int mode; - OpenBaton(Database* db_, Local cb_, const char* filename_, int mode_) : + OpenBaton(Database* db_, Napi::Function cb_, const char* filename_, int mode_) : Baton(db_, cb_), filename(filename_), mode(mode_) {} + virtual ~OpenBaton() override = default; }; struct ExecBaton : Baton { std::string sql; - ExecBaton(Database* db_, Local cb_, const char* sql_) : + ExecBaton(Database* db_, Napi::Function cb_, const char* sql_) : Baton(db_, cb_), sql(sql_) {} + virtual ~ExecBaton() override = default; }; struct LoadExtensionBaton : Baton { std::string filename; - LoadExtensionBaton(Database* db_, Local cb_, const char* filename_) : + LoadExtensionBaton(Database* db_, Napi::Function cb_, const char* filename_) : Baton(db_, cb_), filename(filename_) {} + virtual ~LoadExtensionBaton() override = default; + }; + + struct LimitBaton : Baton { + int id; + int value; + LimitBaton(Database* db_, Napi::Function cb_, int id_, int value_) : + Baton(db_, cb_), id(id_), value(value_) {} + virtual ~LimitBaton() override = default; }; typedef void (*Work_Callback)(Baton* baton); @@ -98,19 +121,9 @@ class Database : public Nan::ObjectWrap { typedef Async AsyncUpdate; friend class Statement; + friend class Backup; -protected: - Database() : Nan::ObjectWrap(), - _handle(NULL), - open(false), - closing(false), - locked(false), - pending(0), - serialize(false), - debug_trace(NULL), - debug_profile(NULL), - update_event(NULL) { - } + Database(const Napi::CallbackInfo& info); ~Database() { RemoveCallbacks(); @@ -119,42 +132,25 @@ class Database : public Nan::ObjectWrap { open = false; } - static NAN_METHOD(New); - static void Work_BeginOpen(Baton* baton); - static void Work_Open(uv_work_t* req); - static void Work_AfterOpen(uv_work_t* req); - - static NAN_GETTER(OpenGetter); +protected: + WORK_DEFINITION(Open); + WORK_DEFINITION(Exec); + WORK_DEFINITION(Close); + WORK_DEFINITION(LoadExtension); void Schedule(Work_Callback callback, Baton* baton, bool exclusive = false); void Process(); - static NAN_METHOD(Exec); - static void Work_BeginExec(Baton* baton); - static void Work_Exec(uv_work_t* req); - static void Work_AfterExec(uv_work_t* req); - - static NAN_METHOD(Wait); + Napi::Value Wait(const Napi::CallbackInfo& info); static void Work_Wait(Baton* baton); - static NAN_METHOD(Close); - static void Work_BeginClose(Baton* baton); - static void Work_Close(uv_work_t* req); - static void Work_AfterClose(uv_work_t* req); - - static NAN_METHOD(LoadExtension); - static void Work_BeginLoadExtension(Baton* baton); - static void Work_LoadExtension(uv_work_t* req); - static void Work_AfterLoadExtension(uv_work_t* req); - - static NAN_METHOD(Serialize); - static NAN_METHOD(Parallelize); - - static NAN_METHOD(Configure); - - static NAN_METHOD(Interrupt); + Napi::Value Serialize(const Napi::CallbackInfo& info); + Napi::Value Parallelize(const Napi::CallbackInfo& info); + Napi::Value Configure(const Napi::CallbackInfo& info); + Napi::Value Interrupt(const Napi::CallbackInfo& info); static void SetBusyTimeout(Baton* baton); + static void SetLimit(Baton* baton); static void RegisterTraceCallback(Baton* baton); static void TraceCallback(void* db, const char* sql); @@ -171,20 +167,20 @@ class Database : public Nan::ObjectWrap { void RemoveCallbacks(); protected: - sqlite3* _handle; + sqlite3* _handle = NULL; - bool open; - bool closing; - bool locked; - unsigned int pending; + bool open = false; + bool closing = false; + bool locked = false; + unsigned int pending = 0; - bool serialize; + bool serialize = false; std::queue queue; - AsyncTrace* debug_trace; - AsyncProfile* debug_profile; - AsyncUpdate* update_event; + AsyncTrace* debug_trace = NULL; + AsyncProfile* debug_profile = NULL; + AsyncUpdate* update_event = NULL; }; } diff --git a/src/gcc-preinclude.h b/src/gcc-preinclude.h index 38c91385c..662d4b5da 100644 --- a/src/gcc-preinclude.h +++ b/src/gcc-preinclude.h @@ -1,6 +1,31 @@ +// http://web.archive.org/web/20140401031018/http://rjpower9000.wordpress.com:80/2012/04/09/fun-with-shared-libraries-version-glibc_2-14-not-found/ -// https://rjpower9000.wordpress.com/2012/04/09/fun-with-shared-libraries-version-glibc_2-14-not-found/ +#if defined(__linux__) -#if defined(__linux__) && defined(__x86_64__) +#define _GNU_SOURCE +#include +#include +#undef _GNU_SOURCE + +#if defined(__GLIBC__) + +#if defined(__x86_64__) __asm__(".symver memcpy,memcpy@GLIBC_2.2.5"); +__asm__(".symver exp,exp@GLIBC_2.2.5"); +__asm__(".symver log,log@GLIBC_2.2.5"); +__asm__(".symver log2,log2@GLIBC_2.2.5"); +__asm__(".symver pow,pow@GLIBC_2.2.5"); +__asm__(".symver fcntl64,fcntl@GLIBC_2.2.5"); +#endif + +#if defined(__aarch64__) || defined(_M_ARM64) +__asm__(".symver memcpy,memcpy@GLIBC_2.17"); +__asm__(".symver exp,exp@GLIBC_2.17"); +__asm__(".symver log,log@GLIBC_2.17"); +__asm__(".symver log2,log2@GLIBC_2.17"); +__asm__(".symver pow,pow@GLIBC_2.17"); +__asm__(".symver fcntl64,fcntl@GLIBC_2.17"); +#endif + +#endif #endif diff --git a/src/macros.h b/src/macros.h index 38399ee86..3bcde83c6 100644 --- a/src/macros.h +++ b/src/macros.h @@ -3,42 +3,74 @@ const char* sqlite_code_string(int code); const char* sqlite_authorizer_string(int type); +#include + +// TODO: better way to work around StringConcat? +#include +inline Napi::String StringConcat(Napi::Value str1, Napi::Value str2) { + return Napi::String::New(str1.Env(), str1.As().Utf8Value() + + str2.As().Utf8Value() ); +} + +// A Napi substitute IsInt32() +inline bool OtherIsInt(Napi::Number source) { + double orig_val = source.DoubleValue(); + double int_val = static_cast(source.Int32Value()); + if (orig_val == int_val) { + return true; + } else { + return false; + } +} +#define IS_FUNCTION(cb) \ + !cb.IsUndefined() && cb.IsFunction() #define REQUIRE_ARGUMENTS(n) \ if (info.Length() < (n)) { \ - return Nan::ThrowTypeError("Expected " #n "arguments"); \ + Napi::TypeError::New(env, "Expected " #n "arguments").ThrowAsJavaScriptException(); \ + return env.Null(); \ } #define REQUIRE_ARGUMENT_EXTERNAL(i, var) \ - if (info.Length() <= (i) || !info[i]->IsExternal()) { \ - return Nan::ThrowTypeError("Argument " #i " invalid"); \ + if (info.Length() <= (i) || !info[i].IsExternal()) { \ + Napi::TypeError::New(env, "Argument " #i " invalid").ThrowAsJavaScriptException(); \ + return env.Null(); \ } \ - Local var = Local::Cast(info[i]); + Napi::External var = info[i].As(); #define REQUIRE_ARGUMENT_FUNCTION(i, var) \ - if (info.Length() <= (i) || !info[i]->IsFunction()) { \ - return Nan::ThrowTypeError("Argument " #i " must be a function"); \ + if (info.Length() <= (i) || !info[i].IsFunction()) { \ + Napi::TypeError::New(env, "Argument " #i " must be a function").ThrowAsJavaScriptException(); \ + return env.Null(); \ } \ - Local var = Local::Cast(info[i]); + Napi::Function var = info[i].As(); #define REQUIRE_ARGUMENT_STRING(i, var) \ - if (info.Length() <= (i) || !info[i]->IsString()) { \ - return Nan::ThrowTypeError("Argument " #i " must be a string"); \ + if (info.Length() <= (i) || !info[i].IsString()) { \ + Napi::TypeError::New(env, "Argument " #i " must be a string").ThrowAsJavaScriptException(); \ + return env.Null(); \ } \ - Nan::Utf8String var(info[i]); + std::string var = info[i].As(); +#define REQUIRE_ARGUMENT_INTEGER(i, var) \ + if (info.Length() <= (i) || !info[i].IsNumber()) { \ + Napi::TypeError::New(env, "Argument " #i " must be an integer").ThrowAsJavaScriptException(); \ + return env.Null(); \ + } \ + int var(info[i].As().Int32Value()); #define OPTIONAL_ARGUMENT_FUNCTION(i, var) \ - Local var; \ - if (info.Length() > i && !info[i]->IsUndefined()) { \ - if (!info[i]->IsFunction()) { \ - return Nan::ThrowTypeError("Argument " #i " must be a function"); \ + Napi::Function var; \ + if (info.Length() > i && !info[i].IsUndefined()) { \ + if (!info[i].IsFunction()) { \ + Napi::TypeError::New(env, "Argument " #i " must be a function").ThrowAsJavaScriptException(); \ + return env.Null(); \ } \ - var = Local::Cast(info[i]); \ + var = info[i].As(); \ } @@ -47,72 +79,76 @@ const char* sqlite_authorizer_string(int type); if (info.Length() <= (i)) { \ var = (default); \ } \ - else if (info[i]->IsInt32()) { \ - var = Nan::To(info[i]).FromJust(); \ + else if (info[i].IsNumber()) { \ + if (OtherIsInt(info[i].As())) { \ + var = info[i].As().Int32Value(); \ + } \ } \ else { \ - return Nan::ThrowTypeError("Argument " #i " must be an integer"); \ + Napi::TypeError::New(env, "Argument " #i " must be an integer").ThrowAsJavaScriptException(); \ + return env.Null(); \ } #define DEFINE_CONSTANT_INTEGER(target, constant, name) \ - Nan::ForceSet(target, \ - Nan::New(#name).ToLocalChecked(), \ - Nan::New(constant), \ - static_cast(ReadOnly | DontDelete) \ - ); + Napi::PropertyDescriptor::Value(#name, Napi::Number::New(env, constant), \ + static_cast(napi_enumerable | napi_configurable)), #define DEFINE_CONSTANT_STRING(target, constant, name) \ - Nan::ForceSet(target, \ - Nan::New(#name).ToLocalChecked(), \ - Nan::New(constant).ToLocalChecked(), \ - static_cast(ReadOnly | DontDelete) \ - ); - - -#define NODE_SET_GETTER(target, name, function) \ - Nan::SetAccessor((target)->InstanceTemplate(), \ - Nan::New(name).ToLocalChecked(), (function)); - -#define GET_STRING(source, name, property) \ - Nan::Utf8String name(Nan::Get(source, \ - Nan::New(prop).ToLocalChecked()).ToLocalChecked()); - -#define GET_INTEGER(source, name, prop) \ - int name = Nan::To(Nan::Get(source, \ - Nan::New(property).ToLocalChecked()).ToLocalChecked()).FromJust(); + Napi::PropertyDescriptor::Value(#name, Napi::String::New(env, constant), \ + static_cast(napi_enumerable | napi_configurable)), #define EXCEPTION(msg, errno, name) \ - Local name = Exception::Error( \ - String::Concat( \ - String::Concat( \ - Nan::New(sqlite_code_string(errno)).ToLocalChecked(), \ - Nan::New(": ").ToLocalChecked() \ + Napi::Value name = Napi::Error::New(env, \ + StringConcat( \ + StringConcat( \ + Napi::String::New(env, sqlite_code_string(errno)), \ + Napi::String::New(env, ": ") \ ), \ (msg) \ - ) \ - ); \ - Local name ##_obj = name.As(); \ - Nan::Set(name ##_obj, Nan::New("errno").ToLocalChecked(), Nan::New(errno));\ - Nan::Set(name ##_obj, Nan::New("code").ToLocalChecked(), \ - Nan::New(sqlite_code_string(errno)).ToLocalChecked()); + ).Utf8Value() \ + ).Value(); \ + Napi::Object name ##_obj = name.As(); \ + (name ##_obj).Set( Napi::String::New(env, "errno"), Napi::Number::New(env, errno)); \ + (name ##_obj).Set( Napi::String::New(env, "code"), \ + Napi::String::New(env, sqlite_code_string(errno))); #define EMIT_EVENT(obj, argc, argv) \ TRY_CATCH_CALL((obj), \ - Nan::Get(obj, \ - Nan::New("emit").ToLocalChecked()).ToLocalChecked().As(),\ + (obj).Get("emit").As(),\ argc, argv \ ); -#define TRY_CATCH_CALL(context, callback, argc, argv) \ - Nan::MakeCallback((context), (callback), (argc), (argv)) +// The Mac OS compiler complains when argv is NULL unless we +// first assign it to a locally defined variable. +#define TRY_CATCH_CALL(context, callback, argc, argv, ...) \ + Napi::Value* passed_argv = argv;\ + std::vector args;\ + if ((argc != 0) && (passed_argv != NULL)) {\ + args.assign(passed_argv, passed_argv + argc);\ + }\ + Napi::Value res = (callback).Call(Napi::Value(context), args); \ + if (res.IsEmpty()) return __VA_ARGS__; #define WORK_DEFINITION(name) \ - static NAN_METHOD(name); \ + Napi::Value name(const Napi::CallbackInfo& info); \ static void Work_Begin##name(Baton* baton); \ - static void Work_##name(uv_work_t* req); \ - static void Work_After##name(uv_work_t* req); + static void Work_##name(napi_env env, void* data); \ + static void Work_After##name(napi_env env, napi_status status, void* data); + +#ifdef DEBUG + #define ASSERT_STATUS() assert(status == 0); +#else + #define ASSERT_STATUS() (void)status; +#endif + +#define CREATE_WORK(name, workerFn, afterFn) \ + int status = napi_create_async_work(env, NULL, Napi::String::New(env, name),\ + workerFn, afterFn, baton, &baton->request); \ + \ + ASSERT_STATUS(); \ + napi_queue_async_work(env, baton->request); #define STATEMENT_BEGIN(type) \ assert(baton); \ @@ -122,33 +158,50 @@ const char* sqlite_authorizer_string(int type); assert(baton->stmt->prepared); \ baton->stmt->locked = true; \ baton->stmt->db->pending++; \ - int status = uv_queue_work(uv_default_loop(), \ - &baton->request, \ - Work_##type, reinterpret_cast(Work_After##type)); \ - assert(status == 0); + auto env = baton->stmt->Env(); \ + CREATE_WORK("sqlite3.Statement."#type, Work_##type, Work_After##type); #define STATEMENT_INIT(type) \ - type* baton = static_cast(req->data); \ + type* baton = static_cast(data); \ Statement* stmt = baton->stmt; +#define STATEMENT_MUTEX(name) \ + if (!stmt->db->_handle) { \ + stmt->status = SQLITE_MISUSE; \ + stmt->message = "Database handle is closed"; \ + return; \ + } \ + sqlite3_mutex* name = sqlite3_db_mutex(stmt->db->_handle); + #define STATEMENT_END() \ assert(stmt->locked); \ assert(stmt->db->pending); \ stmt->locked = false; \ stmt->db->pending--; \ stmt->Process(); \ - stmt->db->Process(); \ - delete baton; - -#define DELETE_FIELD(field) \ - if (field != NULL) { \ - switch ((field)->type) { \ - case SQLITE_INTEGER: delete (Values::Integer*)(field); break; \ - case SQLITE_FLOAT: delete (Values::Float*)(field); break; \ - case SQLITE_TEXT: delete (Values::Text*)(field); break; \ - case SQLITE_BLOB: delete (Values::Blob*)(field); break; \ - case SQLITE_NULL: delete (Values::Null*)(field); break; \ - } \ - } + stmt->db->Process(); -#endif +#define BACKUP_BEGIN(type) \ + assert(baton); \ + assert(baton->backup); \ + assert(!baton->backup->locked); \ + assert(!baton->backup->finished); \ + assert(baton->backup->inited); \ + baton->backup->locked = true; \ + baton->backup->db->pending++; \ + auto env = baton->backup->Env(); \ + CREATE_WORK("sqlite3.Backup."#type, Work_##type, Work_After##type); + +#define BACKUP_INIT(type) \ + type* baton = static_cast(data); \ + Backup* backup = baton->backup; + +#define BACKUP_END() \ + assert(backup->locked); \ + assert(backup->db->pending); \ + backup->locked = false; \ + backup->db->pending--; \ + backup->Process(); \ + backup->db->Process(); + +#endif \ No newline at end of file diff --git a/src/node_sqlite3.cc b/src/node_sqlite3.cc index d8b459a51..6f47a68a8 100644 --- a/src/node_sqlite3.cc +++ b/src/node_sqlite3.cc @@ -7,53 +7,76 @@ #include "macros.h" #include "database.h" #include "statement.h" +#include "backup.h" using namespace node_sqlite3; namespace { -NAN_MODULE_INIT(RegisterModule) { - Nan::HandleScope scope; +Napi::Object RegisterModule(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); - Database::Init(target); - Statement::Init(target); + Database::Init(env, exports); + Statement::Init(env, exports); + Backup::Init(env, exports); - DEFINE_CONSTANT_INTEGER(target, SQLITE_OPEN_READONLY, OPEN_READONLY); - DEFINE_CONSTANT_INTEGER(target, SQLITE_OPEN_READWRITE, OPEN_READWRITE); - DEFINE_CONSTANT_INTEGER(target, SQLITE_OPEN_CREATE, OPEN_CREATE); - DEFINE_CONSTANT_STRING(target, SQLITE_VERSION, VERSION); + exports.DefineProperties({ + DEFINE_CONSTANT_INTEGER(exports, SQLITE_OPEN_READONLY, OPEN_READONLY) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_OPEN_READWRITE, OPEN_READWRITE) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_OPEN_CREATE, OPEN_CREATE) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_OPEN_FULLMUTEX, OPEN_FULLMUTEX) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_OPEN_URI, OPEN_URI) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_OPEN_SHAREDCACHE, OPEN_SHAREDCACHE) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_OPEN_PRIVATECACHE, OPEN_PRIVATECACHE) + DEFINE_CONSTANT_STRING(exports, SQLITE_VERSION, VERSION) #ifdef SQLITE_SOURCE_ID - DEFINE_CONSTANT_STRING(target, SQLITE_SOURCE_ID, SOURCE_ID); + DEFINE_CONSTANT_STRING(exports, SQLITE_SOURCE_ID, SOURCE_ID) #endif - DEFINE_CONSTANT_INTEGER(target, SQLITE_VERSION_NUMBER, VERSION_NUMBER); + DEFINE_CONSTANT_INTEGER(exports, SQLITE_VERSION_NUMBER, VERSION_NUMBER) - DEFINE_CONSTANT_INTEGER(target, SQLITE_OK, OK); - DEFINE_CONSTANT_INTEGER(target, SQLITE_ERROR, ERROR); - DEFINE_CONSTANT_INTEGER(target, SQLITE_INTERNAL, INTERNAL); - DEFINE_CONSTANT_INTEGER(target, SQLITE_PERM, PERM); - DEFINE_CONSTANT_INTEGER(target, SQLITE_ABORT, ABORT); - DEFINE_CONSTANT_INTEGER(target, SQLITE_BUSY, BUSY); - DEFINE_CONSTANT_INTEGER(target, SQLITE_LOCKED, LOCKED); - DEFINE_CONSTANT_INTEGER(target, SQLITE_NOMEM, NOMEM); - DEFINE_CONSTANT_INTEGER(target, SQLITE_READONLY, READONLY); - DEFINE_CONSTANT_INTEGER(target, SQLITE_INTERRUPT, INTERRUPT); - DEFINE_CONSTANT_INTEGER(target, SQLITE_IOERR, IOERR); - DEFINE_CONSTANT_INTEGER(target, SQLITE_CORRUPT, CORRUPT); - DEFINE_CONSTANT_INTEGER(target, SQLITE_NOTFOUND, NOTFOUND); - DEFINE_CONSTANT_INTEGER(target, SQLITE_FULL, FULL); - DEFINE_CONSTANT_INTEGER(target, SQLITE_CANTOPEN, CANTOPEN); - DEFINE_CONSTANT_INTEGER(target, SQLITE_PROTOCOL, PROTOCOL); - DEFINE_CONSTANT_INTEGER(target, SQLITE_EMPTY, EMPTY); - DEFINE_CONSTANT_INTEGER(target, SQLITE_SCHEMA, SCHEMA); - DEFINE_CONSTANT_INTEGER(target, SQLITE_TOOBIG, TOOBIG); - DEFINE_CONSTANT_INTEGER(target, SQLITE_CONSTRAINT, CONSTRAINT); - DEFINE_CONSTANT_INTEGER(target, SQLITE_MISMATCH, MISMATCH); - DEFINE_CONSTANT_INTEGER(target, SQLITE_MISUSE, MISUSE); - DEFINE_CONSTANT_INTEGER(target, SQLITE_NOLFS, NOLFS); - DEFINE_CONSTANT_INTEGER(target, SQLITE_AUTH, AUTH); - DEFINE_CONSTANT_INTEGER(target, SQLITE_FORMAT, FORMAT); - DEFINE_CONSTANT_INTEGER(target, SQLITE_RANGE, RANGE); - DEFINE_CONSTANT_INTEGER(target, SQLITE_NOTADB, NOTADB); + DEFINE_CONSTANT_INTEGER(exports, SQLITE_OK, OK) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_ERROR, ERROR) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_INTERNAL, INTERNAL) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_PERM, PERM) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_ABORT, ABORT) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_BUSY, BUSY) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_LOCKED, LOCKED) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_NOMEM, NOMEM) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_READONLY, READONLY) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_INTERRUPT, INTERRUPT) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_IOERR, IOERR) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_CORRUPT, CORRUPT) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_NOTFOUND, NOTFOUND) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_FULL, FULL) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_CANTOPEN, CANTOPEN) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_PROTOCOL, PROTOCOL) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_EMPTY, EMPTY) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_SCHEMA, SCHEMA) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_TOOBIG, TOOBIG) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_CONSTRAINT, CONSTRAINT) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_MISMATCH, MISMATCH) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_MISUSE, MISUSE) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_NOLFS, NOLFS) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_AUTH, AUTH) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_FORMAT, FORMAT) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_RANGE, RANGE) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_NOTADB, NOTADB) + + DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_LENGTH, LIMIT_LENGTH) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_SQL_LENGTH, LIMIT_SQL_LENGTH) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_COLUMN, LIMIT_COLUMN) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_EXPR_DEPTH, LIMIT_EXPR_DEPTH) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_COMPOUND_SELECT, LIMIT_COMPOUND_SELECT) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_VDBE_OP, LIMIT_VDBE_OP) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_FUNCTION_ARG, LIMIT_FUNCTION_ARG) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_ATTACHED, LIMIT_ATTACHED) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_LIKE_PATTERN_LENGTH, LIMIT_LIKE_PATTERN_LENGTH) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_VARIABLE_NUMBER, LIMIT_VARIABLE_NUMBER) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_TRIGGER_DEPTH, LIMIT_TRIGGER_DEPTH) + DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_WORKER_THREADS, LIMIT_WORKER_THREADS) + }); + + return exports; } } @@ -102,4 +125,4 @@ const char* sqlite_authorizer_string(int type) { } } -NODE_MODULE(node_sqlite3, RegisterModule) +NODE_API_MODULE(node_sqlite3, RegisterModule) diff --git a/src/statement.cc b/src/statement.cc index 0166b72dc..fc49b90f1 100644 --- a/src/statement.cc +++ b/src/statement.cc @@ -1,7 +1,6 @@ -#include -#include -#include -#include +#include +#include +#include #include "macros.h" #include "database.h" @@ -9,27 +8,35 @@ using namespace node_sqlite3; -Nan::Persistent Statement::constructor_template; +Napi::Object Statement::Init(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); -NAN_MODULE_INIT(Statement::Init) { - Nan::HandleScope scope; + // declare napi_default_method here as it is only available in Node v14.12.0+ + auto napi_default_method = static_cast(napi_writable | napi_configurable); - Local t = Nan::New(New); + auto t = DefineClass(env, "Statement", { + InstanceMethod("bind", &Statement::Bind, napi_default_method), + InstanceMethod("get", &Statement::Get, napi_default_method), + InstanceMethod("run", &Statement::Run, napi_default_method), + InstanceMethod("all", &Statement::All, napi_default_method), + InstanceMethod("each", &Statement::Each, napi_default_method), + InstanceMethod("reset", &Statement::Reset, napi_default_method), + InstanceMethod("finalize", &Statement::Finalize_, napi_default_method), + }); - t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(Nan::New("Statement").ToLocalChecked()); + exports.Set("Statement", t); + return exports; +} - Nan::SetPrototypeMethod(t, "bind", Bind); - Nan::SetPrototypeMethod(t, "get", Get); - Nan::SetPrototypeMethod(t, "run", Run); - Nan::SetPrototypeMethod(t, "all", All); - Nan::SetPrototypeMethod(t, "each", Each); - Nan::SetPrototypeMethod(t, "reset", Reset); - Nan::SetPrototypeMethod(t, "finalize", Finalize); +// A Napi InstanceOf for Javascript Objects "Date" and "RegExp" +bool OtherInstanceOf(Napi::Object source, const char* object_type) { + if (strncmp(object_type, "Date", 4) == 0) { + return source.InstanceOf(source.Env().Global().Get("Date").As()); + } else if (strncmp(object_type, "RegExp", 6) == 0) { + return source.InstanceOf(source.Env().Global().Get("RegExp").As()); + } - constructor_template.Reset(t); - Nan::Set(target, Nan::New("Statement").ToLocalChecked(), - Nan::GetFunction(t).ToLocalChecked()); + return false; } void Statement::Process() { @@ -38,21 +45,20 @@ void Statement::Process() { } while (prepared && !locked && !queue.empty()) { - Call* call = queue.front(); + auto call = std::unique_ptr(queue.front()); queue.pop(); call->callback(call->baton); - delete call; } } void Statement::Schedule(Work_Callback callback, Baton* baton) { if (finalized) { - queue.push(new Call(callback, baton)); + queue.emplace(new Call(callback, baton)); CleanQueue(); } else if (!prepared || locked) { - queue.push(new Call(callback, baton)); + queue.emplace(new Call(callback, baton)); } else { callback(baton); @@ -60,72 +66,74 @@ void Statement::Schedule(Work_Callback callback, Baton* baton) { } template void Statement::Error(T* baton) { - Nan::HandleScope scope; - Statement* stmt = baton->stmt; + + auto env = stmt->Env(); + Napi::HandleScope scope(env); + // Fail hard on logic errors. assert(stmt->status != 0); - EXCEPTION(Nan::New(stmt->message.c_str()).ToLocalChecked(), stmt->status, exception); + EXCEPTION(Napi::String::New(env, stmt->message.c_str()), stmt->status, exception); - Local cb = Nan::New(baton->callback); + Napi::Function cb = baton->callback.Value(); - if (!cb.IsEmpty() && cb->IsFunction()) { - Local argv[] = { exception }; - TRY_CATCH_CALL(stmt->handle(), cb, 1, argv); + if (IS_FUNCTION(cb)) { + Napi::Value argv[] = { exception }; + TRY_CATCH_CALL(stmt->Value(), cb, 1, argv); } else { - Local argv[] = { Nan::New("error").ToLocalChecked(), exception }; - EMIT_EVENT(stmt->handle(), 2, argv); + Napi::Value argv[] = { Napi::String::New(env, "error"), exception }; + EMIT_EVENT(stmt->Value(), 2, argv); } } // { Database db, String sql, Array params, Function callback } -NAN_METHOD(Statement::New) { - if (!info.IsConstructCall()) { - return Nan::ThrowTypeError("Use the new operator to create new Statement objects"); - } - +Statement::Statement(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info) { + auto env = info.Env(); int length = info.Length(); if (length <= 0 || !Database::HasInstance(info[0])) { - return Nan::ThrowTypeError("Database object expected"); + Napi::TypeError::New(env, "Database object expected").ThrowAsJavaScriptException(); + return; } - else if (length <= 1 || !info[1]->IsString()) { - return Nan::ThrowTypeError("SQL query expected"); + else if (length <= 1 || !info[1].IsString()) { + Napi::TypeError::New(env, "SQL query expected").ThrowAsJavaScriptException(); + return; } - else if (length > 2 && !info[2]->IsUndefined() && !info[2]->IsFunction()) { - return Nan::ThrowTypeError("Callback expected"); + else if (length > 2 && !info[2].IsUndefined() && !info[2].IsFunction()) { + Napi::TypeError::New(env, "Callback expected").ThrowAsJavaScriptException(); + return; } - Database* db = Nan::ObjectWrap::Unwrap(info[0].As()); - Local sql = Local::Cast(info[1]); + this->db = Napi::ObjectWrap::Unwrap(info[0].As()); + this->db->Ref(); - info.This()->ForceSet(Nan::New("sql").ToLocalChecked(), sql, ReadOnly); + auto sql = info[1].As(); - Statement* stmt = new Statement(db); - stmt->Wrap(info.This()); + info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("sql", sql, napi_default)); - PrepareBaton* baton = new PrepareBaton(db, Local::Cast(info[2]), stmt); - baton->sql = std::string(*Nan::Utf8String(sql)); - db->Schedule(Work_BeginPrepare, baton); - info.GetReturnValue().Set(info.This()); + Statement* stmt = this; + + auto* baton = new PrepareBaton(this->db, info[2].As(), stmt); + baton->sql = std::string(sql.As().Utf8Value().c_str()); + this->db->Schedule(Work_BeginPrepare, baton); } void Statement::Work_BeginPrepare(Database::Baton* baton) { assert(baton->db->open); baton->db->pending++; - int status = uv_queue_work(uv_default_loop(), - &baton->request, Work_Prepare, (uv_after_work_cb)Work_AfterPrepare); - assert(status == 0); + + auto env = baton->db->Env(); + CREATE_WORK("sqlite3.Statement.Prepare", Work_Prepare, Work_AfterPrepare); } -void Statement::Work_Prepare(uv_work_t* req) { +void Statement::Work_Prepare(napi_env e, void* data) { STATEMENT_INIT(PrepareBaton); // In case preparing fails, we use a mutex to make sure we get the associated // error message. - sqlite3_mutex* mtx = sqlite3_db_mutex(baton->db->_handle); + STATEMENT_MUTEX(mtx); sqlite3_mutex_enter(mtx); stmt->status = sqlite3_prepare_v2( @@ -144,99 +152,119 @@ void Statement::Work_Prepare(uv_work_t* req) { sqlite3_mutex_leave(mtx); } -void Statement::Work_AfterPrepare(uv_work_t* req) { - Nan::HandleScope scope; +void Statement::Work_AfterPrepare(napi_env e, napi_status status, void* data) { + std::unique_ptr baton(static_cast(data)); + auto* stmt = baton->stmt; - STATEMENT_INIT(PrepareBaton); + auto env = stmt->Env(); + Napi::HandleScope scope(env); if (stmt->status != SQLITE_OK) { - Error(baton); - stmt->Finalize(); + Error(baton.get()); + stmt->Finalize_(); } else { stmt->prepared = true; - Local cb = Nan::New(baton->callback); - if (!cb.IsEmpty() && cb->IsFunction()) { - Local argv[] = { Nan::Null() }; - TRY_CATCH_CALL(stmt->handle(), cb, 1, argv); + if (!baton->callback.IsEmpty() && baton->callback.Value().IsFunction()) { + Napi::Function cb = baton->callback.Value(); + Napi::Value argv[] = { env.Null() }; + TRY_CATCH_CALL(stmt->Value(), cb, 1, argv); } } STATEMENT_END(); } -template Values::Field* - Statement::BindParameter(const Local source, T pos) { - if (source->IsString() || source->IsRegExp()) { - Nan::Utf8String val(source); - return new Values::Text(pos, val.length(), *val); +template std::unique_ptr + Statement::BindParameter(const Napi::Value source, T pos) { + if (source.IsString()) { + std::string val = source.As().Utf8Value(); + return std::make_unique(pos, val.length(), val.c_str()); } - else if (source->IsInt32()) { - return new Values::Integer(pos, Nan::To(source).FromJust()); + else if (OtherInstanceOf(source.As(), "RegExp")) { + std::string val = source.ToString().Utf8Value(); + return std::make_unique(pos, val.length(), val.c_str()); } - else if (source->IsNumber()) { - return new Values::Float(pos, Nan::To(source).FromJust()); + else if (source.IsNumber()) { + if (OtherIsInt(source.As())) { + return std::make_unique(pos, source.As().Int32Value()); + } else { + return std::make_unique(pos, source.As().DoubleValue()); + } } - else if (source->IsBoolean()) { - return new Values::Integer(pos, Nan::To(source).FromJust() ? 1 : 0); + else if (source.IsBoolean()) { + return std::make_unique(pos, source.As().Value() ? 1 : 0); } - else if (source->IsNull()) { - return new Values::Null(pos); + else if (source.IsNull()) { + return std::make_unique(pos); } - else if (Buffer::HasInstance(source)) { - Local buffer = Nan::To(source).ToLocalChecked(); - return new Values::Blob(pos, Buffer::Length(buffer), Buffer::Data(buffer)); + else if (source.IsBuffer()) { + Napi::Buffer buffer = source.As>(); + return std::make_unique(pos, buffer.Length(), buffer.Data()); } - else if (source->IsDate()) { - return new Values::Float(pos, Nan::To(source).FromJust()); + else if (OtherInstanceOf(source.As(), "Date")) { + return std::make_unique(pos, source.ToNumber().DoubleValue()); + } + else if (source.IsObject()) { + auto napiVal = Napi::String::New(source.Env(), "[object Object]"); + // Check whether toString returned a value that is not undefined. + if(napiVal.Type() == 0) { + return NULL; + } + + std::string val = napiVal.Utf8Value(); + return std::make_unique(pos, val.length(), val.c_str()); } else { return NULL; } } -template T* Statement::Bind(Nan::NAN_METHOD_ARGS_TYPE info, int start, int last) { - Nan::HandleScope scope; +template T* Statement::Bind(const Napi::CallbackInfo& info, int start, int last) { + auto env = info.Env(); + Napi::HandleScope scope(env); if (last < 0) last = info.Length(); - Local callback; - if (last > start && info[last - 1]->IsFunction()) { - callback = Local::Cast(info[last - 1]); + Napi::Function callback; + if (last > start && info[last - 1].IsFunction()) { + callback = info[last - 1].As(); last--; } - T* baton = new T(this, callback); + auto *baton = new T(this, callback); if (start < last) { - if (info[start]->IsArray()) { - Local array = Local::Cast(info[start]); - int length = array->Length(); + if (info[start].IsArray()) { + auto array = info[start].As(); + int length = array.Length(); // Note: bind parameters start with 1. for (int i = 0, pos = 1; i < length; i++, pos++) { - baton->parameters.push_back(BindParameter(Nan::Get(array, i).ToLocalChecked(), pos)); + baton->parameters.emplace_back(BindParameter((array).Get(i), i + 1)); } } - else if (!info[start]->IsObject() || info[start]->IsRegExp() || info[start]->IsDate() || Buffer::HasInstance(info[start])) { + else if (!info[start].IsObject() || OtherInstanceOf(info[start].As(), "RegExp") + || OtherInstanceOf(info[start].As(), "Date") || info[start].IsBuffer()) { // Parameters directly in array. // Note: bind parameters start with 1. for (int i = start, pos = 1; i < last; i++, pos++) { - baton->parameters.push_back(BindParameter(info[i], pos)); + baton->parameters.emplace_back(BindParameter(info[i], pos)); } } - else if (info[start]->IsObject()) { - Local object = Local::Cast(info[start]); - Local array = Nan::GetPropertyNames(object).ToLocalChecked(); - int length = array->Length(); + else if (info[start].IsObject()) { + auto object = info[start].As(); + auto array = object.GetPropertyNames(); + int length = array.Length(); for (int i = 0; i < length; i++) { - Local name = Nan::Get(array, i).ToLocalChecked(); + Napi::Value name = (array).Get(i); + Napi::Number num = name.ToNumber(); - if (name->IsInt32()) { - baton->parameters.push_back( - BindParameter(Nan::Get(object, name).ToLocalChecked(), Nan::To(name).FromJust())); + if (num.Int32Value() == num.DoubleValue()) { + baton->parameters.emplace_back( + BindParameter((object).Get(name), num.Int32Value())); } else { - baton->parameters.push_back(BindParameter(Nan::Get(object, name).ToLocalChecked(), - *Nan::Utf8String(name))); + baton->parameters.emplace_back(BindParameter((object).Get(name), + name.As().Utf8Value().c_str())); } } } @@ -249,72 +277,70 @@ template T* Statement::Bind(Nan::NAN_METHOD_ARGS_TYPE info, int start, } bool Statement::Bind(const Parameters & parameters) { - if (parameters.size() == 0) { + if (parameters.empty()) { return true; } sqlite3_reset(_handle); sqlite3_clear_bindings(_handle); - Parameters::const_iterator it = parameters.begin(); - Parameters::const_iterator end = parameters.end(); - - for (; it < end; ++it) { - Values::Field* field = *it; + for (auto& field : parameters) { + if (field == NULL) + continue; - if (field != NULL) { - int pos; - if (field->index > 0) { - pos = field->index; - } - else { - pos = sqlite3_bind_parameter_index(_handle, field->name.c_str()); - } + unsigned int pos; + if (field->index > 0) { + pos = field->index; + } + else { + pos = sqlite3_bind_parameter_index(_handle, field->name.c_str()); + } - switch (field->type) { - case SQLITE_INTEGER: { - status = sqlite3_bind_int(_handle, pos, - ((Values::Integer*)field)->value); - } break; - case SQLITE_FLOAT: { - status = sqlite3_bind_double(_handle, pos, - ((Values::Float*)field)->value); - } break; - case SQLITE_TEXT: { - status = sqlite3_bind_text(_handle, pos, - ((Values::Text*)field)->value.c_str(), - ((Values::Text*)field)->value.size(), SQLITE_TRANSIENT); - } break; - case SQLITE_BLOB: { - status = sqlite3_bind_blob(_handle, pos, - ((Values::Blob*)field)->value, - ((Values::Blob*)field)->length, SQLITE_TRANSIENT); - } break; - case SQLITE_NULL: { - status = sqlite3_bind_null(_handle, pos); - } break; - } + switch (field->type) { + case SQLITE_INTEGER: { + status = sqlite3_bind_int(_handle, pos, + (static_cast(field.get()))->value); + } break; + case SQLITE_FLOAT: { + status = sqlite3_bind_double(_handle, pos, + (static_cast(field.get()))->value); + } break; + case SQLITE_TEXT: { + status = sqlite3_bind_text(_handle, pos, + (static_cast(field.get()))->value.c_str(), + (static_cast(field.get()))->value.size(), SQLITE_TRANSIENT); + } break; + case SQLITE_BLOB: { + status = sqlite3_bind_blob(_handle, pos, + (static_cast(field.get()))->value, + (static_cast(field.get()))->length, SQLITE_TRANSIENT); + } break; + case SQLITE_NULL: { + status = sqlite3_bind_null(_handle, pos); + } break; + } if (status != SQLITE_OK) { message = std::string(sqlite3_errmsg(db->_handle)); return false; } } - } return true; } -NAN_METHOD(Statement::Bind) { - Statement* stmt = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Statement::Bind(const Napi::CallbackInfo& info) { + auto env = info.Env(); + Statement* stmt = this; - Baton* baton = stmt->Bind(info); + auto baton = stmt->Bind(info); if (baton == NULL) { - return Nan::ThrowTypeError("Data type is not supported"); + Napi::TypeError::New(env, "Data type is not supported").ThrowAsJavaScriptException(); + return env.Null(); } else { stmt->Schedule(Work_BeginBind, baton); - info.GetReturnValue().Set(info.This()); + return info.This(); } } @@ -322,29 +348,31 @@ void Statement::Work_BeginBind(Baton* baton) { STATEMENT_BEGIN(Bind); } -void Statement::Work_Bind(uv_work_t* req) { +void Statement::Work_Bind(napi_env e, void* data) { STATEMENT_INIT(Baton); - sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->_handle); + STATEMENT_MUTEX(mtx); sqlite3_mutex_enter(mtx); stmt->Bind(baton->parameters); sqlite3_mutex_leave(mtx); } -void Statement::Work_AfterBind(uv_work_t* req) { - Nan::HandleScope scope; +void Statement::Work_AfterBind(napi_env e, napi_status status, void* data) { + std::unique_ptr baton(static_cast(data)); + auto* stmt = baton->stmt; - STATEMENT_INIT(Baton); + auto env = stmt->Env(); + Napi::HandleScope scope(env); if (stmt->status != SQLITE_OK) { - Error(baton); + Error(baton.get()); } else { // Fire callbacks. - Local cb = Nan::New(baton->callback); - if (!cb.IsEmpty() && cb->IsFunction()) { - Local argv[] = { Nan::Null() }; - TRY_CATCH_CALL(stmt->handle(), cb, 1, argv); + Napi::Function cb = baton->callback.Value(); + if (IS_FUNCTION(cb)) { + Napi::Value argv[] = { env.Null() }; + TRY_CATCH_CALL(stmt->Value(), cb, 1, argv); } } @@ -353,16 +381,18 @@ void Statement::Work_AfterBind(uv_work_t* req) { -NAN_METHOD(Statement::Get) { - Statement* stmt = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Statement::Get(const Napi::CallbackInfo& info) { + auto env = info.Env(); + Statement* stmt = this; Baton* baton = stmt->Bind(info); if (baton == NULL) { - return Nan::ThrowError("Data type is not supported"); + Napi::Error::New(env, "Data type is not supported").ThrowAsJavaScriptException(); + return env.Null(); } else { stmt->Schedule(Work_BeginGet, baton); - info.GetReturnValue().Set(info.This()); + return info.This(); } } @@ -370,11 +400,11 @@ void Statement::Work_BeginGet(Baton* baton) { STATEMENT_BEGIN(Get); } -void Statement::Work_Get(uv_work_t* req) { +void Statement::Work_Get(napi_env e, void* data) { STATEMENT_INIT(RowBaton); if (stmt->status != SQLITE_DONE || baton->parameters.size()) { - sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->_handle); + STATEMENT_MUTEX(mtx); sqlite3_mutex_enter(mtx); if (stmt->Bind(baton->parameters)) { @@ -394,26 +424,28 @@ void Statement::Work_Get(uv_work_t* req) { } } -void Statement::Work_AfterGet(uv_work_t* req) { - Nan::HandleScope scope; +void Statement::Work_AfterGet(napi_env e, napi_status status, void* data) { + std::unique_ptr baton(static_cast(data)); + auto* stmt = baton->stmt; - STATEMENT_INIT(RowBaton); + auto env = stmt->Env(); + Napi::HandleScope scope(env); if (stmt->status != SQLITE_ROW && stmt->status != SQLITE_DONE) { - Error(baton); + Error(baton.get()); } else { // Fire callbacks. - Local cb = Nan::New(baton->callback); - if (!cb.IsEmpty() && cb->IsFunction()) { + Napi::Function cb = baton->callback.Value(); + if (IS_FUNCTION(cb)) { if (stmt->status == SQLITE_ROW) { // Create the result array from the data we acquired. - Local argv[] = { Nan::Null(), RowToJS(&baton->row) }; - TRY_CATCH_CALL(stmt->handle(), cb, 2, argv); + Napi::Value argv[] = { env.Null(), RowToJS(env, &baton->row) }; + TRY_CATCH_CALL(stmt->Value(), cb, 2, argv); } else { - Local argv[] = { Nan::Null() }; - TRY_CATCH_CALL(stmt->handle(), cb, 1, argv); + Napi::Value argv[] = { env.Null() }; + TRY_CATCH_CALL(stmt->Value(), cb, 1, argv); } } } @@ -421,16 +453,18 @@ void Statement::Work_AfterGet(uv_work_t* req) { STATEMENT_END(); } -NAN_METHOD(Statement::Run) { - Statement* stmt = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Statement::Run(const Napi::CallbackInfo& info) { + auto env = info.Env(); + Statement* stmt = this; Baton* baton = stmt->Bind(info); if (baton == NULL) { - return Nan::ThrowError("Data type is not supported"); + Napi::Error::New(env, "Data type is not supported").ThrowAsJavaScriptException(); + return env.Null(); } else { stmt->Schedule(Work_BeginRun, baton); - info.GetReturnValue().Set(info.This()); + return info.This(); } } @@ -438,10 +472,10 @@ void Statement::Work_BeginRun(Baton* baton) { STATEMENT_BEGIN(Run); } -void Statement::Work_Run(uv_work_t* req) { +void Statement::Work_Run(napi_env e, void* data) { STATEMENT_INIT(RunBaton); - sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->_handle); + STATEMENT_MUTEX(mtx); sqlite3_mutex_enter(mtx); // Make sure that we also reset when there are no parameters. @@ -464,39 +498,43 @@ void Statement::Work_Run(uv_work_t* req) { sqlite3_mutex_leave(mtx); } -void Statement::Work_AfterRun(uv_work_t* req) { - Nan::HandleScope scope; +void Statement::Work_AfterRun(napi_env e, napi_status status, void* data) { + std::unique_ptr baton(static_cast(data)); + auto* stmt = baton->stmt; - STATEMENT_INIT(RunBaton); + auto env = stmt->Env(); + Napi::HandleScope scope(env); if (stmt->status != SQLITE_ROW && stmt->status != SQLITE_DONE) { - Error(baton); + Error(baton.get()); } else { // Fire callbacks. - Local cb = Nan::New(baton->callback); - if (!cb.IsEmpty() && cb->IsFunction()) { - Nan::Set(stmt->handle(), Nan::New("lastID").ToLocalChecked(), Nan::New(baton->inserted_id)); - Nan::Set(stmt->handle(), Nan::New("changes").ToLocalChecked(), Nan::New(baton->changes)); + Napi::Function cb = baton->callback.Value(); + if (IS_FUNCTION(cb)) { + (stmt->Value()).Set(Napi::String::New(env, "lastID"), Napi::Number::New(env, baton->inserted_id)); + (stmt->Value()).Set( Napi::String::New(env, "changes"), Napi::Number::New(env, baton->changes)); - Local argv[] = { Nan::Null() }; - TRY_CATCH_CALL(stmt->handle(), cb, 1, argv); + Napi::Value argv[] = { env.Null() }; + TRY_CATCH_CALL(stmt->Value(), cb, 1, argv); } } STATEMENT_END(); } -NAN_METHOD(Statement::All) { - Statement* stmt = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Statement::All(const Napi::CallbackInfo& info) { + auto env = info.Env(); + Statement* stmt = this; Baton* baton = stmt->Bind(info); if (baton == NULL) { - return Nan::ThrowError("Data type is not supported"); + Napi::Error::New(env, "Data type is not supported").ThrowAsJavaScriptException(); + return env.Null(); } else { stmt->Schedule(Work_BeginAll, baton); - info.GetReturnValue().Set(info.This()); + return info.This(); } } @@ -504,10 +542,10 @@ void Statement::Work_BeginAll(Baton* baton) { STATEMENT_BEGIN(All); } -void Statement::Work_All(uv_work_t* req) { +void Statement::Work_All(napi_env e, void* data) { STATEMENT_INIT(RowsBaton); - sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->_handle); + STATEMENT_MUTEX(mtx); sqlite3_mutex_enter(mtx); // Make sure that we also reset when there are no parameters. @@ -517,9 +555,9 @@ void Statement::Work_All(uv_work_t* req) { if (stmt->Bind(baton->parameters)) { while ((stmt->status = sqlite3_step(stmt->_handle)) == SQLITE_ROW) { - Row* row = new Row(); - GetRow(row, stmt->_handle); - baton->rows.push_back(row); + auto row = std::make_unique(); + GetRow(row.get(), stmt->_handle); + baton->rows.emplace_back(std::move(row)); } if (stmt->status != SQLITE_DONE) { @@ -530,38 +568,39 @@ void Statement::Work_All(uv_work_t* req) { sqlite3_mutex_leave(mtx); } -void Statement::Work_AfterAll(uv_work_t* req) { - Nan::HandleScope scope; +void Statement::Work_AfterAll(napi_env e, napi_status status, void* data) { + std::unique_ptr baton(static_cast(data)); + auto* stmt = baton->stmt; - STATEMENT_INIT(RowsBaton); + auto env = stmt->Env(); + Napi::HandleScope scope(env); if (stmt->status != SQLITE_DONE) { - Error(baton); + Error(baton.get()); } else { // Fire callbacks. - Local cb = Nan::New(baton->callback); - if (!cb.IsEmpty() && cb->IsFunction()) { + Napi::Function cb = baton->callback.Value(); + if (IS_FUNCTION(cb)) { if (baton->rows.size()) { // Create the result array from the data we acquired. - Local result(Nan::New(baton->rows.size())); - Rows::const_iterator it = baton->rows.begin(); - Rows::const_iterator end = baton->rows.end(); + Napi::Array result(Napi::Array::New(env, baton->rows.size())); + auto it = static_cast(baton->rows.begin()); + decltype(it) end = baton->rows.end(); for (int i = 0; it < end; ++it, i++) { - Nan::Set(result, i, RowToJS(*it)); - delete *it; + (result).Set(i, RowToJS(env, it->get())); } - Local argv[] = { Nan::Null(), result }; - TRY_CATCH_CALL(stmt->handle(), cb, 2, argv); + Napi::Value argv[] = { env.Null(), result }; + TRY_CATCH_CALL(stmt->Value(), cb, 2, argv); } else { // There were no result rows. - Local argv[] = { - Nan::Null(), - Nan::New(0) + Napi::Value argv[] = { + env.Null(), + Napi::Array::New(env, 0) }; - TRY_CATCH_CALL(stmt->handle(), cb, 2, argv); + TRY_CATCH_CALL(stmt->Value(), cb, 2, argv); } } } @@ -569,46 +608,46 @@ void Statement::Work_AfterAll(uv_work_t* req) { STATEMENT_END(); } -NAN_METHOD(Statement::Each) { - Statement* stmt = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Statement::Each(const Napi::CallbackInfo& info) { + auto env = info.Env(); + Statement* stmt = this; int last = info.Length(); - Local completed; - if (last >= 2 && info[last - 1]->IsFunction() && info[last - 2]->IsFunction()) { - completed = Local::Cast(info[--last]); + Napi::Function completed; + if (last >= 2 && info[last - 1].IsFunction() && info[last - 2].IsFunction()) { + completed = info[--last].As(); } - EachBaton* baton = stmt->Bind(info, 0, last); + auto baton = stmt->Bind(info, 0, last); if (baton == NULL) { - return Nan::ThrowError("Data type is not supported"); + Napi::Error::New(env, "Data type is not supported").ThrowAsJavaScriptException(); + return env.Null(); } else { - baton->completed.Reset(completed); + baton->completed.Reset(completed, 1); stmt->Schedule(Work_BeginEach, baton); - info.GetReturnValue().Set(info.This()); + return info.This(); } } void Statement::Work_BeginEach(Baton* baton) { // Only create the Async object when we're actually going into // the event loop. This prevents dangling events. - EachBaton* each_baton = static_cast(baton); + auto* each_baton = static_cast(baton); each_baton->async = new Async(each_baton->stmt, reinterpret_cast(AsyncEach)); - each_baton->async->item_cb.Reset(each_baton->callback); - each_baton->async->completed_cb.Reset(each_baton->completed); + each_baton->async->item_cb.Reset(each_baton->callback.Value(), 1); + each_baton->async->completed_cb.Reset(each_baton->completed.Value(), 1); STATEMENT_BEGIN(Each); } -void Statement::Work_Each(uv_work_t* req) { +void Statement::Work_Each(napi_env e, void* data) { STATEMENT_INIT(EachBaton); - Async* async = baton->async; + auto* async = baton->async; - sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->_handle); - - int retrieved = 0; + STATEMENT_MUTEX(mtx); // Make sure that we also reset when there are no parameters. if (!baton->parameters.size()) { @@ -621,11 +660,10 @@ void Statement::Work_Each(uv_work_t* req) { stmt->status = sqlite3_step(stmt->_handle); if (stmt->status == SQLITE_ROW) { sqlite3_mutex_leave(mtx); - Row* row = new Row(); - GetRow(row, stmt->_handle); + auto row = std::make_unique(); + GetRow(row.get(), stmt->_handle); NODE_SQLITE3_MUTEX_LOCK(&async->mutex) - async->data.push_back(row); - retrieved++; + async->data.emplace_back(std::move(row)); NODE_SQLITE3_MUTEX_UNLOCK(&async->mutex) uv_async_send(&async->watcher); @@ -647,14 +685,15 @@ void Statement::Work_Each(uv_work_t* req) { void Statement::CloseCallback(uv_handle_t* handle) { assert(handle != NULL); assert(handle->data != NULL); - Async* async = static_cast(handle->data); + auto* async = static_cast(handle->data); delete async; } -void Statement::AsyncEach(uv_async_t* handle, int status) { - Nan::HandleScope scope; +void Statement::AsyncEach(uv_async_t* handle) { + auto* async = static_cast(handle->data); - Async* async = static_cast(handle->data); + auto env = async->stmt->Env(); + Napi::HandleScope scope(env); while (true) { // Get the contents out of the data cache for us to process in the JS callback. @@ -667,148 +706,151 @@ void Statement::AsyncEach(uv_async_t* handle, int status) { break; } - Local cb = Nan::New(async->item_cb); - if (!cb.IsEmpty() && cb->IsFunction()) { - Local argv[2]; - argv[0] = Nan::Null(); + Napi::Function cb = async->item_cb.Value(); + if (IS_FUNCTION(cb)) { + Napi::Value argv[2]; + argv[0] = env.Null(); - Rows::const_iterator it = rows.begin(); - Rows::const_iterator end = rows.end(); - for (int i = 0; it < end; ++it, i++) { - argv[1] = RowToJS(*it); + for(auto& row : rows) { + argv[1] = RowToJS(env,row.get()); async->retrieved++; - TRY_CATCH_CALL(async->stmt->handle(), cb, 2, argv); - delete *it; + TRY_CATCH_CALL(async->stmt->Value(), cb, 2, argv); } } } - Local cb = Nan::New(async->completed_cb); + Napi::Function cb = async->completed_cb.Value(); if (async->completed) { if (!cb.IsEmpty() && - cb->IsFunction()) { - Local argv[] = { - Nan::Null(), - Nan::New(async->retrieved) + cb.IsFunction()) { + Napi::Value argv[] = { + env.Null(), + Napi::Number::New(env, async->retrieved) }; - TRY_CATCH_CALL(async->stmt->handle(), cb, 2, argv); + TRY_CATCH_CALL(async->stmt->Value(), cb, 2, argv); } uv_close(reinterpret_cast(handle), CloseCallback); } } -void Statement::Work_AfterEach(uv_work_t* req) { - Nan::HandleScope scope; +void Statement::Work_AfterEach(napi_env e, napi_status status, void* data) { + std::unique_ptr baton(static_cast(data)); + auto* stmt = baton->stmt; - STATEMENT_INIT(EachBaton); + auto env = stmt->Env(); + Napi::HandleScope scope(env); if (stmt->status != SQLITE_DONE) { - Error(baton); + Error(baton.get()); } STATEMENT_END(); } -NAN_METHOD(Statement::Reset) { - Statement* stmt = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Statement::Reset(const Napi::CallbackInfo& info) { + auto env = info.Env(); + Statement* stmt = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); - Baton* baton = new Baton(stmt, callback); + auto* baton = new Baton(stmt, callback); stmt->Schedule(Work_BeginReset, baton); - info.GetReturnValue().Set(info.This()); + return info.This(); } void Statement::Work_BeginReset(Baton* baton) { STATEMENT_BEGIN(Reset); } -void Statement::Work_Reset(uv_work_t* req) { +void Statement::Work_Reset(napi_env e, void* data) { STATEMENT_INIT(Baton); sqlite3_reset(stmt->_handle); stmt->status = SQLITE_OK; } -void Statement::Work_AfterReset(uv_work_t* req) { - Nan::HandleScope scope; +void Statement::Work_AfterReset(napi_env e, napi_status status, void* data) { + std::unique_ptr baton(static_cast(data)); + auto* stmt = baton->stmt; - STATEMENT_INIT(Baton); + auto env = stmt->Env(); + Napi::HandleScope scope(env); // Fire callbacks. - Local cb = Nan::New(baton->callback); - if (!cb.IsEmpty() && cb->IsFunction()) { - Local argv[] = { Nan::Null() }; - TRY_CATCH_CALL(stmt->handle(), cb, 1, argv); + Napi::Function cb = baton->callback.Value(); + if (IS_FUNCTION(cb)) { + Napi::Value argv[] = { env.Null() }; + TRY_CATCH_CALL(stmt->Value(), cb, 1, argv); } STATEMENT_END(); } -Local Statement::RowToJS(Row* row) { - Nan::EscapableHandleScope scope; +Napi::Value Statement::RowToJS(Napi::Env env, Row* row) { + Napi::EscapableHandleScope scope(env); - Local result = Nan::New(); + auto result = Napi::Object::New(env); - Row::const_iterator it = row->begin(); - Row::const_iterator end = row->end(); - for (int i = 0; it < end; ++it, i++) { - Values::Field* field = *it; + for (auto& field : *row) { - Local value; + Napi::Value value; switch (field->type) { case SQLITE_INTEGER: { - value = Nan::New(((Values::Integer*)field)->value); + value = Napi::Number::New(env, (static_cast(field.get()))->value); } break; case SQLITE_FLOAT: { - value = Nan::New(((Values::Float*)field)->value); + value = Napi::Number::New(env, (static_cast(field.get()))->value); } break; case SQLITE_TEXT: { - value = Nan::New(((Values::Text*)field)->value.c_str(), ((Values::Text*)field)->value.size()).ToLocalChecked(); + value = Napi::String::New(env, (static_cast(field.get()))->value.c_str(), + (static_cast(field.get()))->value.size()); } break; case SQLITE_BLOB: { - value = Nan::CopyBuffer(((Values::Blob*)field)->value, ((Values::Blob*)field)->length).ToLocalChecked(); + value = Napi::Buffer::Copy(env, (static_cast(field.get()))->value, + (static_cast(field.get()))->length); } break; case SQLITE_NULL: { - value = Nan::Null(); + value = env.Null(); } break; } - Nan::Set(result, Nan::New(field->name.c_str()).ToLocalChecked(), value); - - DELETE_FIELD(field); + result.Set(field->name, value); } return scope.Escape(result); } void Statement::GetRow(Row* row, sqlite3_stmt* stmt) { - int rows = sqlite3_column_count(stmt); + int cols = sqlite3_column_count(stmt); - for (int i = 0; i < rows; i++) { + for (int i = 0; i < cols; i++) { int type = sqlite3_column_type(stmt, i); const char* name = sqlite3_column_name(stmt, i); + if (name == NULL) { + assert(false); + } + switch (type) { case SQLITE_INTEGER: { - row->push_back(new Values::Integer(name, sqlite3_column_int64(stmt, i))); + row->emplace_back(std::make_unique(name, sqlite3_column_int64(stmt, i))); } break; case SQLITE_FLOAT: { - row->push_back(new Values::Float(name, sqlite3_column_double(stmt, i))); + row->emplace_back(std::make_unique(name, sqlite3_column_double(stmt, i))); } break; case SQLITE_TEXT: { const char* text = (const char*)sqlite3_column_text(stmt, i); int length = sqlite3_column_bytes(stmt, i); - row->push_back(new Values::Text(name, length, text)); + row->emplace_back(std::make_unique(name, length, text)); } break; case SQLITE_BLOB: { const void* blob = sqlite3_column_blob(stmt, i); int length = sqlite3_column_bytes(stmt, i); - row->push_back(new Values::Blob(name, length, blob)); + row->emplace_back(std::make_unique(name, length, blob)); } break; case SQLITE_NULL: { - row->push_back(new Values::Null(name)); + row->emplace_back(std::make_unique(name)); } break; default: assert(false); @@ -816,31 +858,32 @@ void Statement::GetRow(Row* row, sqlite3_stmt* stmt) { } } -NAN_METHOD(Statement::Finalize) { - Statement* stmt = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Statement::Finalize_(const Napi::CallbackInfo& info) { + auto env = info.Env(); + Statement* stmt = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); - Baton* baton = new Baton(stmt, callback); - stmt->Schedule(Finalize, baton); + auto *baton = new Baton(stmt, callback); + stmt->Schedule(Finalize_, baton); - info.GetReturnValue().Set(stmt->db->handle()); + return stmt->db->Value(); } -void Statement::Finalize(Baton* baton) { - Nan::HandleScope scope; +void Statement::Finalize_(Baton* b) { + auto baton = std::unique_ptr(b); + auto env = baton->stmt->Env(); + Napi::HandleScope scope(env); - baton->stmt->Finalize(); + baton->stmt->Finalize_(); // Fire callback in case there was one. - Local cb = Nan::New(baton->callback); - if (!cb.IsEmpty() && cb->IsFunction()) { - TRY_CATCH_CALL(baton->stmt->handle(), cb, 0, NULL); + Napi::Function cb = baton->callback.Value(); + if (IS_FUNCTION(cb)) { + TRY_CATCH_CALL(baton->stmt->Value(), cb, 0, NULL); } - - delete baton; } -void Statement::Finalize() { +void Statement::Finalize_() { assert(!finalized); finalized = true; CleanQueue(); @@ -852,50 +895,45 @@ void Statement::Finalize() { } void Statement::CleanQueue() { - Nan::HandleScope scope; + auto env = this->Env(); + Napi::HandleScope scope(env); if (prepared && !queue.empty()) { // This statement has already been prepared and is now finalized. // Fire error for all remaining items in the queue. - EXCEPTION(Nan::New("Statement is already finalized").ToLocalChecked(), SQLITE_MISUSE, exception); - Local argv[] = { exception }; + EXCEPTION(Napi::String::New(env, "Statement is already finalized"), SQLITE_MISUSE, exception); + Napi::Value argv[] = { exception }; bool called = false; // Clear out the queue so that this object can get GC'ed. while (!queue.empty()) { - Call* call = queue.front(); + auto call = std::unique_ptr(queue.front()); queue.pop(); - Local cb = Nan::New(call->baton->callback); + auto baton = std::unique_ptr(call->baton); + Napi::Function cb = baton->callback.Value(); if (prepared && !cb.IsEmpty() && - cb->IsFunction()) { - TRY_CATCH_CALL(handle(), cb, 1, argv); + cb.IsFunction()) { + TRY_CATCH_CALL(Value(), cb, 1, argv); called = true; } - - // We don't call the actual callback, so we have to make sure that - // the baton gets destroyed. - delete call->baton; - delete call; } // When we couldn't call a callback function, emit an error on the // Statement object. if (!called) { - Local info[] = { Nan::New("error").ToLocalChecked(), exception }; - EMIT_EVENT(handle(), 2, info); + Napi::Value info[] = { Napi::String::New(env, "error"), exception }; + EMIT_EVENT(Value(), 2, info); } } else while (!queue.empty()) { // Just delete all items in the queue; we already fired an event when // preparing the statement failed. - Call* call = queue.front(); + auto call = std::unique_ptr(queue.front()); queue.pop(); - // We don't call the actual callback, so we have to make sure that // the baton gets destroyed. delete call->baton; - delete call; } } diff --git a/src/statement.h b/src/statement.h index 90d295b70..c522c0fdf 100644 --- a/src/statement.h +++ b/src/statement.h @@ -1,21 +1,19 @@ #ifndef NODE_SQLITE3_SRC_STATEMENT_H #define NODE_SQLITE3_SRC_STATEMENT_H - -#include "database.h" -#include "threading.h" - #include #include #include #include #include - #include -#include +#include +#include + +#include "database.h" +#include "threading.h" -using namespace v8; -using namespace node; +using namespace Napi; namespace node_sqlite3 { @@ -29,34 +27,40 @@ namespace Values { unsigned short type; unsigned short index; std::string name; + + virtual ~Field() = default; }; struct Integer : Field { template inline Integer(T _name, int64_t val) : Field(_name, SQLITE_INTEGER), value(val) {} int64_t value; + virtual ~Integer() override = default; }; struct Float : Field { template inline Float(T _name, double val) : Field(_name, SQLITE_FLOAT), value(val) {} double value; + virtual ~Float() override = default; }; struct Text : Field { template inline Text(T _name, size_t len, const char* val) : Field(_name, SQLITE_TEXT), value(val, len) {} std::string value; + virtual ~Text() override = default; }; struct Blob : Field { template inline Blob(T _name, size_t len, const void* val) : Field(_name, SQLITE_BLOB), length(len) { - value = (char*)malloc(len); + value = new char[len]; + assert(value != nullptr); memcpy(value, val, len); } - inline ~Blob() { - free(value); + inline virtual ~Blob() override { + delete[] value; } int length; char* value; @@ -65,68 +69,66 @@ namespace Values { typedef Field Null; } -typedef std::vector Row; -typedef std::vector Rows; +typedef std::vector > Row; +typedef std::vector > Rows; typedef Row Parameters; -class Statement : public Nan::ObjectWrap { +class Statement : public Napi::ObjectWrap { public: - static Nan::Persistent constructor_template; - - static NAN_MODULE_INIT(Init); - static NAN_METHOD(New); + static Napi::Object Init(Napi::Env env, Napi::Object exports); + static Napi::Value New(const Napi::CallbackInfo& info); struct Baton { - uv_work_t request; + napi_async_work request = NULL; Statement* stmt; - Nan::Persistent callback; + Napi::FunctionReference callback; Parameters parameters; - Baton(Statement* stmt_, Local cb_) : stmt(stmt_) { + Baton(Statement* stmt_, Napi::Function cb_) : stmt(stmt_) { stmt->Ref(); - request.data = this; - callback.Reset(cb_); + callback.Reset(cb_, 1); } virtual ~Baton() { - for (unsigned int i = 0; i < parameters.size(); i++) { - Values::Field* field = parameters[i]; - DELETE_FIELD(field); - } + parameters.clear(); + if (request) napi_delete_async_work(stmt->Env(), request); stmt->Unref(); callback.Reset(); } }; struct RowBaton : Baton { - RowBaton(Statement* stmt_, Local cb_) : + RowBaton(Statement* stmt_, Napi::Function cb_) : Baton(stmt_, cb_) {} Row row; + virtual ~RowBaton() override = default; }; struct RunBaton : Baton { - RunBaton(Statement* stmt_, Local cb_) : + RunBaton(Statement* stmt_, Napi::Function cb_) : Baton(stmt_, cb_), inserted_id(0), changes(0) {} sqlite3_int64 inserted_id; int changes; + virtual ~RunBaton() override = default; }; struct RowsBaton : Baton { - RowsBaton(Statement* stmt_, Local cb_) : + RowsBaton(Statement* stmt_, Napi::Function cb_) : Baton(stmt_, cb_) {} Rows rows; + virtual ~RowsBaton() override = default; }; struct Async; struct EachBaton : Baton { - Nan::Persistent completed; + Napi::FunctionReference completed; Async* async; // Isn't deleted when the baton is deleted. - EachBaton(Statement* stmt_, Local cb_) : + EachBaton(Statement* stmt_, Napi::Function cb_) : Baton(stmt_, cb_) {} - virtual ~EachBaton() { + virtual ~EachBaton() override { completed.Reset(); } }; @@ -134,16 +136,16 @@ class Statement : public Nan::ObjectWrap { struct PrepareBaton : Database::Baton { Statement* stmt; std::string sql; - PrepareBaton(Database* db_, Local cb_, Statement* stmt_) : + PrepareBaton(Database* db_, Napi::Function cb_, Statement* stmt_) : Baton(db_, cb_), stmt(stmt_) { stmt->Ref(); } - virtual ~PrepareBaton() { + virtual ~PrepareBaton() override { stmt->Unref(); if (!db->IsOpen() && db->IsLocked()) { // The database handle was closed before the statement could be // prepared. - stmt->Finalize(); + stmt->Finalize_(); } } }; @@ -166,15 +168,17 @@ class Statement : public Nan::ObjectWrap { // Store the callbacks here because we don't have // access to the baton in the async callback. - Nan::Persistent item_cb; - Nan::Persistent completed_cb; + Napi::FunctionReference item_cb; + Napi::FunctionReference completed_cb; Async(Statement* st, uv_async_cb async_cb) : stmt(st), completed(false), retrieved(0) { watcher.data = this; NODE_SQLITE3_MUTEX_INIT stmt->Ref(); - uv_async_init(uv_default_loop(), &watcher, async_cb); + uv_loop_t *loop; + napi_get_uv_event_loop(stmt->Env(), &loop); + uv_async_init(loop, &watcher, async_cb); } ~Async() { @@ -185,46 +189,38 @@ class Statement : public Nan::ObjectWrap { } }; - Statement(Database* db_) : Nan::ObjectWrap(), - db(db_), - _handle(NULL), - status(SQLITE_OK), - prepared(false), - locked(true), - finalized(false) { - db->Ref(); - } + Statement(const Napi::CallbackInfo& info); ~Statement() { - if (!finalized) Finalize(); + if (!finalized) Finalize_(); } - WORK_DEFINITION(Bind); - WORK_DEFINITION(Get); - WORK_DEFINITION(Run); - WORK_DEFINITION(All); - WORK_DEFINITION(Each); - WORK_DEFINITION(Reset); + WORK_DEFINITION(Bind) + WORK_DEFINITION(Get) + WORK_DEFINITION(Run) + WORK_DEFINITION(All) + WORK_DEFINITION(Each) + WORK_DEFINITION(Reset) - static NAN_METHOD(Finalize); + Napi::Value Finalize_(const Napi::CallbackInfo& info); protected: static void Work_BeginPrepare(Database::Baton* baton); - static void Work_Prepare(uv_work_t* req); - static void Work_AfterPrepare(uv_work_t* req); + static void Work_Prepare(napi_env env, void* data); + static void Work_AfterPrepare(napi_env env, napi_status status, void* data); - static void AsyncEach(uv_async_t* handle, int status); + static void AsyncEach(uv_async_t* handle); static void CloseCallback(uv_handle_t* handle); - static void Finalize(Baton* baton); - void Finalize(); + static void Finalize_(Baton* baton); + void Finalize_(); - template inline Values::Field* BindParameter(const Local source, T pos); - template T* Bind(Nan::NAN_METHOD_ARGS_TYPE info, int start = 0, int end = -1); + template inline std::unique_ptr BindParameter(const Napi::Value source, T pos); + template T* Bind(const Napi::CallbackInfo& info, int start = 0, int end = -1); bool Bind(const Parameters ¶meters); static void GetRow(Row* row, sqlite3_stmt* stmt); - static Local RowToJS(Row* row); + static Napi::Value RowToJS(Napi::Env env, Row* row); void Schedule(Work_Callback callback, Baton* baton); void Process(); void CleanQueue(); @@ -233,14 +229,14 @@ class Statement : public Nan::ObjectWrap { protected: Database* db; - sqlite3_stmt* _handle; - int status; - std::string message; + sqlite3_stmt* _handle = NULL; + int status = SQLITE_OK; + bool prepared = false; + bool locked = true; + bool finalized = false; - bool prepared; - bool locked; - bool finalized; std::queue queue; + std::string message; }; } diff --git a/src/threading.h b/src/threading.h index fe738a4c0..7c7139bd3 100644 --- a/src/threading.h +++ b/src/threading.h @@ -1,48 +1,10 @@ #ifndef NODE_SQLITE3_SRC_THREADING_H #define NODE_SQLITE3_SRC_THREADING_H - -#ifdef _WIN32 - -#include - - #define NODE_SQLITE3_MUTEX_t HANDLE mutex; - - #define NODE_SQLITE3_MUTEX_INIT mutex = CreateMutex(NULL, FALSE, NULL); - - #define NODE_SQLITE3_MUTEX_LOCK(m) WaitForSingleObject(*m, INFINITE); - - #define NODE_SQLITE3_MUTEX_UNLOCK(m) ReleaseMutex(*m); - - #define NODE_SQLITE3_MUTEX_DESTROY CloseHandle(mutex); - -#elif defined(NODE_SQLITE3_BOOST_THREADING) - -#include - - #define NODE_SQLITE3_MUTEX_t boost::mutex mutex; - - #define NODE_SQLITE3_MUTEX_INIT - - #define NODE_SQLITE3_MUTEX_LOCK(m) (*m).lock(); - - #define NODE_SQLITE3_MUTEX_UNLOCK(m) (*m).unlock(); - - #define NODE_SQLITE3_MUTEX_DESTROY mutex.unlock(); - -#else - - #define NODE_SQLITE3_MUTEX_t pthread_mutex_t mutex; - - #define NODE_SQLITE3_MUTEX_INIT pthread_mutex_init(&mutex,NULL); - - #define NODE_SQLITE3_MUTEX_LOCK(m) pthread_mutex_lock(m); - - #define NODE_SQLITE3_MUTEX_UNLOCK(m) pthread_mutex_unlock(m); - - #define NODE_SQLITE3_MUTEX_DESTROY pthread_mutex_destroy(&mutex); - -#endif - +#define NODE_SQLITE3_MUTEX_t uv_mutex_t mutex; +#define NODE_SQLITE3_MUTEX_INIT uv_mutex_init(&mutex); +#define NODE_SQLITE3_MUTEX_LOCK(m) uv_mutex_lock(m); +#define NODE_SQLITE3_MUTEX_UNLOCK(m) uv_mutex_unlock(m); +#define NODE_SQLITE3_MUTEX_DESTROY uv_mutex_destroy(&mutex); #endif // NODE_SQLITE3_SRC_THREADING_H diff --git a/test/.eslintrc.js b/test/.eslintrc.js new file mode 100644 index 000000000..41371e2b6 --- /dev/null +++ b/test/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + env: { + mocha: true, + }, +}; diff --git a/test/affected.test.js b/test/affected.test.js index f0bf192e6..031dc1b9c 100644 --- a/test/affected.test.js +++ b/test/affected.test.js @@ -11,7 +11,7 @@ describe('query properties', function() { it('should return the correct lastID', function(done) { var stmt = db.prepare("INSERT INTO foo VALUES(?, ?)"); var j = 1; - for (var i = 0; i < 1000; i++) { + for (var i = 0; i < 5000; i++) { stmt.run(i, "demo", function(err) { if (err) throw err; // Relies on SQLite's row numbering to be gapless and starting @@ -25,7 +25,7 @@ describe('query properties', function() { it('should return the correct changes count', function(done) { db.run("UPDATE foo SET id = id + 1 WHERE id % 2 = 0", function(err) { if (err) throw err; - assert.equal(500, this.changes); + assert.equal(2500, this.changes); done(); }); }); diff --git a/test/async_calls.test.js b/test/async_calls.test.js new file mode 100644 index 000000000..9ce29a730 --- /dev/null +++ b/test/async_calls.test.js @@ -0,0 +1,42 @@ +"use strict" + +var sqlite3 = require('..'); +const assert = require("assert"); +const { createHook, executionAsyncId } = require("async_hooks"); + + +describe('async_hooks', function() { + let db; + let dbId; + let asyncHook; + + beforeEach(function() { + db = new sqlite3.Database(':memory:'); + + asyncHook = createHook({ + init(asyncId, type) { + if (dbId == null && type.startsWith("sqlite3.")) { + dbId = asyncId; + } + } + }).enable(); + }); + + it('should support performance measuring with async hooks', function(done) { + db.run("DROP TABLE user", () => { + const cbId = executionAsyncId(); + assert.strictEqual(cbId, dbId); + done(); + }); + }); + + afterEach(function() { + if (asyncHook != null) { + asyncHook.disable(); + } + dbId = null; + if (db != null) { + db.close(); + } + }); +}); \ No newline at end of file diff --git a/test/backup.test.js b/test/backup.test.js new file mode 100644 index 000000000..c05c298f8 --- /dev/null +++ b/test/backup.test.js @@ -0,0 +1,279 @@ +var sqlite3 = require('..'); +var assert = require('assert'); +var fs = require('fs'); +var helper = require('./support/helper'); + +// Check that the number of rows in two tables matches. +function assertRowsMatchDb(db1, table1, db2, table2, done) { + db1.get("SELECT COUNT(*) as count FROM " + table1, function(err, row) { + if (err) throw err; + db2.get("SELECT COUNT(*) as count FROM " + table2, function(err, row2) { + if (err) throw err; + assert.equal(row.count, row2.count); + done(); + }); + }); +} + +// Check that the number of rows in the table "foo" is preserved in a backup. +function assertRowsMatchFile(db, backupName, done) { + var db2 = new sqlite3.Database(backupName, sqlite3.OPEN_READONLY, function(err) { + if (err) throw err; + assertRowsMatchDb(db, 'foo', db2, 'foo', function() { + db2.close(done); + }); + }); +} + +describe('backup', function() { + before(function() { + helper.ensureExists('test/tmp'); + }); + + var db; + beforeEach(function(done) { + helper.deleteFile('test/tmp/backup.db'); + helper.deleteFile('test/tmp/backup2.db'); + db = new sqlite3.Database('test/support/prepare.db', sqlite3.OPEN_READONLY, done); + }); + + afterEach(function(done) { + if (!db) { done(); } + db.close(done); + }); + + it ('output db created once step is called', function(done) { + var backup = db.backup('test/tmp/backup.db', function(err) { + if (err) throw err; + backup.step(1, function(err) { + if (err) throw err; + assert.fileExists('test/tmp/backup.db'); + backup.finish(done); + }); + }); + }); + + it ('copies source fully with step(-1)', function(done) { + var backup = db.backup('test/tmp/backup.db'); + backup.step(-1, function(err) { + if (err) throw err; + assert.fileExists('test/tmp/backup.db'); + backup.finish(function(err) { + if (err) throw err; + assertRowsMatchFile(db, 'test/tmp/backup.db', done); + }); + }); + }); + + it ('backup db not created if finished immediately', function(done) { + var backup = db.backup('test/tmp/backup.db'); + backup.finish(function(err) { + if (err) throw err; + assert.fileDoesNotExist('test/tmp/backup.db'); + done(); + }); + }); + + it ('error closing db if backup not finished', function(done) { + var backup = db.backup('test/tmp/backup.db'); + db.close(function(err) { + db = null; + if (!err) throw new Error('should have an error'); + if (err.errno == sqlite3.BUSY) { + done(); + } + else throw err; + }); + }); + + it ('using the backup after finished is an error', function(done) { + var backup = db.backup('test/tmp/backup.db'); + backup.finish(function(err) { + if (err) throw err; + backup.step(1, function(err) { + if (!err) throw new Error('should have an error'); + if (err.errno == sqlite3.MISUSE && + err.message === 'SQLITE_MISUSE: Backup is already finished') { + done(); + } + else throw err; + }); + }); + }); + + it ('remaining/pageCount are available after call to step', function(done) { + var backup = db.backup('test/tmp/backup.db'); + backup.step(0, function(err) { + if (err) throw err; + assert.equal(typeof this.pageCount, 'number'); + assert.equal(typeof this.remaining, 'number'); + assert.equal(this.remaining, this.pageCount); + var prevRemaining = this.remaining; + var prevPageCount = this.pageCount; + backup.step(1, function(err) { + if (err) throw err; + assert.notEqual(this.remaining, prevRemaining); + assert.equal(this.pageCount, prevPageCount); + backup.finish(done); + }); + }); + }); + + it ('backup works if database is modified half-way through', function(done) { + var backup = db.backup('test/tmp/backup.db'); + backup.step(-1, function(err) { + if (err) throw err; + backup.finish(function(err) { + if (err) throw err; + var db2 = new sqlite3.Database('test/tmp/backup.db', function(err) { + if (err) throw err; + var backup2 = db2.backup('test/tmp/backup2.db'); + backup2.step(1, function(err, completed) { + if (err) throw err; + assert.equal(completed, false); // Page size for the test db + // should not be raised to high. + db2.exec("insert into foo(txt) values('hello')", function(err) { + if (err) throw err; + backup2.step(-1, function(err, completed) { + if (err) throw err; + assert.equal(completed, true); + assertRowsMatchFile(db2, 'test/tmp/backup2.db', function() { + backup2.finish(function(err) { + if (err) throw err; + db2.close(done); + }); + }); + }); + }); + }); + }); + }); + }); + }); + + (sqlite3.VERSION_NUMBER < 3026000 ? it.skip : it) ('can backup from temp to main', function(done) { + db.exec("CREATE TEMP TABLE space (txt TEXT)", function(err) { + if (err) throw err; + db.exec("INSERT INTO space(txt) VALUES('monkey')", function(err) { + if (err) throw err; + var backup = db.backup('test/tmp/backup.db', 'temp', 'main', true, function(err) { + if (err) throw err; + backup.step(-1, function(err) { + if (err) throw err; + backup.finish(function(err) { + if (err) throw err; + var db2 = new sqlite3.Database('test/tmp/backup.db', function(err) { + if (err) throw err; + db2.get("SELECT * FROM space", function(err, row) { + if (err) throw err; + assert.equal(row.txt, 'monkey'); + db2.close(done); + }); + }); + }); + }); + }); + }); + }); + }); + + (sqlite3.VERSION_NUMBER < 3026000 ? it.skip : it) ('can backup from main to temp', function(done) { + var backup = db.backup('test/support/prepare.db', 'main', 'temp', false, function(err) { + if (err) throw err; + backup.step(-1, function(err) { + if (err) throw err; + backup.finish(function(err) { + if (err) throw err; + assertRowsMatchDb(db, 'temp.foo', db, 'main.foo', done); + }); + }); + }); + }); + + it ('cannot backup to a locked db', function(done) { + var db2 = new sqlite3.Database('test/tmp/backup.db', function(err) { + db2.exec("PRAGMA locking_mode = EXCLUSIVE"); + db2.exec("BEGIN EXCLUSIVE", function(err) { + if (err) throw err; + var backup = db.backup('test/tmp/backup.db'); + backup.step(-1, function(stepErr) { + db2.close(function(err) { + if (err) throw err; + if (stepErr.errno == sqlite3.BUSY) { + backup.finish(done); + } + else throw stepErr; + }); + }); + }); + }); + }); + + it ('fuss-free incremental backups work', function(done) { + var backup = db.backup('test/tmp/backup.db'); + var timer; + function makeProgress() { + if (backup.idle) { + backup.step(1); + } + if (backup.completed || backup.failed) { + clearInterval(timer); + assert.equal(backup.completed, true); + assert.equal(backup.failed, false); + done(); + } + } + timer = setInterval(makeProgress, 2); + }); + + it ('setting retryErrors to empty disables automatic finishing', function(done) { + var backup = db.backup('test/tmp/backup.db'); + backup.retryErrors = []; + backup.step(-1, function(err) { + if (err) throw err; + db.close(function(err) { + db = null; + if (!err) throw new Error('should have an error'); + assert.equal(err.errno, sqlite3.BUSY); + done(); + }); + }); + }); + + it ('setting retryErrors enables automatic finishing', function(done) { + var backup = db.backup('test/tmp/backup.db'); + backup.retryErrors = [sqlite3.OK]; + backup.step(-1, function(err) { + if (err) throw err; + db.close(function(err) { + if (err) throw err; + db = null; + done(); + }); + }); + }); + + it ('default retryErrors will retry on a locked/busy db', function(done) { + var db2 = new sqlite3.Database('test/tmp/backup.db', function(err) { + db2.exec("PRAGMA locking_mode = EXCLUSIVE"); + db2.exec("BEGIN EXCLUSIVE", function(err) { + if (err) throw err; + var backup = db.backup('test/tmp/backup.db'); + backup.step(-1, function(stepErr) { + db2.close(function(err) { + if (err) throw err; + assert.equal(stepErr.errno, sqlite3.BUSY); + assert.equal(backup.completed, false); + assert.equal(backup.failed, false); + backup.step(-1, function(err) { + if (err) throw err; + assert.equal(backup.completed, true); + assert.equal(backup.failed, false); + done(); + }); + }); + }); + }); + }); + }); +}); diff --git a/test/constants.test.js b/test/constants.test.js index 126d10141..7e1affdda 100644 --- a/test/constants.test.js +++ b/test/constants.test.js @@ -6,6 +6,10 @@ describe('constants', function() { assert.ok(sqlite3.OPEN_READONLY === 1); assert.ok(sqlite3.OPEN_READWRITE === 2); assert.ok(sqlite3.OPEN_CREATE === 4); + assert.ok(sqlite3.OPEN_URI === 0x00000040); + assert.ok(sqlite3.OPEN_FULLMUTEX === 0x00010000); + assert.ok(sqlite3.OPEN_SHAREDCACHE === 0x00020000); + assert.ok(sqlite3.OPEN_PRIVATECACHE === 0x00040000); }); it('should have the right error flags', function() { diff --git a/test/database_fail.test.js b/test/database_fail.test.js index 35589ece5..8b936769e 100644 --- a/test/database_fail.test.js +++ b/test/database_fail.test.js @@ -10,11 +10,11 @@ describe('error handling', function() { it('throw when calling Database() without new', function() { assert.throws(function() { sqlite3.Database(':memory:'); - }, (/Use the new operator to create new Database objects/)); + }, (/Class constructors cannot be invoked without 'new'/)); assert.throws(function() { sqlite3.Statement(); - }, (/Use the new operator to create new Statement objects/)); + }, (/Class constructors cannot be invoked without 'new'/)); }); it('should error when calling Database#get on a missing table', function(done) { diff --git a/test/each.test.js b/test/each.test.js index 02729c64e..27df32c8c 100644 --- a/test/each.test.js +++ b/test/each.test.js @@ -10,15 +10,16 @@ describe('each', function() { it('retrieve 100,000 rows with Statement#each', function(done) { var total = 100000; var retrieved = 0; + db.each('SELECT id, txt FROM foo LIMIT 0, ?', total, function(err, row) { if (err) throw err; retrieved++; - }); - - db.wait(function() { - assert.equal(retrieved, total, "Only retrieved " + retrieved + " out of " + total + " rows."); - done(); + + if(retrieved === total) { + assert.equal(retrieved, total, "Only retrieved " + retrieved + " out of " + total + " rows."); + done(); + } }); }); diff --git a/test/issue-108.test.js b/test/issue-108.test.js index 2ea69a30c..99343782c 100644 --- a/test/issue-108.test.js +++ b/test/issue-108.test.js @@ -17,8 +17,8 @@ describe('buffer', function() { throw err; }); - var buff = new Buffer(2); - stmt.run('a'); + var buff = Buffer.alloc(2); + stmt.run(buff); stmt.finalize(); }); diff --git a/test/limit.test.js b/test/limit.test.js new file mode 100644 index 000000000..d79f2c8df --- /dev/null +++ b/test/limit.test.js @@ -0,0 +1,28 @@ +var sqlite3 = require('..'); + +describe('limit', function() { + var db; + + before(function(done) { + db = new sqlite3.Database(':memory:', done); + }); + + it('should support applying limits via configure', function(done) { + db.configure('limit', sqlite3.LIMIT_ATTACHED, 0); + db.exec("ATTACH 'test/support/prepare.db' AS zing", function(err) { + if (!err) { + throw new Error('ATTACH should not succeed'); + } + if (err.errno === sqlite3.ERROR && + err.message === 'SQLITE_ERROR: too many attached databases - max 0') { + db.configure('limit', sqlite3.LIMIT_ATTACHED, 1); + db.exec("ATTACH 'test/support/prepare.db' AS zing", function(err) { + if (err) throw err; + db.close(done); + }); + } else { + throw err; + } + }); + }); +}); diff --git a/test/open_close.test.js b/test/open_close.test.js index 649e21789..49d2af791 100644 --- a/test/open_close.test.js +++ b/test/open_close.test.js @@ -30,6 +30,64 @@ describe('open/close', function() { helper.deleteFile('test/tmp/test_create.db'); }); }); + + describe('open and close non-existant shared database', function() { + before(function() { + helper.deleteFile('test/tmp/test_create_shared.db'); + }); + + var db; + it('should open the database', function(done) { + db = new sqlite3.Database('file:./test/tmp/test_create_shared.db', sqlite3.OPEN_URI | sqlite3.OPEN_SHAREDCACHE | sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, done); + }); + + it('should close the database', function(done) { + db.close(done); + }); + + it('should have created the file', function() { + assert.fileExists('test/tmp/test_create_shared.db'); + }); + + after(function() { + helper.deleteFile('test/tmp/test_create_shared.db'); + }); + }); + + + (sqlite3.VERSION_NUMBER < 3008000 ? describe.skip : describe)('open and close shared memory database', function() { + + var db1; + var db2; + + it('should open the first database', function(done) { + db1 = new sqlite3.Database('file:./test/tmp/test_memory.db?mode=memory', sqlite3.OPEN_URI | sqlite3.OPEN_SHAREDCACHE | sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, done); + }); + + it('should open the second database', function(done) { + db2 = new sqlite3.Database('file:./test/tmp/test_memory.db?mode=memory', sqlite3.OPEN_URI | sqlite3.OPEN_SHAREDCACHE | sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, done); + }); + + it('first database should set the user_version', function(done) { + db1.exec('PRAGMA user_version=42', done); + }); + + it('second database should get the user_version', function(done) { + db2.get('PRAGMA user_version', function(err, row) { + if (err) throw err; + assert.equal(row.user_version, 42); + done(); + }); + }); + + it('should close the first database', function(done) { + db1.close(done); + }); + + it('should close the second database', function(done) { + db2.close(done); + }); + }); it('should not be unable to open an inaccessible database', function(done) { // NOTE: test assumes that the user is not allowed to create new files diff --git a/test/other_objects.test.js b/test/other_objects.test.js index 155951791..cc516c490 100644 --- a/test/other_objects.test.js +++ b/test/other_objects.test.js @@ -86,4 +86,29 @@ describe('data types', function() { }); }); }); + + it('should ignore faulty toString', function(done) { + const faulty = { toString: 23 }; + db.run("INSERT INTO txt_table VALUES(?)", faulty, function (err) { + assert.notEqual(err, undefined); + done(); + }); + }); + + it('should ignore faulty toString in array', function(done) { + const faulty = [[{toString: null}], 1]; + db.all('SELECT * FROM txt_table WHERE txt = ? LIMIT ?', faulty, function (err) { + assert.equal(err, null); + done(); + }); + }); + + it('should ignore faulty toString set to function', function(done) { + const faulty = [[{toString: function () {console.log('oh no');}}], 1]; + db.all('SELECT * FROM txt_table WHERE txt = ? LIMIT ?', faulty, function (err) { + assert.equal(err, undefined); + done(); + }); + }); + }); diff --git a/test/patching.test.js b/test/patching.test.js new file mode 100644 index 000000000..3f9f68d59 --- /dev/null +++ b/test/patching.test.js @@ -0,0 +1,184 @@ +var sqlite3 = require('..'); +var assert = require('assert'); + +describe('patching', function() { + describe("Database", function() { + var db; + var originalFunctions = {}; + + before(function() { + originalFunctions.close = sqlite3.Database.prototype.close; + originalFunctions.exec = sqlite3.Database.prototype.exec; + originalFunctions.wait = sqlite3.Database.prototype.wait; + originalFunctions.loadExtension = sqlite3.Database.prototype.loadExtension; + originalFunctions.serialize = sqlite3.Database.prototype.serialize; + originalFunctions.parallelize = sqlite3.Database.prototype.parallelize; + originalFunctions.configure = sqlite3.Database.prototype.configure; + originalFunctions.interrupt = sqlite3.Database.prototype.interrupt; + }); + + it('allow patching native functions', function() { + var myFun = function myFunction() { + return "Success"; + } + + assert.doesNotThrow(() => { + sqlite3.Database.prototype.close = myFun; + }); + assert.doesNotThrow(() => { + sqlite3.Database.prototype.exec = myFun; + }); + assert.doesNotThrow(() => { + sqlite3.Database.prototype.wait = myFun; + }); + assert.doesNotThrow(() => { + sqlite3.Database.prototype.loadExtension = myFun; + }); + assert.doesNotThrow(() => { + sqlite3.Database.prototype.serialize = myFun; + }); + assert.doesNotThrow(() => { + sqlite3.Database.prototype.parallelize = myFun; + }); + assert.doesNotThrow(() => { + sqlite3.Database.prototype.configure = myFun; + }); + assert.doesNotThrow(() => { + sqlite3.Database.prototype.interrupt = myFun; + }); + + db = new sqlite3.Database(':memory:'); + assert.strictEqual(db.close(), "Success"); + assert.strictEqual(db.exec(), "Success"); + assert.strictEqual(db.wait(), "Success"); + assert.strictEqual(db.loadExtension(), "Success"); + assert.strictEqual(db.serialize(), "Success"); + assert.strictEqual(db.parallelize(), "Success"); + assert.strictEqual(db.configure(), "Success"); + assert.strictEqual(db.interrupt(), "Success"); + }); + + after(function() { + if(db != null) { + sqlite3.Database.prototype.close = originalFunctions.close; + sqlite3.Database.prototype.exec = originalFunctions.exec; + sqlite3.Database.prototype.wait = originalFunctions.wait; + sqlite3.Database.prototype.loadExtension = originalFunctions.loadExtension; + sqlite3.Database.prototype.serialize = originalFunctions.serialize; + sqlite3.Database.prototype.parallelize = originalFunctions.parallelize; + sqlite3.Database.prototype.configure = originalFunctions.configure; + sqlite3.Database.prototype.interrupt = originalFunctions.interrupt; + db.close(); + } + }); + }); + + describe('Statement', function() { + var db; + var statement; + var originalFunctions = {}; + + before(function() { + originalFunctions.bind = sqlite3.Statement.prototype.bind; + originalFunctions.get = sqlite3.Statement.prototype.get; + originalFunctions.run = sqlite3.Statement.prototype.run; + originalFunctions.all = sqlite3.Statement.prototype.all; + originalFunctions.each = sqlite3.Statement.prototype.each; + originalFunctions.reset = sqlite3.Statement.prototype.reset; + originalFunctions.finalize = sqlite3.Statement.prototype.finalize; + }); + + it('allow patching native functions', function() { + var myFun = function myFunction() { + return "Success"; + } + + assert.doesNotThrow(() => { + sqlite3.Statement.prototype.bind = myFun; + }); + assert.doesNotThrow(() => { + sqlite3.Statement.prototype.get = myFun; + }); + assert.doesNotThrow(() => { + sqlite3.Statement.prototype.run = myFun; + }); + assert.doesNotThrow(() => { + sqlite3.Statement.prototype.all = myFun; + }); + assert.doesNotThrow(() => { + sqlite3.Statement.prototype.each = myFun; + }); + assert.doesNotThrow(() => { + sqlite3.Statement.prototype.reset = myFun; + }); + assert.doesNotThrow(() => { + sqlite3.Statement.prototype.finalize = myFun; + }); + + db = new sqlite3.Database(':memory:'); + statement = db.prepare(""); + assert.strictEqual(statement.bind(), "Success"); + assert.strictEqual(statement.get(), "Success"); + assert.strictEqual(statement.run(), "Success"); + assert.strictEqual(statement.all(), "Success"); + assert.strictEqual(statement.each(), "Success"); + assert.strictEqual(statement.reset(), "Success"); + assert.strictEqual(statement.finalize(), "Success"); + }); + + after(function() { + if(statement != null) { + sqlite3.Statement.prototype.bind = originalFunctions.bind; + sqlite3.Statement.prototype.get = originalFunctions.get; + sqlite3.Statement.prototype.run = originalFunctions.run; + sqlite3.Statement.prototype.all = originalFunctions.all; + sqlite3.Statement.prototype.each = originalFunctions.each; + sqlite3.Statement.prototype.reset = originalFunctions.reset; + sqlite3.Statement.prototype.finalize = originalFunctions.finalize; + } + if(db != null) { + db.close(); + } + }); + }); + + describe('Backup', function() { + var db; + var backup; + var originalFunctions = {}; + + before(function() { + originalFunctions.step = sqlite3.Backup.prototype.step; + originalFunctions.finish = sqlite3.Backup.prototype.finish; + }); + + it('allow patching native functions', function() { + var myFun = function myFunction() { + return "Success"; + } + + assert.doesNotThrow(() => { + sqlite3.Backup.prototype.step = myFun; + }); + assert.doesNotThrow(() => { + sqlite3.Backup.prototype.finish = myFun; + }); + + db = new sqlite3.Database(':memory:'); + backup = db.backup("somefile", myFun); + assert.strictEqual(backup.step(), "Success"); + assert.strictEqual(backup.finish(), "Success"); + }); + + after(function() { + if(backup != null) { + sqlite3.Backup.prototype.step = originalFunctions.step; + sqlite3.Backup.prototype.finish = originalFunctions.finish; + backup.finish(); + } + if(db != null) { + db.close(); + } + }); + }); +}); diff --git a/test/prepare.test.js b/test/prepare.test.js index c32db72a4..c237b6222 100644 --- a/test/prepare.test.js +++ b/test/prepare.test.js @@ -270,7 +270,7 @@ describe('prepare', function() { before(function(done) { db = new sqlite3.Database('test/support/prepare.db', sqlite3.OPEN_READONLY, done); }); it('should retrieve particular rows', function(done) { - db.prepare("SELECT txt, num, flt, blb FROM foo WHERE num > 5000") + db.prepare("SELECT txt, num, flt, blb FROM foo WHERE num > 5000") .all(function(err, rows) { if (err) throw err; assert.ok(rows.length === 0); diff --git a/test/profile.test.js b/test/profile.test.js index 6545f09c9..d8eb8b5d6 100644 --- a/test/profile.test.js +++ b/test/profile.test.js @@ -14,7 +14,6 @@ describe('profiling', function() { if (sql.match(/^SELECT/)) { assert.ok(!select); assert.equal(sql, "SELECT * FROM foo"); - console.log('profile select'); select = true; } else if (sql.match(/^CREATE/)) { diff --git a/test/support/createdb-electron.js b/test/support/createdb-electron.js new file mode 100644 index 000000000..c2cac4183 --- /dev/null +++ b/test/support/createdb-electron.js @@ -0,0 +1,10 @@ + +var {app} = require('electron'); +var createdb = require('./createdb.js'); + +createdb(function () { + setTimeout(function () { + app.quit(); + }, 20000); +}); + diff --git a/test/support/createdb.js b/test/support/createdb.js index 2cb24c6a6..ee22d05e8 100755 --- a/test/support/createdb.js +++ b/test/support/createdb.js @@ -1,36 +1,48 @@ #!/usr/bin/env node -var existsSync = require('fs').existsSync || require('path').existsSync; -var path = require('path'); +function createdb(callback) { + var existsSync = require('fs').existsSync || require('path').existsSync; + var statSync = require('fs').statSync || require('path').statSync; + var path = require('path'); -var sqlite3 = require('../../lib/sqlite3'); + var sqlite3 = require('../../lib/sqlite3'); -var count = 1000000; -var db_path = path.join(__dirname,'big.db'); + var count = 1000000; + var db_path = path.join(__dirname,'big.db'); -function randomString() { - var str = ''; - var chars = 'abcdefghijklmnopqrstuvwxzyABCDEFGHIJKLMNOPQRSTUVWXZY0123456789 '; - for (var i = Math.random() * 100; i > 0; i--) { - str += chars[Math.floor(Math.random() * chars.length)]; + function randomString() { + var str = ''; + var chars = 'abcdefghijklmnopqrstuvwxzyABCDEFGHIJKLMNOPQRSTUVWXZY0123456789 '; + for (var i = Math.random() * 100; i > 0; i--) { + str += chars[Math.floor(Math.random() * chars.length)]; + } + return str; } - return str; -}; +// Make sure the file exists and is also valid. + if (existsSync(db_path) && statSync(db_path).size !== 0) { + console.log('okay: database already created (' + db_path + ')'); + if (callback) callback(); + } else { + console.log("Creating test database... This may take several minutes."); + var db = new sqlite3.Database(db_path); + db.serialize(function() { + db.run("CREATE TABLE foo (id INT, txt TEXT)"); + db.run("BEGIN TRANSACTION"); + var stmt = db.prepare("INSERT INTO foo VALUES(?, ?)"); + for (var i = 0; i < count; i++) { + stmt.run(i, randomString()); + } + stmt.finalize(); + db.run("COMMIT TRANSACTION", [], function () { + db.close(callback); + }); + }); + } +} -if (existsSync(db_path)) { - console.log('okay: database already created (' + db_path + ')'); -} else { - console.log("Creating test database... This may take several minutes."); - var db = new sqlite3.Database(db_path); - db.serialize(function() { - db.run("CREATE TABLE foo (id INT, txt TEXT)"); - db.run("BEGIN TRANSACTION"); - var stmt = db.prepare("INSERT INTO foo VALUES(?, ?)"); - for (var i = 0; i < count; i++) { - stmt.run(i, randomString()); - } - stmt.finalize(); - db.run("COMMIT TRANSACTION"); - }); +if (require.main === module) { + createdb(); } + +module.exports = createdb; diff --git a/test/support/helper.js b/test/support/helper.js index 10dc20c70..cb2075d2f 100644 --- a/test/support/helper.js +++ b/test/support/helper.js @@ -15,8 +15,8 @@ exports.deleteFile = function(name) { exports.ensureExists = function(name,cb) { if (!pathExists(name)) { fs.mkdirSync(name); - }; -} + } +}; assert.fileDoesNotExist = function(name) { try { @@ -29,9 +29,5 @@ assert.fileDoesNotExist = function(name) { }; assert.fileExists = function(name) { - try { - fs.statSync(name); - } catch(err) { - throw err; - } + fs.statSync(name); }; \ No newline at end of file diff --git a/test/unicode.test.js b/test/unicode.test.js index b76ca4289..9a78c53d6 100644 --- a/test/unicode.test.js +++ b/test/unicode.test.js @@ -48,7 +48,7 @@ describe('unicode', function() { } else if (first < 0xe0) { return String.fromCharCode((first & 0x1f) << 0x6 | random_choice(trailing_values) & 0x3f); } else if (first == 0xe0) { - return String.fromCharCode(((first & 0xf) << 0xc) | ((random_choice(subranges[0]) & 0x3f) << 6) | random_choice(trailing_values) & 0x3f); + return String.fromCharCode(((first & 0xf) << 0xc) | ((random_choice(subranges[0]) & 0x3f) << 6) | random_choice(trailing_values) & 0x3f); } else if (first == 0xed) { return String.fromCharCode(((first & 0xf) << 0xc) | ((random_choice(subranges[1]) & 0x3f) << 6) | random_choice(trailing_values) & 0x3f); } else if (first < 0xf0) { @@ -58,7 +58,7 @@ describe('unicode', function() { function randomString() { var str = '', - i; + i; for (i = Math.random() * 300; i > 0; i--) { str += random_utf8(); @@ -68,7 +68,7 @@ describe('unicode', function() { } - // Generate random data. + // Generate random data. var data = []; var length = Math.floor(Math.random() * 1000) + 200; for (var i = 0; i < length; i++) { diff --git a/test/update_hook.test.js b/test/update_hook.test.js new file mode 100644 index 000000000..6507d2c83 --- /dev/null +++ b/test/update_hook.test.js @@ -0,0 +1,75 @@ +var sqlite3 = require('..'); +var assert = require('assert'); + +describe('update_hook', function() { + var db; + + beforeEach(function(done) { + db = new sqlite3.Database(':memory:', function(err) { + if (err) return done(err); + + db.run("CREATE TABLE update_hooks_test (id int PRIMARY KEY, value text)", done); + }); + }); + + it('emits insert event on inserting data to table', function(done) { + db.addListener('change', function(eventType, database, table, rowId) { + assert.equal(eventType, 'insert'); + assert.equal(database, 'main'); + assert.equal(table, 'update_hooks_test'); + assert.equal(rowId, 1); + + return done(); + }); + + db.run("INSERT INTO update_hooks_test VALUES (1, 'value')", function(err) { + if (err) return done(err); + }); + }); + + it('emits update event on row modification in table', function(done) { + db.run("INSERT INTO update_hooks_test VALUES (2, 'value'), (3, 'value4')", function(err) { + if (err) return done(err); + + db.addListener('change', function(eventType, database, table, rowId) { + assert.equal(eventType, 'update'); + assert.equal(database, 'main'); + assert.equal(table, 'update_hooks_test'); + assert.equal(rowId, 1); + + db.all("SELECT * FROM update_hooks_test WHERE rowid = ?", rowId, function(err, rows) { + assert.deepEqual(rows, [{ id: 2, value: 'new_val' }]); + + return done(err); + }); + }); + + db.run("UPDATE update_hooks_test SET value = 'new_val' WHERE id = 2", function(err) { + if (err) return done(err); + }); + }); + }); + + it('emits delete event on row was deleted from table', function(done) { + db.run("INSERT INTO update_hooks_test VALUES (2, 'value')", function(err) { + if (err) return done(err); + + db.addListener('change', function(eventType, database, table, rowId) { + assert.equal(eventType, 'delete'); + assert.equal(database, 'main'); + assert.equal(table, 'update_hooks_test'); + assert.equal(rowId, 1); + + return done(); + }); + + db.run("DELETE FROM update_hooks_test WHERE id = 2", function(err) { + if (err) return done(err); + }); + }); + }); + + afterEach(function(done) { + db.close(done); + }); +}); diff --git a/test/upsert.test.js b/test/upsert.test.js new file mode 100644 index 000000000..f2aa8fa8b --- /dev/null +++ b/test/upsert.test.js @@ -0,0 +1,27 @@ +var sqlite3 = require('..'); +var assert = require('assert'); + +describe('query properties', function() { + var db; + before(function(done) { + db = new sqlite3.Database(':memory:'); + db.run("CREATE TABLE foo (id INT PRIMARY KEY, count INT)", done); + }); + + (sqlite3.VERSION_NUMBER < 3024000 ? it.skip : it)('should upsert', function(done) { + var stmt = db.prepare("INSERT INTO foo VALUES(?, ?)"); + stmt.run(1, 1, function(err) { // insert 1 + if (err) throw err; + var upsert_stmt = db.prepare("INSERT INTO foo VALUES(?, ?) ON CONFLICT (id) DO UPDATE SET count = count + excluded.count"); + upsert_stmt.run(1, 2, function(err) { // add 2 + if (err) throw err; + var select_stmt = db.prepare("SELECT count FROM foo WHERE id = ?"); + select_stmt.get(1, function(err, row) { + if (err) throw err; + assert.equal(row.count, 3); // equals 3 + }); + }); + }); + db.wait(done); + }); +}); diff --git a/test/verbose.test.js b/test/verbose.test.js new file mode 100644 index 000000000..b680280c4 --- /dev/null +++ b/test/verbose.test.js @@ -0,0 +1,60 @@ +var sqlite3 = require('..'); +var assert = require('assert'); + +var invalid_sql = 'update non_existent_table set id=1'; + +var originalMethods = { + Database: {}, + Statement: {}, +}; + +function backupOriginalMethods() { + for (var obj in originalMethods) { + for (var attr in sqlite3[obj].prototype) { + originalMethods[obj][attr] = sqlite3[obj].prototype[attr]; + } + } +} + +function resetVerbose() { + for (var obj in originalMethods) { + for (var attr in originalMethods[obj]) { + sqlite3[obj].prototype[attr] = originalMethods[obj][attr]; + } + } +} + +describe('verbose', function() { + it('Shoud add trace info to error when verbose is called', function(done) { + var db = new sqlite3.Database(':memory:'); + backupOriginalMethods(); + sqlite3.verbose(); + + db.run(invalid_sql, function(err) { + assert(err instanceof Error); + + assert( + err.stack.indexOf(`Database#run('${invalid_sql}'`) > -1, + `Stack shoud contain trace info, stack = ${err.stack}` + ); + + done(); + resetVerbose(); + }); + }); + + it('Shoud not add trace info to error when verbose is not called', function(done) { + var db = new sqlite3.Database(':memory:'); + + db.run(invalid_sql, function(err) { + assert(err instanceof Error); + + assert( + err.stack.indexOf(invalid_sql) === -1, + `Stack shoud not contain trace info, stack = ${err.stack}` + ); + + done(); + }); + }); +}); diff --git a/tools/BinaryBuilder.Dockerfile b/tools/BinaryBuilder.Dockerfile new file mode 100644 index 000000000..e9c09b40c --- /dev/null +++ b/tools/BinaryBuilder.Dockerfile @@ -0,0 +1,23 @@ +ARG NODE_VERSION=24 +ARG VARIANT=bookworm + +FROM node:$NODE_VERSION-$VARIANT + +ARG VARIANT + +RUN if case $VARIANT in "alpine"*) true;; *) false;; esac; then apk add build-base python3 --update-cache ; fi + +WORKDIR /usr/src/build + +COPY . . +RUN npm install --ignore-scripts + +ENV CFLAGS="${CFLAGS:-} -include ../src/gcc-preinclude.h" +ENV CXXFLAGS="${CXXFLAGS:-} -include ../src/gcc-preinclude.h" +RUN npm run prebuild + +RUN if case $VARIANT in "alpine"*) false;; *) true;; esac; then ldd build/**/node_sqlite3.node; nm build/**/node_sqlite3.node | grep \"GLIBC_\" | c++filt || true ; fi + +RUN npm run test + +CMD ["sh"] diff --git a/benchmark/insert-transaction.sql b/tools/benchmark/insert-transaction.sql similarity index 100% rename from benchmark/insert-transaction.sql rename to tools/benchmark/insert-transaction.sql diff --git a/benchmark/insert.js b/tools/benchmark/insert.js similarity index 96% rename from benchmark/insert.js rename to tools/benchmark/insert.js index c6810cfbe..f2ebf7b90 100644 --- a/benchmark/insert.js +++ b/tools/benchmark/insert.js @@ -1,4 +1,4 @@ -var sqlite3 = require('../lib/sqlite3'); +var sqlite3 = require('../../lib/sqlite3'); var fs = require('fs'); var iterations = 10000; @@ -8,7 +8,7 @@ exports.compare = { var db = new sqlite3.Database(''); var file = fs.readFileSync('benchmark/insert-transaction.sql', 'utf8'); db.exec(file); - db.close(finished) + db.close(finished); }, 'insert with transaction and two statements': function(finished) { diff --git a/tools/benchmark/select-data.sql b/tools/benchmark/select-data.sql new file mode 100644 index 000000000..2f89a4ddd --- /dev/null +++ b/tools/benchmark/select-data.sql @@ -0,0 +1,1014 @@ +CREATE TEMP TABLE Bits (Bit INTEGER PRIMARY KEY); +INSERT INTO Bits VALUES (0); +INSERT INTO Bits VALUES (1); + +CREATE TEMP TABLE Nums AS SELECT + b9.Bit * 512 + b8.Bit * 256 + b7.Bit * 128 + b6.Bit * 64 + b5.Bit * 32 + + b4.Bit * 16 + b3.Bit * 8 + b2.Bit * 4 + b1.Bit * 2 + b0.Bit + AS Num +FROM Bits b9, Bits b8, Bits b7, Bits b6, Bits b5, + Bits b4, Bits b3, Bits b2, Bits b1, Bits b0; + +CREATE TABLE foo (id INT, txt TEXT); +BEGIN; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +COMMIT; diff --git a/tools/benchmark/select.js b/tools/benchmark/select.js new file mode 100644 index 000000000..be4b0e71d --- /dev/null +++ b/tools/benchmark/select.js @@ -0,0 +1,28 @@ +const sqlite3 = require('../../'); +const { readFileSync } = require('fs'); +const db = new sqlite3.Database(':memory:'); + +db.serialize(() => { + db.exec(readFileSync(`${__dirname}/select-data.sql`, 'utf8'), (err) => { + if (err) throw err; + console.time('db.each'); + }); + + { + const results = []; + db.each('SELECT * FROM foo', (err, row) => { + if (err) throw err; + results.push(row); + }, () => { + console.timeEnd('db.each'); + console.time('db.all'); + }); + } + + db.all('SELECT * FROM foo', (err, rows) => { + console.timeEnd('db.all'); + if (err) throw err; + }); + + db.close(); +}); diff --git a/tools/semver-check.js b/tools/semver-check.js new file mode 100644 index 000000000..cedc7a713 --- /dev/null +++ b/tools/semver-check.js @@ -0,0 +1,33 @@ +const fs = require('fs'); +const path = require('path'); +const semver = require('semver'); + +const supportedVersions = '20.17.0'; + +function checkEngines(modulePath) { + const packageJsonPath = path.join(modulePath, 'package.json'); + + if (!fs.existsSync(packageJsonPath)) return; + + const packageJson = JSON.parse(fs.readFileSync(packageJsonPath)); + const engines = packageJson.engines; + + if (engines && engines.node) { + const minVersion = semver.minVersion(engines.node); + + if (semver.gt(minVersion, supportedVersions)) { + console.log(`${packageJson.name}@${packageJson.version} requires ${engines.node}`); + process.exit(1); + } + } +} + +const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'))); + +const allDependencies = Object.keys(packageJson.dependencies || {}).concat(Object.keys(packageJson.optionalDependencies || {})); + +for (const dependency of allDependencies) { + const modulePath = path.join(__dirname, '..', 'node_modules', dependency); + checkEngines(modulePath); +} + diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 000000000..25742b3c1 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,3134 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@eslint-community/eslint-utils@^4.2.0": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz#4e90af67bc51ddee6cdef5284edf572ec376b595" + integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ== + dependencies: + eslint-visitor-keys "^3.4.3" + +"@eslint-community/regexpp@^4.6.1": + version "4.12.2" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b" + integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew== + +"@eslint/eslintrc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.6.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.56.0": + version "8.56.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.56.0.tgz#ef20350fec605a7f7035a01764731b2de0f3782b" + integrity sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A== + +"@humanwhocodes/config-array@^0.11.13": + version "0.11.14" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" + integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== + dependencies: + "@humanwhocodes/object-schema" "^2.0.2" + debug "^4.3.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@isaacs/fs-minipass@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz#2d59ae3ab4b38fb4270bfa23d30f8e2e86c7fe32" + integrity sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w== + dependencies: + minipass "^7.0.4" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@npmcli/agent@^2.0.0": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@npmcli/agent/-/agent-2.2.2.tgz#967604918e62f620a648c7975461c9c9e74fc5d5" + integrity sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og== + dependencies: + agent-base "^7.1.0" + http-proxy-agent "^7.0.0" + https-proxy-agent "^7.0.1" + lru-cache "^10.0.1" + socks-proxy-agent "^8.0.3" + +"@npmcli/fs@^3.1.0": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-3.1.1.tgz#59cdaa5adca95d135fc00f2bb53f5771575ce726" + integrity sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg== + dependencies: + semver "^7.3.5" + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +"@ungap/structured-clone@^1.2.0": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.1.tgz#0e8f34854df7966b09304a18e808b23997bb9fc1" + integrity sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +abbrev@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf" + integrity sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ== + +abbrev@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-4.0.0.tgz#ec933f0e27b6cd60e89b5c6b2a304af42209bb05" + integrity sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA== + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.9.0: + version "8.17.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.17.0.tgz#1785adb84faf8d8add10369b93826fc2bd08f1fe" + integrity sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg== + +after@~0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" + integrity sha512-QbJ0NTQ/I9DI3uSJA4cbexiwQeRAfjPScqIbSjUDd9TOrcg6pTkdgziesOqxBMBzit8vFCTwrP27t13vFOORRA== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +agent-base@^7.1.0, agent-base@^7.1.2: + version "7.1.4" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" + integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv@^6.12.3, ajv@^6.12.4: + version "6.15.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.15.0.tgz#07e982c74626167aa7a2495c53817892d7139492" + integrity sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" + integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.1.0: + version "6.2.3" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041" + integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== + +ansi@^0.3.0, ansi@~0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21" + integrity sha512-iFY7JCgHbepc0b82yLaw4IMortylNb6wG4kL+4R0C3iv6i+RHGHux/yUX5BTiRvSX/shMnngjR1YyNMnXEFh5A== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +"aproba@^1.0.3 || ^2.0.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.1.0.tgz#75500a190313d95c64e871e7e4284c6ac219f0b1" + integrity sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew== + +are-we-there-yet@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz#679df222b278c64f2cdba1175cdc00b0d96164bd" + integrity sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + +are-we-there-yet@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-4.0.2.tgz#aed25dd0eae514660d49ac2b2366b175c614785a" + integrity sha512-ncSWAawFhKMJDTdoAeOV+jyW1VCMj5QIAwULIBV0SSR7B/RLPPEQiknKcg/RIIZlUQrxELpsxMiTUoAQ4sIUyg== + +are-we-there-yet@~1.1.2: + version "1.1.7" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" + integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-index@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-index/-/array-index-1.0.0.tgz#ec56a749ee103e4e08c790b9c353df16055b97f9" + integrity sha512-jesyNbBkLQgGZMSwA1FanaFjalb1mZUGxGeUEkSDidzgrbjBGhvizJkaItdhkt8eIHFOJC7nDsrXk+BaehTdRw== + dependencies: + debug "^2.2.0" + es6-symbol "^3.0.2" + +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== + +aws4@^1.8.0: + version "1.13.2" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef" + integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== + +axios@^1.6.5: + version "1.18.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.18.0.tgz#8a7f8854af280fcaae063272df2ed9f3837d2398" + integrity sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw== + dependencies: + follow-redirects "^1.16.0" + form-data "^4.0.5" + https-proxy-agent "^5.0.1" + proxy-from-env "^2.1.0" + +b4a@^1.6.4, b4a@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.8.1.tgz#7f16334ca80127aeb26064a28841acbf174840a4" + integrity sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +bare-events@^2.5.4, bare-events@^2.7.0: + version "2.9.1" + resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.9.1.tgz#5c86616966343bcb03a1b3155feab253eadbf349" + integrity sha512-Z0oHEHAFDZkffN8Qc39zNZjQlMDkPJRyyyZieU1VH7u8c5S+qHZ2S8ixdKIAxEjfHO7FJxXmJWgteOghVanIsg== + +bare-fs@^4.5.5: + version "4.7.2" + resolved "https://registry.yarnpkg.com/bare-fs/-/bare-fs-4.7.2.tgz#0f59b317e5bdbec6a1489b519a06a203cd3fe035" + integrity sha512-aTvMFUWkBmjzKtEQMDGGDNF8bkfpD5N1b/FCwt7A3wrU4t1o/e/85Wzkluh6JlODCjqVESYCkQCdTXqZ9G7VFg== + dependencies: + bare-events "^2.5.4" + bare-path "^3.0.0" + bare-stream "^2.6.4" + bare-url "^2.2.2" + fast-fifo "^1.3.2" + +bare-os@^3.0.1: + version "3.9.1" + resolved "https://registry.yarnpkg.com/bare-os/-/bare-os-3.9.1.tgz#660228ca7ffc47a72e96b6047cdd9d8342994e2f" + integrity sha512-6M5XjcnsygQNPMCMPXSK379xrJFiZ/AEMNBmFEmQW8d/789VQATvriyi5r0HYTL9TkQ26rn3kgdTG3aisbrXkQ== + +bare-path@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/bare-path/-/bare-path-3.0.1.tgz#c12c81b527936b650e87c5d00264d59ef458082c" + integrity sha512-ghj2DSK/2e99a1anTVPCV4m4YIYtrbXhfM7V3D7XZLOTsybnYyaJloymGqssQc8l/or0UoDyRtNQkmkEF/ysgQ== + dependencies: + bare-os "^3.0.1" + +bare-stream@^2.6.4: + version "2.13.3" + resolved "https://registry.yarnpkg.com/bare-stream/-/bare-stream-2.13.3.tgz#f6186c7cbb4bbf53a4560f35e48b16373ba51ce6" + integrity sha512-Kc+brLqvEqGkjyfiwJmImAOqLZL7OsoLKuavx+hJjgVV3nLTOjloJyPMFxjUPerGGHrNH0fLU06jjykMLWrERQ== + dependencies: + b4a "^1.8.1" + streamx "^2.25.0" + teex "^1.0.1" + +bare-url@^2.2.2: + version "2.4.5" + resolved "https://registry.yarnpkg.com/bare-url/-/bare-url-2.4.5.tgz#50d205f8f2724eec60fd091ba9cebd675fca63aa" + integrity sha512-K+y9xF1tN+CdPu4qWwr0QiK1Al07eFPGYK5M2pDXcmHdMdgC/tT/bpmMe1hrmRHaidKLkXrC+cRNYf3XVDUhSQ== + dependencies: + bare-path "^3.0.0" + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== + dependencies: + tweetnacl "^0.14.3" + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +bl@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/bl/-/bl-3.0.1.tgz#1cbb439299609e419b5a74d7fce2f8b37d8e5c6f" + integrity sha512-jrCW5ZhfQ/Vt07WX1Ngs+yn9BDqPL/gw28S7s9H6QK/gupnizNzJAss5akW20ISgOrbLTlXOOCTJeNUQqruAWQ== + dependencies: + readable-stream "^3.0.1" + +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + integrity sha512-OorbnJVPII4DuUKbjARAe8u8EfqOmkEEaSFIyoQ7OjTHn6kafxWl0wLgoZ2rXaYd7MyLcDaU4TmhfxtwgcccMQ== + dependencies: + inherits "~2.0.0" + +brace-expansion@^1.1.7: + version "1.1.15" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.15.tgz#a6d90d54067236e5f42570a3b7378d594d9b7738" + integrity sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1, brace-expansion@^2.0.2: + version "2.1.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.1.tgz#c68b1c4111c76aae3a6fba55d496cee10c39dad8" + integrity sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA== + dependencies: + balanced-match "^1.0.0" + +braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +buffer-from@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-0.1.2.tgz#15f4b9bcef012044df31142c14333caf6e0260d0" + integrity sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg== + +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +cacache@^18.0.0: + version "18.0.4" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-18.0.4.tgz#4601d7578dadb59c66044e157d02a3314682d6a5" + integrity sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ== + dependencies: + "@npmcli/fs" "^3.1.0" + fs-minipass "^3.0.0" + glob "^10.2.2" + lru-cache "^10.0.1" + minipass "^7.0.3" + minipass-collect "^2.0.1" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + p-map "^4.0.0" + ssri "^10.0.0" + tar "^6.1.11" + unique-filename "^3.0.0" + +call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== + +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +chownr@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4" + integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g== + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +cmake-js@^7.3.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/cmake-js/-/cmake-js-7.4.0.tgz#eb175b8abb97c86e4ba92ca7c22f5c9588b5a0ac" + integrity sha512-Lw0JxEHrmk+qNj1n9W9d4IvkDdYTBn7l2BW6XmtLj7WPpIo2shvxUy+YokfjMxAAOELNonQwX3stkPhM5xSC2Q== + dependencies: + axios "^1.6.5" + debug "^4" + fs-extra "^11.2.0" + memory-stream "^1.0.0" + node-api-headers "^1.1.0" + npmlog "^6.0.2" + rc "^1.2.7" + semver "^7.5.4" + tar "^6.2.0" + url-join "^4.0.1" + which "^2.0.2" + yargs "^17.7.2" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commander@^2.9.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cross-spawn@^7.0.2, cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +d@1, d@^1.0.1, d@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.2.tgz#2aefd554b81981e7dccf72d6842ae725cb17e5de" + integrity sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw== + dependencies: + es5-ext "^0.10.64" + type "^2.7.2" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== + dependencies: + assert-plus "^1.0.0" + +debug@4, debug@^4, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + +debug@4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@^2.2.0: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + +detect-libc@^2.0.0, detect-libc@^2.0.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad" + integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +duplexer2@~0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" + integrity sha512-+AWBwjGadtksxjOQSFDhPNQbed7icNXApT4+2BNpsXzcCBiInq2H9XW0O8sfHFaPmnQRs7cg/P0fAr2IWQSW0g== + dependencies: + readable-stream "~1.1.9" + +each-series-async@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/each-series-async/-/each-series-async-1.0.1.tgz#7e3f8dfa5af934663960e5a17561362909b34328" + integrity sha512-G4zip/Ewpwr6JQxW7+2RNgkPd09h/UNec5UlvA/xKwl4qf5blyBNK6a/zjQc3MojgsxaOb93B9v3T92QU6IMVg== + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +encoding@^0.1.13: + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + +end-of-stream@^1.1.0, end-of-stream@^1.4.1: + version "1.4.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" + integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== + dependencies: + once "^1.4.0" + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +err-code@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" + integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== + +es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.2.tgz#a2d0b373205724dfa525d23b0c3e1b1ca582c99b" + integrity sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +es5-ext@^0.10.35, es5-ext@^0.10.62, es5-ext@^0.10.64, es5-ext@~0.10.14: + version "0.10.64" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.64.tgz#12e4ffb48f1ba2ea777f1fcdd1918ef73ea21714" + integrity sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + esniff "^2.0.1" + next-tick "^1.1.0" + +es6-iterator@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.0.2, es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.4" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.4.tgz#f4e7d28013770b4208ecbf3e0bf14d3bcb557b8c" + integrity sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg== + dependencies: + d "^1.0.2" + ext "^1.7.0" + +escalade@^3.1.1: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint@8.56.0: + version "8.56.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.56.0.tgz#4957ce8da409dc0809f99ab07a1b94832ab74b15" + integrity sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.56.0" + "@humanwhocodes/config-array" "^0.11.13" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + "@ungap/structured-clone" "^1.2.0" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +esniff@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/esniff/-/esniff-2.0.1.tgz#a4d4b43a5c71c7ec51c51098c1d8a29081f9b308" + integrity sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg== + dependencies: + d "^1.0.1" + es5-ext "^0.10.62" + event-emitter "^0.3.5" + type "^2.7.2" + +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esquery@^1.4.2: + version "1.7.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.7.0.tgz#08d048f261f0ddedb5bae95f46809463d9c9496d" + integrity sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== + dependencies: + d "1" + es5-ext "~0.10.14" + +events-universal@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/events-universal/-/events-universal-1.0.1.tgz#b56a84fd611b6610e0a2d0f09f80fdf931e2dfe6" + integrity sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw== + dependencies: + bare-events "^2.7.0" + +execspawn@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/execspawn/-/execspawn-1.0.1.tgz#8286f9dde7cecde7905fbdc04e24f368f23f8da6" + integrity sha512-s2k06Jy9i8CUkYe0+DxRlvtkZoOkwwfhB+Xxo5HGUtrISVW2m98jO2tr67DGRFxZwkjQqloA3v/tNtjhBRBieg== + dependencies: + util-extend "^1.0.1" + +expand-template@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" + integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== + +exponential-backoff@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.3.tgz#51cf92c1c0493c766053f9d3abee4434c244d2f6" + integrity sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA== + +ext@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + dependencies: + type "^2.7.2" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-fifo@^1.2.0, fast-fifo@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" + integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.20.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.20.1.tgz#ca750a10dc925bc8b18839fd203e3ef4b3ced675" + integrity sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw== + dependencies: + reusify "^1.0.4" + +fdir@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-up@5.0.0, find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.3" + rimraf "^3.0.2" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +flatted@^3.2.9: + version "3.4.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.4.2.tgz#f5c23c107f0f37de8dbdf24f13722b3b98d52726" + integrity sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA== + +follow-redirects@^1.16.0: + version "1.16.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.16.0.tgz#28474a159d3b9d11ef62050a14ed60e4df6d61bc" + integrity sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw== + +foreground-child@^3.1.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" + integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== + dependencies: + cross-spawn "^7.0.6" + signal-exit "^4.0.1" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== + +form-data@^4.0.5: + version "4.0.6" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.6.tgz#28e864e1b786dbebb68db1f452f9635278665827" + integrity sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + hasown "^2.0.4" + mime-types "^2.1.35" + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + +fs-extra@^11.2.0: + version "11.3.5" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.5.tgz#07a44eff40bea53e719909a532f91a23bf0769ff" + integrity sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs-minipass@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-3.0.3.tgz#79a85981c4dc120065e96f62086bf6f9dc26cc54" + integrity sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw== + dependencies: + minipass "^7.0.3" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +fstream@^1.0.0, fstream@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" + integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +gauge@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce" + integrity sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.3" + console-control-strings "^1.1.0" + has-unicode "^2.0.1" + signal-exit "^3.0.7" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.5" + +gauge@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-5.0.2.tgz#7ab44c11181da9766333f10db8cd1e4b17fd6c46" + integrity sha512-pMaFftXPtiGIHCJHdcUUx9Rby/rFT/Kkt3fIIGCs+9PMDIljSyRiqraTlxNtBReJRDfUefpa263RQ3vnp5G/LQ== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.3" + console-control-strings "^1.1.0" + has-unicode "^2.0.1" + signal-exit "^4.0.1" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.5" + +gauge@~1.2.5: + version "1.2.7" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-1.2.7.tgz#e9cec5483d3d4ee0ef44b60a7d99e4935e136d93" + integrity sha512-fVbU2wRE91yDvKUnrIaQlHKAWKY5e08PmztCrwuH5YVQ+Z/p3d0ny2T48o6uvAAXHIUnfaQdHkmxYbQft1eHVA== + dependencies: + ansi "^0.3.0" + has-unicode "^2.0.0" + lodash.pad "^4.1.0" + lodash.padend "^4.1.0" + lodash.padstart "^4.1.0" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg== + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.2.6: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== + dependencies: + assert-plus "^1.0.0" + +ghreleases@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/ghreleases/-/ghreleases-3.0.2.tgz#1bdb6d31ec03a24a0d80f58f5e9a84a4db725818" + integrity sha512-QiR9mIYvRG7hd8JuQYoxeBNOelVuTp2DpdiByRywbCDBSJufK9Vq7VuhD8B+5uviMxZx2AEkCzye61Us9gYgnw== + dependencies: + after "~0.8.1" + ghrepos "~2.1.0" + ghutils "~3.2.0" + lodash.uniq "^4.5.0" + simple-mime "~0.1.0" + url-template "~2.0.6" + +ghrepos@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ghrepos/-/ghrepos-2.1.0.tgz#abaf558b690b722c70c7ad45076f6f9be8e495e1" + integrity sha512-6GM0ohSDTAv7xD6GsKfxJiV/CajoofRyUwu0E8l29d1o6lFAUxmmyMP/FH33afA20ZrXzxxcTtN6TsYvudMoAg== + dependencies: + ghutils "~3.2.0" + +ghutils@~3.2.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/ghutils/-/ghutils-3.2.6.tgz#d43986e267da02787464d97a6489659e4609bb1f" + integrity sha512-WpYHgLQkqU7Cv147wKUEThyj6qKHCdnAG2CL9RRsRQImVdLGdVqblJ3JUnj3ToQwgm1ALPS+FXgR0448AgGPUg== + dependencies: + jsonist "~2.1.0" + xtend "~4.0.1" + +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + integrity sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw== + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +"glob@3 || 4 || 5 || 6 || 7", glob@^7.0.3, glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^10.2.2, glob@^10.3.10: + version "10.5.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.5.0.tgz#8ec0355919cd3338c28428a23d4f24ecc5fe738c" + integrity sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + +globals@^13.19.0: + version "13.24.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== + dependencies: + type-fest "^0.20.2" + +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.6: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +has-unicode@^2.0.0, has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + +hasown@^2.0.2, hasown@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.4.tgz#8c62d8cb90beb2aad5d0a5b67581ad9854c3f003" + integrity sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A== + dependencies: + function-bind "^1.1.2" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +http-cache-semantics@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz#205f4db64f8562b76a4ff9235aa5279839a09dd5" + integrity sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ== + +http-proxy-agent@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-proxy-agent@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +https-proxy-agent@^7.0.1: + version "7.0.6" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" + integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== + dependencies: + agent-base "^7.1.2" + debug "4" + +hyperquest@~2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/hyperquest/-/hyperquest-2.1.3.tgz#523127d7a343181b40bf324e231d2576edf52633" + integrity sha512-fUuDOrB47PqNK/BAMOS13v41UoaqIxqSLHX6CAbOD7OfT+/GCWO1/vPLfTNutOeXrv1ikuaZ3yux+33Z9vh+rw== + dependencies: + buffer-from "^0.1.1" + duplexer2 "~0.0.2" + through2 "~0.6.3" + +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore@^5.2.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + +import-fresh@^3.2.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" + integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +ip-address@^10.1.1: + version "10.2.0" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.2.0.tgz#805fc178b20c518bd4c8548b24fe30892d7f3206" + integrity sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-lambda@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" + integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isexe@^3.1.1: + version "3.1.5" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-3.1.5.tgz#42e368f68d5e10dadfee4fda7b550bc2d8892dc9" + integrity sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w== + +isexe@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-4.0.0.tgz#48f6576af8e87a18feb796b7ed5e2e5903b43dca" + integrity sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw== + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== + +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +js-yaml@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.2.0.tgz#2bd9e85682dd91bd469afb809d816043b3d49524" + integrity sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw== + dependencies: + argparse "^2.0.1" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +jsonfile@^6.0.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.2.1.tgz#b6e31717f22cc37330b081ce0051ed5de53af2f6" + integrity sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonist@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/jsonist/-/jsonist-2.1.2.tgz#c1377311e8fc857abe7aa3df197116a911f95324" + integrity sha512-8yqmWJAC2VaYoSKQAbsfgCpGY5o/1etWzx6ZxaZrC4iGaHrHUZEo+a2MyF8w+2uTavTlHdLWaZUoR19UfBstxQ== + dependencies: + bl "~3.0.0" + hyperquest "~2.1.3" + json-stringify-safe "~5.0.1" + xtend "~4.0.1" + +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.pad@^4.1.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/lodash.pad/-/lodash.pad-4.5.1.tgz#4330949a833a7c8da22cc20f6a26c4d59debba70" + integrity sha512-mvUHifnLqM+03YNzeTBS1/Gr6JRFjd3rRx88FHWUvamVaT9k2O/kXha3yBSOwB9/DTQrSTLJNHvLBBt2FdX7Mg== + +lodash.padend@^4.1.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e" + integrity sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw== + +lodash.padstart@^4.1.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b" + integrity sha512-sW73O6S8+Tg66eY56DBk85aQzzUJDtpoXFBgELMd5P/SotAguo+1kYO6RuYgXxA4HJH3LFTFPASX6ET6bjfriw== + +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +lru-cache@^10.0.1, lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + +make-fetch-happen@^13.0.0: + version "13.0.1" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz#273ba2f78f45e1f3a6dca91cede87d9fa4821e36" + integrity sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA== + dependencies: + "@npmcli/agent" "^2.0.0" + cacache "^18.0.0" + http-cache-semantics "^4.1.1" + is-lambda "^1.0.1" + minipass "^7.0.2" + minipass-fetch "^3.0.0" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + negotiator "^0.6.3" + proc-log "^4.2.0" + promise-retry "^2.0.1" + ssri "^10.0.0" + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +memory-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/memory-stream/-/memory-stream-1.0.0.tgz#481dfd259ccdf57b03ec2c9632960044180e73c2" + integrity sha512-Wm13VcsPIMdG96dzILfij09PvuS3APtcKNh7M28FsCA/w6+1mjR7hhPmfFNoilX9xU7wTdhsH5lJAm6XNzdtww== + dependencies: + readable-stream "^3.4.0" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@^2.1.35, mime-types@~2.1.19: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + +minimatch@3, minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e" + integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== + dependencies: + brace-expansion "^1.1.7" + +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.4: + version "9.0.9" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.9.tgz#9b0cb9fcb78087f6fd7eababe2511c4d3d60574e" + integrity sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg== + dependencies: + brace-expansion "^2.0.2" + +minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.6, minimist@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +minipass-collect@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-2.0.1.tgz#1621bc77e12258a12c60d34e2276ec5c20680863" + integrity sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw== + dependencies: + minipass "^7.0.3" + +minipass-fetch@^3.0.0: + version "3.0.5" + resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-3.0.5.tgz#f0f97e40580affc4a35cc4a1349f05ae36cb1e4c" + integrity sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg== + dependencies: + minipass "^7.0.3" + minipass-sized "^1.0.3" + minizlib "^2.1.2" + optionalDependencies: + encoding "^0.1.13" + +minipass-flush@^1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.7.tgz#145c383d5ae294b36030aa80d4e872d08bebcb73" + integrity sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA== + dependencies: + minipass "^3.0.0" + +minipass-pipeline@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" + integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== + dependencies: + minipass "^3.0.0" + +minipass-sized@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70" + integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g== + dependencies: + minipass "^3.0.0" + +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.2, minipass@^7.0.3, minipass@^7.0.4, minipass@^7.1.2: + version "7.1.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.3.tgz#79389b4eb1bb2d003a9bba87d492f2bd37bdc65b" + integrity sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A== + +minizlib@^2.1.1, minizlib@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +minizlib@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-3.1.0.tgz#6ad76c3a8f10227c9b51d1c9ac8e30b27f5a251c" + integrity sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw== + dependencies: + minipass "^7.1.2" + +mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + +"mkdirp@>=0.5 0", mkdirp@^0.5.0: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mocha@10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" + integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== + dependencies: + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.4" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "5.0.1" + ms "2.1.3" + nanoid "3.3.3" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + workerpool "6.2.1" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nanoid@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" + integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== + +napi-build-utils@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" + integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== + +napi-build-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-2.0.0.tgz#13c22c0187fcfccce1461844136372a47ddc027e" + integrity sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +negotiator@^0.6.3: + version "0.6.4" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7" + integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== + +next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + +node-abi@^3.3.0, node-abi@^3.54.0: + version "3.92.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.92.0.tgz#18e2214677499b8dda81ffcd095afc763d5a9802" + integrity sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ== + dependencies: + semver "^7.3.5" + +node-addon-api@^8.0.0: + version "8.8.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-8.8.0.tgz#b742be05007b37ebc1741bbaf370d22bf25d208a" + integrity sha512-c5Ko1fZJIJmzhFIkhRN76WTq+fC6tWnGy9CXA0fA+XygsWZmEwG8vmbkNqxMyoaa0Tin4djul49NzdVcJJcjeA== + +node-api-headers@^1.1.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/node-api-headers/-/node-api-headers-1.9.0.tgz#28bd6c8de3cbfe0649fa9bd581d9375677c8cc13" + integrity sha512-2oNILP4jXwRB4ywnYKjVk1YyJ96n2D4EOVJO6S3oYZ5PtbJrw3Yt9TpAuX3nBLMuzn74rnfGQrv13pS9vC+YiA== + +node-gyp@12.x: + version "12.4.0" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-12.4.0.tgz#2d017b6ea1ca9294dbbee75be533728f49257024" + integrity sha512-OMcPNvqTCFUnNaBlmdgq+lfNqY7gTiSmNRDjY3uAXRyudeKZEZxu3CLtjMQrx4zZxCX2b/mpNqTtwuCJgXhHkw== + dependencies: + env-paths "^2.2.0" + exponential-backoff "^3.1.1" + graceful-fs "^4.2.6" + nopt "^9.0.0" + proc-log "^6.0.0" + semver "^7.3.5" + tar "^7.5.4" + tinyglobby "^0.2.12" + undici "^6.25.0" + which "^6.0.0" + +node-gyp@^10.0.1: + version "10.3.1" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-10.3.1.tgz#1dd1a1a1c6c5c59da1a76aea06a062786b2c8a1a" + integrity sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ== + dependencies: + env-paths "^2.2.0" + exponential-backoff "^3.1.1" + glob "^10.3.10" + graceful-fs "^4.2.6" + make-fetch-happen "^13.0.0" + nopt "^7.0.0" + proc-log "^4.1.0" + semver "^7.3.5" + tar "^6.2.1" + which "^4.0.0" + +node-ninja@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/node-ninja/-/node-ninja-1.0.2.tgz#20a09e57b92e2df591993d4bf098ac3e727062b6" + integrity sha512-wMtWsG2QZI1Z5V7GciX9OI2DVT0PuDRIDQfe3L3rJsQ1qN1Gm3QQhoNtb4PMRi7gq4ByvEIYtPwHC7YbEf5yxw== + dependencies: + fstream "^1.0.0" + glob "3 || 4 || 5 || 6 || 7" + graceful-fs "^4.1.2" + minimatch "3" + mkdirp "^0.5.0" + nopt "2 || 3" + npmlog "0 || 1 || 2" + osenv "0" + path-array "^1.0.0" + request "2" + rimraf "2" + semver "2.x || 3.x || 4 || 5" + tar "^2.0.0" + which "1" + +noop-logger@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" + integrity sha512-6kM8CLXvuW5crTxsAtva2YLrRrDaiTIkIePWs9moLHqbFWT94WpNFjwS/5dfLfECg5i/lkmw3aoqVidxt23TEQ== + +"nopt@2 || 3": + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg== + dependencies: + abbrev "1" + +nopt@^7.0.0: + version "7.2.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-7.2.1.tgz#1cac0eab9b8e97c9093338446eddd40b2c8ca1e7" + integrity sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w== + dependencies: + abbrev "^2.0.0" + +nopt@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-9.0.0.tgz#6bff0836b2964d24508b6b41b5a9a49c4f4a1f96" + integrity sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw== + dependencies: + abbrev "^4.0.0" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-path@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-2.0.4.tgz#c641347a5ff9d6a09e4d9bce5580c4f505278e64" + integrity sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw== + dependencies: + which "^1.2.10" + +npm-which@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/npm-which/-/npm-which-3.0.1.tgz#9225f26ec3a285c209cae67c3b11a6b4ab7140aa" + integrity sha512-CM8vMpeFQ7MAPin0U3wzDhSGV0hMHNwHU0wjo402IVizPDrs45jSfSuoC+wThevY88LQti8VvaAnqYAeVy3I1A== + dependencies: + commander "^2.9.0" + npm-path "^2.0.2" + which "^1.2.10" + +"npmlog@0 || 1 || 2": + version "2.0.4" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-2.0.4.tgz#98b52530f2514ca90d09ec5b22c8846722375692" + integrity sha512-DaL6RTb8Qh4tMe2ttPT1qWccETy2Vi5/8p+htMpLBeXJTr2CAqnF5WQtSP2eFpvaNbhLZ5uilDb98mRm4Q+lZQ== + dependencies: + ansi "~0.3.1" + are-we-there-yet "~1.1.2" + gauge "~1.2.5" + +"npmlog@0 || 1 || 2 || 3 || 4": + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +npmlog@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830" + integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg== + dependencies: + are-we-there-yet "^3.0.0" + console-control-strings "^1.1.0" + gauge "^4.0.3" + set-blocking "^2.0.0" + +npmlog@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-7.0.1.tgz#7372151a01ccb095c47d8bf1d0771a4ff1f53ac8" + integrity sha512-uJ0YFk/mCQpLBt+bxN88AKd+gyqZvZDbtiNxk6Waqcj2aPRyfVx8ITawkyQynxUagInjdYT1+qj4NfA5KJJUxg== + dependencies: + are-we-there-yet "^4.0.0" + console-control-strings "^1.1.0" + gauge "^5.0.0" + set-blocking "^2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== + +nw-gyp@^3.6.6: + version "3.6.8" + resolved "https://registry.yarnpkg.com/nw-gyp/-/nw-gyp-3.6.8.tgz#5a2a42dcde6f5644ad73f45872ad81d01824f762" + integrity sha512-5aIDGPOlePxo0wBPzRDdOpgo/9Al+La0gCjKIjSl4K8FDvb5vFJB+H9SpBwBtXNpi2KEMImtvKwSkt85stNcCA== + dependencies: + fstream "^1.0.0" + glob "^7.0.3" + graceful-fs "^4.1.2" + minimatch "^3.0.2" + mkdirp "^0.5.0" + nopt "2 || 3" + npmlog "0 || 1 || 2 || 3 || 4" + osenv "0" + request "2" + rimraf "2" + semver "~5.3.0" + tar "^2.0.0" + which "1" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.5" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== + +os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +osenv@0: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +path-array@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-array/-/path-array-1.0.1.tgz#7e2f0f35f07a2015122b868b7eac0eb2c4fec271" + integrity sha512-teWG2rJTJJZi2kINKOsHcdIuHP7jy3D7pAsVgdhxMq8kaL2RnS5sg7YTlrClMVCIItcVbPTPI6eMBEoNxYahLA== + dependencies: + array-index "^1.0.0" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.2.tgz#5a942915e26b372dc0f0e6753149a16e6b1c5601" + integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA== + +picomatch@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.4.tgz#fd6f5e00a143086e074dffe4c924b8fb293b0589" + integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A== + +prebuild-install@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.3.tgz#d630abad2b147443f20a212917beae68b8092eec" + integrity sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug== + dependencies: + detect-libc "^2.0.0" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.3" + mkdirp-classic "^0.5.3" + napi-build-utils "^2.0.0" + node-abi "^3.3.0" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^4.0.0" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + +prebuild@13.0.1: + version "13.0.1" + resolved "https://registry.yarnpkg.com/prebuild/-/prebuild-13.0.1.tgz#6e554d9e1b232044d4a26115ef8c8e088ad85d25" + integrity sha512-AR+ZoFfG2qQM5iCtNNBWlueuzlBWQdeiU+fBF7ZwbW2w5p/2Ep1+3G4AtAymrMfZn0yg3DoF+xCorh5hHOJY/Q== + dependencies: + cmake-js "^7.3.0" + detect-libc "^2.0.2" + each-series-async "^1.0.1" + execspawn "^1.0.1" + ghreleases "^3.0.2" + github-from-package "0.0.0" + glob "^10.3.10" + minimist "^1.2.8" + napi-build-utils "^1.0.2" + node-abi "^3.54.0" + node-gyp "^10.0.1" + node-ninja "^1.0.2" + noop-logger "^0.1.1" + npm-which "^3.0.1" + npmlog "^7.0.1" + nw-gyp "^3.6.6" + rc "^1.2.8" + run-waterfall "^1.1.7" + tar-stream "^3.1.7" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +proc-log@^4.1.0, proc-log@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-4.2.0.tgz#b6f461e4026e75fdfe228b265e9f7a00779d7034" + integrity sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA== + +proc-log@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-6.1.0.tgz#18519482a37d5198e231133a70144a50f21f0215" + integrity sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +promise-retry@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22" + integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g== + dependencies: + err-code "^2.0.2" + retry "^0.12.0" + +proxy-from-env@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz#a7487568adad577cfaaa7e88c49cab3ab3081aba" + integrity sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA== + +psl@^1.1.28: + version "1.15.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" + integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w== + dependencies: + punycode "^2.3.1" + +pump@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.4.tgz#1f313430527fa8b905622ebd22fe1444e757ab3c" + integrity sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +qs@~6.5.2: + version "6.5.5" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.5.tgz#7c9442fc3f1c58bb52ac57ad09db63ba68916395" + integrity sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +rc@^1.2.7, rc@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +"readable-stream@>=1.0.33-1 <1.1.0-0": + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.0.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.1, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +request@2: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + +reusify@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== + +rimraf@2: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +run-waterfall@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/run-waterfall/-/run-waterfall-1.1.7.tgz#ae368b549b2f5171f86c2924492cab3352a6e9c5" + integrity sha512-iFPgh7SatHXOG1ClcpdwHI63geV3Hc/iL6crGSyBlH2PY7Rm/za+zoKz6FfY/Qlw5K7JwSol8pseO8fN6CMhhQ== + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +"safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +"semver@2.x || 3.x || 4 || 5": + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@^7.3.5, semver@^7.5.4: + version "7.8.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.8.5.tgz#39b646037dd50c14fb451e7e4cac58ed8b863f69" + integrity sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA== + +semver@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + integrity sha512-mfmm3/H9+67MCVix1h+IXTpDwL6710LyHuk7+cWC9T1mE0qz4iHhh6r4hU2wrIT9iTsAAC2XQRvfblL028cpLw== + +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.0, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" + integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== + dependencies: + decompress-response "^6.0.0" + once "^1.3.1" + simple-concat "^1.0.0" + +simple-mime@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/simple-mime/-/simple-mime-0.1.0.tgz#95f517c4f466d7cff561a71fc9dab2596ea9ef2e" + integrity sha512-2EoTElzj77w0hV4lW6nWdA+MR+81hviMBhEc/ppUi0+Q311EFCvwKrGS7dcxqvGRKnUdbAyqPJtBQbRYgmtmvQ== + +smart-buffer@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== + +socks-proxy-agent@^8.0.3: + version "8.0.5" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz#b9cdb4e7e998509d7659d689ce7697ac21645bee" + integrity sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw== + dependencies: + agent-base "^7.1.2" + debug "^4.3.4" + socks "^2.8.3" + +socks@^2.8.3: + version "2.8.9" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.9.tgz#aa5f130ca0f88a43fa44faf4869c50d22aa27752" + integrity sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw== + dependencies: + ip-address "^10.1.1" + smart-buffer "^4.2.0" + +sshpk@^1.7.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" + integrity sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +ssri@^10.0.0: + version "10.0.6" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.6.tgz#a8aade2de60ba2bce8688e3fa349bad05c7dc1e5" + integrity sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ== + dependencies: + minipass "^7.0.3" + +streamx@^2.12.5, streamx@^2.15.0, streamx@^2.25.0: + version "2.28.0" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.28.0.tgz#035ab56057b7ed2211b51d532e6973f0f99fbf11" + integrity sha512-1Yowhzjf0ivGMrTIkY9hav5TxobO9qIVqUE41fiCGMGgc3CLlf4MY+9AHmZqBWgDTue0fY9zWjYFVyf6Diuobw== + dependencies: + events-universal "^1.0.0" + fast-fifo "^1.3.2" + text-decoder "^1.1.0" + +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.2.0.tgz#d22a269522836a627af8d04b5c3fd2c7fa3e32e3" + integrity sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w== + dependencies: + ansi-regex "^6.2.2" + +strip-json-comments@3.1.1, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +tar-fs@^2.0.0: + version "2.1.4" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.4.tgz#800824dbf4ef06ded9afea4acafe71c67c76b930" + integrity sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-stream@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + +tar-stream@^3.1.7: + version "3.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-3.2.0.tgz#0d0064d9b67ea3c9f5abde155e35faab0df37591" + integrity sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg== + dependencies: + b4a "^1.6.4" + bare-fs "^4.5.5" + fast-fifo "^1.2.0" + streamx "^2.15.0" + +tar@^2.0.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" + integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA== + dependencies: + block-stream "*" + fstream "^1.0.12" + inherits "2" + +tar@^6.1.11, tar@^6.2.0, tar@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" + integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +tar@^7.5.10, tar@^7.5.4: + version "7.5.16" + resolved "https://registry.yarnpkg.com/tar/-/tar-7.5.16.tgz#f11e063afed4554f758049d082909e37d6b53ced" + integrity sha512-56adEpPMouktRlBLXiaYFFzZ/3+JXa8P9n7WbR+ibIjtviN55mEaOkiysCnPnWm+7kkui1Dn8J9l+g6zV8731w== + dependencies: + "@isaacs/fs-minipass" "^4.0.0" + chownr "^3.0.0" + minipass "^7.1.2" + minizlib "^3.1.0" + yallist "^5.0.0" + +teex@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/teex/-/teex-1.0.1.tgz#b8fa7245ef8e8effa8078281946c85ab780a0b12" + integrity sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg== + dependencies: + streamx "^2.12.5" + +text-decoder@^1.1.0: + version "1.2.7" + resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.2.7.tgz#5d073a9a74b9c0a9d28dfadcab96b604af57d8ba" + integrity sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ== + dependencies: + b4a "^1.6.4" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +through2@~0.6.3: + version "0.6.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" + integrity sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg== + dependencies: + readable-stream ">=1.0.33-1 <1.1.0-0" + xtend ">=4.0.0 <4.1.0-0" + +tinyglobby@^0.2.12: + version "0.2.17" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.17.tgz#562a9a6c9eb2b3b123d39719f9af5bb44fcd7631" + integrity sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g== + dependencies: + fdir "^6.5.0" + picomatch "^4.0.4" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type@^2.7.2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.3.tgz#436981652129285cc3ba94f392886c2637ea0486" + integrity sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ== + +undici@^6.25.0: + version "6.27.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-6.27.0.tgz#41f9e48f7c5a40d27376caaead8c9a9fc7bca9c4" + integrity sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg== + +unique-filename@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-3.0.0.tgz#48ba7a5a16849f5080d26c760c86cf5cf05770ea" + integrity sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g== + dependencies: + unique-slug "^4.0.0" + +unique-slug@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-4.0.0.tgz#6bae6bb16be91351badd24cdce741f892a6532e3" + integrity sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ== + dependencies: + imurmurhash "^0.1.4" + +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +url-join@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" + integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== + +url-template@~2.0.6: + version "2.0.8" + resolved "https://registry.yarnpkg.com/url-template/-/url-template-2.0.8.tgz#fc565a3cccbff7730c775f5641f9555791439f21" + integrity sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +util-extend@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f" + integrity sha512-mLs5zAK+ctllYBj+iAQvlDCwoxU/WDOUaJkcFudeiAX6OajC6BKXJUa9a+tbtkC11dz2Ufb7h0lyvIOVn4LADA== + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +which@1, which@^1.2.10: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1, which@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +which@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/which/-/which-4.0.0.tgz#cd60b5e74503a3fbcfbf6cd6b4138a8bae644c1a" + integrity sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg== + dependencies: + isexe "^3.1.1" + +which@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/which/-/which-6.0.1.tgz#021642443a198fb93b784a5606721cb18cfcbfce" + integrity sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg== + dependencies: + isexe "^4.0.0" + +wide-align@^1.1.0, wide-align@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +"xtend@>=4.0.0 <4.1.0-0", xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yallist@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-5.0.0.tgz#00e2de443639ed0d78fd87de0d27469fbcffb533" + integrity sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw== + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@^17.7.2: + version "17.7.3" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.3.tgz#779dffe6bcafec596a7172e983289a588647faaa" + integrity sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==