├── .cargo └── config.toml ├── .editorconfig ├── .env.example ├── .github ├── actions │ └── yarn-install │ │ └── action.yml └── workflows │ ├── build_and_release.yml │ ├── lint.yml │ └── test.yml ├── .gitignore ├── .prettierignore ├── .yarn ├── plugins │ └── @yarnpkg │ │ ├── plugin-interactive-tools.cjs │ │ └── plugin-typescript.cjs └── releases │ └── yarn-3.3.1.cjs ├── .yarnrc.yml ├── CONTRIBUTING.md ├── Cargo.toml ├── LICENSE ├── README.md ├── __tests__ ├── __snapshots__ │ └── cli.ts.snap └── cli.ts ├── bin.js ├── build.rs ├── index.d.ts ├── index.js ├── npm ├── darwin-arm64 │ ├── README.md │ └── package.json ├── darwin-x64 │ ├── README.md │ └── package.json ├── linux-arm-gnueabihf │ ├── README.md │ └── package.json ├── linux-arm64-gnu │ ├── README.md │ └── package.json ├── linux-arm64-musl │ ├── README.md │ └── package.json ├── linux-x64-gnu │ ├── README.md │ └── package.json ├── linux-x64-musl │ ├── README.md │ └── package.json └── win32-x64-msvc │ ├── README.md │ └── package.json ├── package.json ├── rustfmt.toml ├── src ├── api.rs ├── error.rs ├── lib.rs └── utils.rs ├── tsconfig.json ├── vitest.config.ts ├── vitest.utils.ts └── yarn.lock /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.x86_64-unknown-linux-musl] 2 | rustflags = [ 3 | "-C", 4 | "target-feature=-crt-static", 5 | ] 6 | 7 | [target.aarch64-unknown-linux-musl] 8 | linker = "aarch64-linux-musl-gcc" 9 | rustflags = ["-C", "target-feature=-crt-static"] -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 2 7 | indent_style = tab 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | GITHUB_ACCESS_TOKEN=your-token -------------------------------------------------------------------------------- /.github/actions/yarn-install/action.yml: -------------------------------------------------------------------------------- 1 | # "yarn install" composite action for yarn 2/3/4+ and "nodeLinker: node-modules" 2 | # Cache: 3 | # - Downloaded zip archive (multi-arch, preserved across yarn.lock changes) 4 | # - Yarn install state (discarded on yarn.lock changes) 5 | # Based on: https://gist.github.com/belgattitude/042f9caf10d029badbde6cf9d43e400a 6 | 7 | name: "yarn install" 8 | description: "Run yarn install with node_modules linker and cache enabled" 9 | runs: 10 | using: "composite" 11 | steps: 12 | - name: Expose yarn config as "$GITHUB_OUTPUT" 13 | id: yarn-config 14 | shell: bash 15 | run: | 16 | echo "CACHE_FOLDER=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT 17 | - name: Restore yarn cache 18 | uses: actions/cache@v3 19 | id: yarn-download-cache 20 | with: 21 | path: ${{ steps.yarn-config.outputs.CACHE_FOLDER }} 22 | key: yarn-download-cache-${{ hashFiles('yarn.lock') }} 23 | restore-keys: | 24 | yarn-download-cache- 25 | - name: Restore yarn install state 26 | id: yarn-install-state-cache 27 | uses: actions/cache@v3 28 | with: 29 | path: .yarn/ci-cache/ 30 | key: ${{ runner.os }}-yarn-install-state-cache-${{ hashFiles('yarn.lock', '.yarnrc.yml') }} 31 | - name: Install dependencies 32 | shell: bash 33 | run: | 34 | yarn install --immutable --inline-builds 35 | env: 36 | # CI optimizations. Overrides yarnrc.yml options (or their defaults) in the CI action. 37 | YARN_ENABLE_GLOBAL_CACHE: "false" # Use local cache folder to keep downloaded archives 38 | YARN_NM_MODE: "hardlinks-local" # Hardlinks-(local|global) reduces io / node_modules size 39 | YARN_INSTALL_STATE_PATH: .yarn/ci-cache/install-state.gz # Very small speedup when lock does not change 40 | # Other environment variables 41 | HUSKY: "0" # By default do not run HUSKY install 42 | -------------------------------------------------------------------------------- /.github/workflows/build_and_release.yml: -------------------------------------------------------------------------------- 1 | name: Build & Release 2 | 3 | env: 4 | DEBUG: napi:* 5 | APP_NAME: thanks-contributors 6 | MACOSX_DEPLOYMENT_TARGET: "10.13" 7 | RUST_BACKTRACE: full 8 | NODE_VERSION: 20 9 | 10 | on: 11 | push: 12 | branches: 13 | - main 14 | tags-ignore: 15 | - "**" 16 | paths-ignore: 17 | - "**/*.md" 18 | - LICENSE 19 | - "**/*.gitignore" 20 | - .editorconfig 21 | - docs/** 22 | pull_request: null 23 | 24 | concurrency: 25 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 26 | cancel-in-progress: true 27 | 28 | jobs: 29 | build: 30 | strategy: 31 | fail-fast: true 32 | matrix: 33 | include: 34 | - os: windows-latest 35 | target: x86_64-pc-windows-msvc 36 | - os: macos-latest 37 | target: x86_64-apple-darwin 38 | strip: strip -x # Must use -x on Mac OS. This produces larger results on Linux. 39 | name: build-${{ matrix.target }} 40 | runs-on: ${{ matrix.os }} 41 | steps: 42 | - uses: actions/checkout@v4 43 | - name: Setup node 44 | uses: actions/setup-node@v4 45 | with: 46 | node-version: ${{ env.NODE_VERSION }} 47 | check-latest: true 48 | - uses: dtolnay/rust-toolchain@stable 49 | - name: Setup rust target 50 | run: rustup target add ${{ matrix.target }} 51 | - name: Install dependencies 52 | uses: ./.github/actions/yarn-install 53 | - name: Build release 54 | run: yarn build 55 | shell: bash 56 | - name: Strip debug symbols 57 | if: ${{ matrix.strip }} 58 | run: ${{ matrix.strip }} *.node 59 | - name: Upload artifact 60 | uses: actions/upload-artifact@v4 61 | with: 62 | name: bindings-${{ matrix.target }} 63 | path: ${{ env.APP_NAME }}.*.node 64 | if-no-files-found: error 65 | 66 | build-apple-silicon: 67 | name: build-apple-silicon 68 | runs-on: macos-latest 69 | steps: 70 | - uses: actions/checkout@v4 71 | - name: Setup node 72 | uses: actions/setup-node@v4 73 | with: 74 | node-version: ${{ env.NODE_VERSION }} 75 | check-latest: true 76 | - uses: dtolnay/rust-toolchain@stable 77 | - name: Setup rust target 78 | run: rustup target add aarch64-apple-darwin 79 | - name: Install dependencies 80 | uses: ./.github/actions/yarn-install 81 | - name: Build release 82 | run: | 83 | sudo rm -Rf /Library/Developer/CommandLineTools/SDKs/*; 84 | export CC=$(xcrun -f clang); 85 | export CXX=$(xcrun -f clang++); 86 | SYSROOT=$(xcrun --sdk macosx --show-sdk-path); 87 | export CFLAGS="-isysroot $SYSROOT -isystem $SYSROOT"; 88 | yarn build --target aarch64-apple-darwin 89 | shell: bash 90 | - name: Strip debug symbols 91 | run: strip -x *.node 92 | - name: Upload artifact 93 | uses: actions/upload-artifact@v4 94 | with: 95 | name: bindings-aarch64-apple-darwin 96 | path: ${{ env.APP_NAME }}.*.node 97 | if-no-files-found: error 98 | 99 | build-linux: 100 | strategy: 101 | fail-fast: false 102 | matrix: 103 | include: 104 | - target: x86_64-unknown-linux-gnu 105 | strip: strip 106 | image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian 107 | - target: x86_64-unknown-linux-musl 108 | strip: strip 109 | setup: apk add perl 110 | image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine 111 | - target: aarch64-unknown-linux-musl 112 | strip: aarch64-linux-musl-strip 113 | setup: apk add perl 114 | image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine 115 | # Currently broken images 116 | # 117 | # - target: aarch64-unknown-linux-gnu 118 | # strip: aarch64-linux-gnu-strip 119 | # image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian-aarch64 120 | # - target: armv7-unknown-linux-gnueabihf 121 | # strip: arm-linux-gnueabihf-strip 122 | # image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian 123 | # setup: sudo apt-get update && sudo apt-get install gcc-arm-linux-gnueabihf -y 124 | name: build-${{ matrix.target }} 125 | runs-on: ubuntu-latest 126 | container: ${{ matrix.image }} 127 | steps: 128 | - uses: actions/checkout@v4 129 | - name: Setup node 130 | uses: actions/setup-node@v4 131 | with: 132 | node-version: ${{ env.NODE_VERSION }} 133 | check-latest: true 134 | - uses: dtolnay/rust-toolchain@stable 135 | - uses: goto-bus-stop/setup-zig@v2 136 | if: ${{ matrix.target == 'armv7-unknown-linux-gnueabihf' }} 137 | with: 138 | version: 0.10.0 139 | - name: Setup cross compile toolchain 140 | if: ${{ matrix.setup }} 141 | run: ${{ matrix.setup }} 142 | shell: bash 143 | - name: Setup rust target 144 | run: rustup target add ${{ matrix.target }} 145 | - name: Install dependencies 146 | uses: ./.github/actions/yarn-install 147 | - name: Build release 148 | run: yarn build --target ${{ matrix.target }} 149 | shell: bash 150 | - name: Strip debug symbols 151 | if: ${{ matrix.strip }} 152 | run: ${{ matrix.strip }} *.node 153 | - name: Upload artifact 154 | uses: actions/upload-artifact@v4 155 | with: 156 | name: bindings-${{ matrix.target }} 157 | path: ${{ env.APP_NAME }}.*.node 158 | if-no-files-found: error 159 | 160 | publish: 161 | name: Publish 162 | runs-on: ubuntu-latest 163 | needs: 164 | - build 165 | - build-apple-silicon 166 | - build-linux 167 | steps: 168 | - uses: actions/checkout@v4 169 | - name: Setup node 170 | uses: actions/setup-node@v4 171 | with: 172 | node-version: ${{ env.NODE_VERSION }} 173 | check-latest: true 174 | - name: Install dependencies 175 | uses: ./.github/actions/yarn-install 176 | - name: Download all artifacts 177 | uses: actions/download-artifact@v4 178 | with: 179 | path: artifacts 180 | - name: Move artifacts 181 | run: yarn artifacts 182 | - name: List packages 183 | run: ls -R ./npm 184 | shell: bash 185 | - name: Publish 186 | run: | 187 | if git log -1 --pretty=%B | grep "^[0-9]\+\.[0-9]\+\.[0-9]\+$"; 188 | then 189 | echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc 190 | npm publish --access public 191 | elif git log -1 --pretty=%B | grep "^[0-9]\+\.[0-9]\+\.[0-9]\+"; 192 | then 193 | echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc 194 | npm publish --tag next --access public 195 | else 196 | echo "Not a release, skipping publish" 197 | fi 198 | env: 199 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 200 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 201 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - main 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | RUSTFLAGS: -D warnings 12 | 13 | concurrency: 14 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 15 | cancel-in-progress: true 16 | 17 | jobs: 18 | fmt-clippy: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v4 22 | - uses: dtolnay/rust-toolchain@stable 23 | - name: rustfmt 24 | run: cargo fmt --all -- --check 25 | - name: Run Clippy 26 | run: cargo clippy --all-targets --all-features 27 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - main 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | RUST_BACKTRACE: full 12 | RUSTFLAGS: -D warnings 13 | 14 | concurrency: 15 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 16 | cancel-in-progress: true 17 | 18 | jobs: 19 | test-rust: 20 | name: Unit Tests - Rust 21 | runs-on: ubuntu-latest 22 | env: 23 | CARGO_TERM_COLOR: always 24 | RUST_BACKTRACE: full 25 | RUSTFLAGS: -D warnings 26 | steps: 27 | - uses: actions/checkout@v4 28 | - uses: dtolnay/rust-toolchain@stable 29 | - uses: Swatinem/rust-cache@v2 30 | - run: cargo test --all-features 31 | test-js: 32 | name: Unit Tests - Node ${{ matrix.node }} 33 | strategy: 34 | fail-fast: false 35 | matrix: 36 | node: 37 | - "18" 38 | - "20" 39 | runs-on: ubuntu-latest 40 | steps: 41 | - uses: actions/checkout@v4 42 | - name: Setup node 43 | uses: actions/setup-node@v4 44 | with: 45 | node-version: ${{ matrix.node }} 46 | check-latest: true 47 | - name: Install dependencies 48 | uses: ./.github/actions/yarn-install 49 | - uses: dtolnay/rust-toolchain@stable 50 | - uses: Swatinem/rust-cache@v2 51 | - name: Build 52 | run: yarn build 53 | - name: Run Vitest 54 | run: yarn test 55 | env: 56 | GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/node 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=node 4 | 5 | ### Node ### 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # TypeScript v1 declaration files 50 | typings/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Microbundle cache 62 | .rpt2_cache/ 63 | .rts2_cache_cjs/ 64 | .rts2_cache_es/ 65 | .rts2_cache_umd/ 66 | 67 | # Optional REPL history 68 | .node_repl_history 69 | 70 | # Output of 'npm pack' 71 | *.tgz 72 | 73 | # Yarn Integrity file 74 | .yarn-integrity 75 | 76 | # dotenv environment variables file 77 | .env 78 | .env.test 79 | 80 | # parcel-bundler cache (https://parceljs.org/) 81 | .cache 82 | 83 | # Next.js build output 84 | .next 85 | 86 | # Nuxt.js build / generate output 87 | .nuxt 88 | dist 89 | 90 | # Gatsby files 91 | .cache/ 92 | # Comment in the public line in if your project uses Gatsby and not Next.js 93 | # https://nextjs.org/blog/next-9-1#public-directory-support 94 | # public 95 | 96 | # vuepress build output 97 | .vuepress/dist 98 | 99 | # Serverless directories 100 | .serverless/ 101 | 102 | # FuseBox cache 103 | .fusebox/ 104 | 105 | # DynamoDB Local files 106 | .dynamodb/ 107 | 108 | # TernJS port file 109 | .tern-port 110 | 111 | # Stores VSCode versions used for testing VSCode extensions 112 | .vscode-test 113 | 114 | # End of https://www.toptal.com/developers/gitignore/api/node 115 | 116 | 117 | #Added by cargo 118 | 119 | /target 120 | Cargo.lock 121 | 122 | *.node 123 | .env 124 | .env.* 125 | !.env.example 126 | output 127 | 128 | # Yarn Berry 129 | .pnp.* 130 | .yarn/* 131 | !.yarn/patches 132 | !.yarn/plugins 133 | !.yarn/releases 134 | !.yarn/sdks 135 | !.yarn/versions -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/node 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=node 4 | 5 | ### Node ### 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # TypeScript v1 declaration files 50 | typings/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Microbundle cache 62 | .rpt2_cache/ 63 | .rts2_cache_cjs/ 64 | .rts2_cache_es/ 65 | .rts2_cache_umd/ 66 | 67 | # Optional REPL history 68 | .node_repl_history 69 | 70 | # Output of 'npm pack' 71 | *.tgz 72 | 73 | # Yarn Integrity file 74 | .yarn-integrity 75 | 76 | # dotenv environment variables file 77 | .env 78 | .env.test 79 | 80 | # parcel-bundler cache (https://parceljs.org/) 81 | .cache 82 | 83 | # Next.js build output 84 | .next 85 | 86 | # Nuxt.js build / generate output 87 | .nuxt 88 | dist 89 | 90 | # Gatsby files 91 | .cache/ 92 | # Comment in the public line in if your project uses Gatsby and not Next.js 93 | # https://nextjs.org/blog/next-9-1#public-directory-support 94 | # public 95 | 96 | # vuepress build output 97 | .vuepress/dist 98 | 99 | # Serverless directories 100 | .serverless/ 101 | 102 | # FuseBox cache 103 | .fusebox/ 104 | 105 | # DynamoDB Local files 106 | .dynamodb/ 107 | 108 | # TernJS port file 109 | .tern-port 110 | 111 | # Stores VSCode versions used for testing VSCode extensions 112 | .vscode-test 113 | 114 | # End of https://www.toptal.com/developers/gitignore/api/node 115 | 116 | 117 | #Added by cargo 118 | 119 | /target 120 | Cargo.lock 121 | 122 | *.node 123 | .env 124 | .env.* 125 | !.env.example 126 | output 127 | 128 | # Yarn Berry 129 | .pnp.* 130 | .yarn/* 131 | 132 | npm 133 | src 134 | build.rs 135 | index.js -------------------------------------------------------------------------------- /.yarn/plugins/@yarnpkg/plugin-typescript.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | //prettier-ignore 3 | module.exports = { 4 | name: "@yarnpkg/plugin-typescript", 5 | factory: function (require) { 6 | var plugin=(()=>{var Ft=Object.create,H=Object.defineProperty,Bt=Object.defineProperties,Kt=Object.getOwnPropertyDescriptor,zt=Object.getOwnPropertyDescriptors,Gt=Object.getOwnPropertyNames,Q=Object.getOwnPropertySymbols,$t=Object.getPrototypeOf,ne=Object.prototype.hasOwnProperty,De=Object.prototype.propertyIsEnumerable;var Re=(e,t,r)=>t in e?H(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,u=(e,t)=>{for(var r in t||(t={}))ne.call(t,r)&&Re(e,r,t[r]);if(Q)for(var r of Q(t))De.call(t,r)&&Re(e,r,t[r]);return e},g=(e,t)=>Bt(e,zt(t)),Lt=e=>H(e,"__esModule",{value:!0});var R=(e,t)=>{var r={};for(var s in e)ne.call(e,s)&&t.indexOf(s)<0&&(r[s]=e[s]);if(e!=null&&Q)for(var s of Q(e))t.indexOf(s)<0&&De.call(e,s)&&(r[s]=e[s]);return r};var I=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Vt=(e,t)=>{for(var r in t)H(e,r,{get:t[r],enumerable:!0})},Qt=(e,t,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Gt(t))!ne.call(e,s)&&s!=="default"&&H(e,s,{get:()=>t[s],enumerable:!(r=Kt(t,s))||r.enumerable});return e},C=e=>Qt(Lt(H(e!=null?Ft($t(e)):{},"default",e&&e.__esModule&&"default"in e?{get:()=>e.default,enumerable:!0}:{value:e,enumerable:!0})),e);var xe=I(J=>{"use strict";Object.defineProperty(J,"__esModule",{value:!0});function _(e){let t=[...e.caches],r=t.shift();return r===void 0?ve():{get(s,n,a={miss:()=>Promise.resolve()}){return r.get(s,n,a).catch(()=>_({caches:t}).get(s,n,a))},set(s,n){return r.set(s,n).catch(()=>_({caches:t}).set(s,n))},delete(s){return r.delete(s).catch(()=>_({caches:t}).delete(s))},clear(){return r.clear().catch(()=>_({caches:t}).clear())}}}function ve(){return{get(e,t,r={miss:()=>Promise.resolve()}){return t().then(n=>Promise.all([n,r.miss(n)])).then(([n])=>n)},set(e,t){return Promise.resolve(t)},delete(e){return Promise.resolve()},clear(){return Promise.resolve()}}}J.createFallbackableCache=_;J.createNullCache=ve});var Ee=I(($s,qe)=>{qe.exports=xe()});var Te=I(ae=>{"use strict";Object.defineProperty(ae,"__esModule",{value:!0});function Jt(e={serializable:!0}){let t={};return{get(r,s,n={miss:()=>Promise.resolve()}){let a=JSON.stringify(r);if(a in t)return Promise.resolve(e.serializable?JSON.parse(t[a]):t[a]);let o=s(),d=n&&n.miss||(()=>Promise.resolve());return o.then(y=>d(y)).then(()=>o)},set(r,s){return t[JSON.stringify(r)]=e.serializable?JSON.stringify(s):s,Promise.resolve(s)},delete(r){return delete t[JSON.stringify(r)],Promise.resolve()},clear(){return t={},Promise.resolve()}}}ae.createInMemoryCache=Jt});var we=I((Vs,Me)=>{Me.exports=Te()});var Ce=I(M=>{"use strict";Object.defineProperty(M,"__esModule",{value:!0});function Xt(e,t,r){let s={"x-algolia-api-key":r,"x-algolia-application-id":t};return{headers(){return e===oe.WithinHeaders?s:{}},queryParameters(){return e===oe.WithinQueryParameters?s:{}}}}function Yt(e){let t=0,r=()=>(t++,new Promise(s=>{setTimeout(()=>{s(e(r))},Math.min(100*t,1e3))}));return e(r)}function ke(e,t=(r,s)=>Promise.resolve()){return Object.assign(e,{wait(r){return ke(e.then(s=>Promise.all([t(s,r),s])).then(s=>s[1]))}})}function Zt(e){let t=e.length-1;for(t;t>0;t--){let r=Math.floor(Math.random()*(t+1)),s=e[t];e[t]=e[r],e[r]=s}return e}function er(e,t){return Object.keys(t!==void 0?t:{}).forEach(r=>{e[r]=t[r](e)}),e}function tr(e,...t){let r=0;return e.replace(/%s/g,()=>encodeURIComponent(t[r++]))}var rr="4.2.0",sr=e=>()=>e.transporter.requester.destroy(),oe={WithinQueryParameters:0,WithinHeaders:1};M.AuthMode=oe;M.addMethods=er;M.createAuth=Xt;M.createRetryablePromise=Yt;M.createWaitablePromise=ke;M.destroy=sr;M.encode=tr;M.shuffle=Zt;M.version=rr});var F=I((Js,Ue)=>{Ue.exports=Ce()});var Ne=I(ie=>{"use strict";Object.defineProperty(ie,"__esModule",{value:!0});var nr={Delete:"DELETE",Get:"GET",Post:"POST",Put:"PUT"};ie.MethodEnum=nr});var B=I((Ys,We)=>{We.exports=Ne()});var Ze=I(A=>{"use strict";Object.defineProperty(A,"__esModule",{value:!0});var He=B();function ce(e,t){let r=e||{},s=r.data||{};return Object.keys(r).forEach(n=>{["timeout","headers","queryParameters","data","cacheable"].indexOf(n)===-1&&(s[n]=r[n])}),{data:Object.entries(s).length>0?s:void 0,timeout:r.timeout||t,headers:r.headers||{},queryParameters:r.queryParameters||{},cacheable:r.cacheable}}var X={Read:1,Write:2,Any:3},U={Up:1,Down:2,Timeouted:3},_e=2*60*1e3;function ue(e,t=U.Up){return g(u({},e),{status:t,lastUpdate:Date.now()})}function Fe(e){return e.status===U.Up||Date.now()-e.lastUpdate>_e}function Be(e){return e.status===U.Timeouted&&Date.now()-e.lastUpdate<=_e}function le(e){return{protocol:e.protocol||"https",url:e.url,accept:e.accept||X.Any}}function ar(e,t){return Promise.all(t.map(r=>e.get(r,()=>Promise.resolve(ue(r))))).then(r=>{let s=r.filter(d=>Fe(d)),n=r.filter(d=>Be(d)),a=[...s,...n],o=a.length>0?a.map(d=>le(d)):t;return{getTimeout(d,y){return(n.length===0&&d===0?1:n.length+3+d)*y},statelessHosts:o}})}var or=({isTimedOut:e,status:t})=>!e&&~~t==0,ir=e=>{let t=e.status;return e.isTimedOut||or(e)||~~(t/100)!=2&&~~(t/100)!=4},cr=({status:e})=>~~(e/100)==2,ur=(e,t)=>ir(e)?t.onRetry(e):cr(e)?t.onSucess(e):t.onFail(e);function Qe(e,t,r,s){let n=[],a=$e(r,s),o=Le(e,s),d=r.method,y=r.method!==He.MethodEnum.Get?{}:u(u({},r.data),s.data),b=u(u(u({"x-algolia-agent":e.userAgent.value},e.queryParameters),y),s.queryParameters),f=0,p=(h,S)=>{let O=h.pop();if(O===void 0)throw Ve(de(n));let P={data:a,headers:o,method:d,url:Ge(O,r.path,b),connectTimeout:S(f,e.timeouts.connect),responseTimeout:S(f,s.timeout)},x=j=>{let T={request:P,response:j,host:O,triesLeft:h.length};return n.push(T),T},v={onSucess:j=>Ke(j),onRetry(j){let T=x(j);return j.isTimedOut&&f++,Promise.all([e.logger.info("Retryable failure",pe(T)),e.hostsCache.set(O,ue(O,j.isTimedOut?U.Timeouted:U.Down))]).then(()=>p(h,S))},onFail(j){throw x(j),ze(j,de(n))}};return e.requester.send(P).then(j=>ur(j,v))};return ar(e.hostsCache,t).then(h=>p([...h.statelessHosts].reverse(),h.getTimeout))}function lr(e){let{hostsCache:t,logger:r,requester:s,requestsCache:n,responsesCache:a,timeouts:o,userAgent:d,hosts:y,queryParameters:b,headers:f}=e,p={hostsCache:t,logger:r,requester:s,requestsCache:n,responsesCache:a,timeouts:o,userAgent:d,headers:f,queryParameters:b,hosts:y.map(h=>le(h)),read(h,S){let O=ce(S,p.timeouts.read),P=()=>Qe(p,p.hosts.filter(j=>(j.accept&X.Read)!=0),h,O);if((O.cacheable!==void 0?O.cacheable:h.cacheable)!==!0)return P();let v={request:h,mappedRequestOptions:O,transporter:{queryParameters:p.queryParameters,headers:p.headers}};return p.responsesCache.get(v,()=>p.requestsCache.get(v,()=>p.requestsCache.set(v,P()).then(j=>Promise.all([p.requestsCache.delete(v),j]),j=>Promise.all([p.requestsCache.delete(v),Promise.reject(j)])).then(([j,T])=>T)),{miss:j=>p.responsesCache.set(v,j)})},write(h,S){return Qe(p,p.hosts.filter(O=>(O.accept&X.Write)!=0),h,ce(S,p.timeouts.write))}};return p}function dr(e){let t={value:`Algolia for JavaScript (${e})`,add(r){let s=`; ${r.segment}${r.version!==void 0?` (${r.version})`:""}`;return t.value.indexOf(s)===-1&&(t.value=`${t.value}${s}`),t}};return t}function Ke(e){try{return JSON.parse(e.content)}catch(t){throw Je(t.message,e)}}function ze({content:e,status:t},r){let s=e;try{s=JSON.parse(e).message}catch(n){}return Xe(s,t,r)}function pr(e,...t){let r=0;return e.replace(/%s/g,()=>encodeURIComponent(t[r++]))}function Ge(e,t,r){let s=Ye(r),n=`${e.protocol}://${e.url}/${t.charAt(0)==="/"?t.substr(1):t}`;return s.length&&(n+=`?${s}`),n}function Ye(e){let t=r=>Object.prototype.toString.call(r)==="[object Object]"||Object.prototype.toString.call(r)==="[object Array]";return Object.keys(e).map(r=>pr("%s=%s",r,t(e[r])?JSON.stringify(e[r]):e[r])).join("&")}function $e(e,t){if(e.method===He.MethodEnum.Get||e.data===void 0&&t.data===void 0)return;let r=Array.isArray(e.data)?e.data:u(u({},e.data),t.data);return JSON.stringify(r)}function Le(e,t){let r=u(u({},e.headers),t.headers),s={};return Object.keys(r).forEach(n=>{let a=r[n];s[n.toLowerCase()]=a}),s}function de(e){return e.map(t=>pe(t))}function pe(e){let t=e.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return g(u({},e),{request:g(u({},e.request),{headers:u(u({},e.request.headers),t)})})}function Xe(e,t,r){return{name:"ApiError",message:e,status:t,transporterStackTrace:r}}function Je(e,t){return{name:"DeserializationError",message:e,response:t}}function Ve(e){return{name:"RetryError",message:"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.",transporterStackTrace:e}}A.CallEnum=X;A.HostStatusEnum=U;A.createApiError=Xe;A.createDeserializationError=Je;A.createMappedRequestOptions=ce;A.createRetryError=Ve;A.createStatefulHost=ue;A.createStatelessHost=le;A.createTransporter=lr;A.createUserAgent=dr;A.deserializeFailure=ze;A.deserializeSuccess=Ke;A.isStatefulHostTimeouted=Be;A.isStatefulHostUp=Fe;A.serializeData=$e;A.serializeHeaders=Le;A.serializeQueryParameters=Ye;A.serializeUrl=Ge;A.stackFrameWithoutCredentials=pe;A.stackTraceWithoutCredentials=de});var K=I((en,et)=>{et.exports=Ze()});var tt=I(w=>{"use strict";Object.defineProperty(w,"__esModule",{value:!0});var N=F(),mr=K(),z=B(),hr=e=>{let t=e.region||"us",r=N.createAuth(N.AuthMode.WithinHeaders,e.appId,e.apiKey),s=mr.createTransporter(g(u({hosts:[{url:`analytics.${t}.algolia.com`}]},e),{headers:u(g(u({},r.headers()),{"content-type":"application/json"}),e.headers),queryParameters:u(u({},r.queryParameters()),e.queryParameters)})),n=e.appId;return N.addMethods({appId:n,transporter:s},e.methods)},yr=e=>(t,r)=>e.transporter.write({method:z.MethodEnum.Post,path:"2/abtests",data:t},r),gr=e=>(t,r)=>e.transporter.write({method:z.MethodEnum.Delete,path:N.encode("2/abtests/%s",t)},r),fr=e=>(t,r)=>e.transporter.read({method:z.MethodEnum.Get,path:N.encode("2/abtests/%s",t)},r),br=e=>t=>e.transporter.read({method:z.MethodEnum.Get,path:"2/abtests"},t),Pr=e=>(t,r)=>e.transporter.write({method:z.MethodEnum.Post,path:N.encode("2/abtests/%s/stop",t)},r);w.addABTest=yr;w.createAnalyticsClient=hr;w.deleteABTest=gr;w.getABTest=fr;w.getABTests=br;w.stopABTest=Pr});var st=I((rn,rt)=>{rt.exports=tt()});var at=I(G=>{"use strict";Object.defineProperty(G,"__esModule",{value:!0});var me=F(),jr=K(),nt=B(),Or=e=>{let t=e.region||"us",r=me.createAuth(me.AuthMode.WithinHeaders,e.appId,e.apiKey),s=jr.createTransporter(g(u({hosts:[{url:`recommendation.${t}.algolia.com`}]},e),{headers:u(g(u({},r.headers()),{"content-type":"application/json"}),e.headers),queryParameters:u(u({},r.queryParameters()),e.queryParameters)}));return me.addMethods({appId:e.appId,transporter:s},e.methods)},Ir=e=>t=>e.transporter.read({method:nt.MethodEnum.Get,path:"1/strategies/personalization"},t),Ar=e=>(t,r)=>e.transporter.write({method:nt.MethodEnum.Post,path:"1/strategies/personalization",data:t},r);G.createRecommendationClient=Or;G.getPersonalizationStrategy=Ir;G.setPersonalizationStrategy=Ar});var it=I((nn,ot)=>{ot.exports=at()});var jt=I(i=>{"use strict";Object.defineProperty(i,"__esModule",{value:!0});var l=F(),q=K(),m=B(),Sr=require("crypto");function Y(e){let t=r=>e.request(r).then(s=>{if(e.batch!==void 0&&e.batch(s.hits),!e.shouldStop(s))return s.cursor?t({cursor:s.cursor}):t({page:(r.page||0)+1})});return t({})}var Dr=e=>{let t=e.appId,r=l.createAuth(e.authMode!==void 0?e.authMode:l.AuthMode.WithinHeaders,t,e.apiKey),s=q.createTransporter(g(u({hosts:[{url:`${t}-dsn.algolia.net`,accept:q.CallEnum.Read},{url:`${t}.algolia.net`,accept:q.CallEnum.Write}].concat(l.shuffle([{url:`${t}-1.algolianet.com`},{url:`${t}-2.algolianet.com`},{url:`${t}-3.algolianet.com`}]))},e),{headers:u(g(u({},r.headers()),{"content-type":"application/x-www-form-urlencoded"}),e.headers),queryParameters:u(u({},r.queryParameters()),e.queryParameters)})),n={transporter:s,appId:t,addAlgoliaAgent(a,o){s.userAgent.add({segment:a,version:o})},clearCache(){return Promise.all([s.requestsCache.clear(),s.responsesCache.clear()]).then(()=>{})}};return l.addMethods(n,e.methods)};function ct(){return{name:"MissingObjectIDError",message:"All objects must have an unique objectID (like a primary key) to be valid. Algolia is also able to generate objectIDs automatically but *it's not recommended*. To do it, use the `{'autoGenerateObjectIDIfNotExist': true}` option."}}function ut(){return{name:"ObjectNotFoundError",message:"Object not found."}}function lt(){return{name:"ValidUntilNotFoundError",message:"ValidUntil not found in given secured api key."}}var Rr=e=>(t,r)=>{let d=r||{},{queryParameters:s}=d,n=R(d,["queryParameters"]),a=u({acl:t},s!==void 0?{queryParameters:s}:{}),o=(y,b)=>l.createRetryablePromise(f=>$(e)(y.key,b).catch(p=>{if(p.status!==404)throw p;return f()}));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:"1/keys",data:a},n),o)},vr=e=>(t,r,s)=>{let n=q.createMappedRequestOptions(s);return n.queryParameters["X-Algolia-User-ID"]=t,e.transporter.write({method:m.MethodEnum.Post,path:"1/clusters/mapping",data:{cluster:r}},n)},xr=e=>(t,r,s)=>e.transporter.write({method:m.MethodEnum.Post,path:"1/clusters/mapping/batch",data:{users:t,cluster:r}},s),Z=e=>(t,r,s)=>{let n=(a,o)=>L(e)(t,{methods:{waitTask:D}}).waitTask(a.taskID,o);return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/operation",t),data:{operation:"copy",destination:r}},s),n)},qr=e=>(t,r,s)=>Z(e)(t,r,g(u({},s),{scope:[ee.Rules]})),Er=e=>(t,r,s)=>Z(e)(t,r,g(u({},s),{scope:[ee.Settings]})),Tr=e=>(t,r,s)=>Z(e)(t,r,g(u({},s),{scope:[ee.Synonyms]})),Mr=e=>(t,r)=>{let s=(n,a)=>l.createRetryablePromise(o=>$(e)(t,a).then(o).catch(d=>{if(d.status!==404)throw d}));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Delete,path:l.encode("1/keys/%s",t)},r),s)},wr=()=>(e,t)=>{let r=q.serializeQueryParameters(t),s=Sr.createHmac("sha256",e).update(r).digest("hex");return Buffer.from(s+r).toString("base64")},$=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/keys/%s",t)},r),kr=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/logs"},t),Cr=()=>e=>{let t=Buffer.from(e,"base64").toString("ascii"),r=/validUntil=(\d+)/,s=t.match(r);if(s===null)throw lt();return parseInt(s[1],10)-Math.round(new Date().getTime()/1e3)},Ur=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/clusters/mapping/top"},t),Nr=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/clusters/mapping/%s",t)},r),Wr=e=>t=>{let n=t||{},{retrieveMappings:r}=n,s=R(n,["retrieveMappings"]);return r===!0&&(s.getClusters=!0),e.transporter.read({method:m.MethodEnum.Get,path:"1/clusters/mapping/pending"},s)},L=e=>(t,r={})=>{let s={transporter:e.transporter,appId:e.appId,indexName:t};return l.addMethods(s,r.methods)},Hr=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/keys"},t),_r=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/clusters"},t),Fr=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/indexes"},t),Br=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/clusters/mapping"},t),Kr=e=>(t,r,s)=>{let n=(a,o)=>L(e)(t,{methods:{waitTask:D}}).waitTask(a.taskID,o);return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/operation",t),data:{operation:"move",destination:r}},s),n)},zr=e=>(t,r)=>{let s=(n,a)=>Promise.all(Object.keys(n.taskID).map(o=>L(e)(o,{methods:{waitTask:D}}).waitTask(n.taskID[o],a)));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:"1/indexes/*/batch",data:{requests:t}},r),s)},Gr=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:"1/indexes/*/objects",data:{requests:t}},r),$r=e=>(t,r)=>{let s=t.map(n=>g(u({},n),{params:q.serializeQueryParameters(n.params||{})}));return e.transporter.read({method:m.MethodEnum.Post,path:"1/indexes/*/queries",data:{requests:s},cacheable:!0},r)},Lr=e=>(t,r)=>Promise.all(t.map(s=>{let d=s.params,{facetName:n,facetQuery:a}=d,o=R(d,["facetName","facetQuery"]);return L(e)(s.indexName,{methods:{searchForFacetValues:dt}}).searchForFacetValues(n,a,u(u({},r),o))})),Vr=e=>(t,r)=>{let s=q.createMappedRequestOptions(r);return s.queryParameters["X-Algolia-User-ID"]=t,e.transporter.write({method:m.MethodEnum.Delete,path:"1/clusters/mapping"},s)},Qr=e=>(t,r)=>{let s=(n,a)=>l.createRetryablePromise(o=>$(e)(t,a).catch(d=>{if(d.status!==404)throw d;return o()}));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/keys/%s/restore",t)},r),s)},Jr=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:"1/clusters/mapping/search",data:{query:t}},r),Xr=e=>(t,r)=>{let s=Object.assign({},r),f=r||{},{queryParameters:n}=f,a=R(f,["queryParameters"]),o=n?{queryParameters:n}:{},d=["acl","indexes","referers","restrictSources","queryParameters","description","maxQueriesPerIPPerHour","maxHitsPerQuery"],y=p=>Object.keys(s).filter(h=>d.indexOf(h)!==-1).every(h=>p[h]===s[h]),b=(p,h)=>l.createRetryablePromise(S=>$(e)(t,h).then(O=>y(O)?Promise.resolve():S()));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Put,path:l.encode("1/keys/%s",t),data:o},a),b)},pt=e=>(t,r)=>{let s=(n,a)=>D(e)(n.taskID,a);return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/batch",e.indexName),data:{requests:t}},r),s)},Yr=e=>t=>Y(g(u({},t),{shouldStop:r=>r.cursor===void 0,request:r=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/browse",e.indexName),data:r},t)})),Zr=e=>t=>{let r=u({hitsPerPage:1e3},t);return Y(g(u({},r),{shouldStop:s=>s.hits.lengthg(u({},n),{hits:n.hits.map(a=>(delete a._highlightResult,a))}))}}))},es=e=>t=>{let r=u({hitsPerPage:1e3},t);return Y(g(u({},r),{shouldStop:s=>s.hits.lengthg(u({},n),{hits:n.hits.map(a=>(delete a._highlightResult,a))}))}}))},te=e=>(t,r,s)=>{let y=s||{},{batchSize:n}=y,a=R(y,["batchSize"]),o={taskIDs:[],objectIDs:[]},d=(b=0)=>{let f=[],p;for(p=b;p({action:r,body:h})),a).then(h=>(o.objectIDs=o.objectIDs.concat(h.objectIDs),o.taskIDs.push(h.taskID),p++,d(p)))};return l.createWaitablePromise(d(),(b,f)=>Promise.all(b.taskIDs.map(p=>D(e)(p,f))))},ts=e=>t=>l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/clear",e.indexName)},t),(r,s)=>D(e)(r.taskID,s)),rs=e=>t=>{let a=t||{},{forwardToReplicas:r}=a,s=R(a,["forwardToReplicas"]),n=q.createMappedRequestOptions(s);return r&&(n.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/rules/clear",e.indexName)},n),(o,d)=>D(e)(o.taskID,d))},ss=e=>t=>{let a=t||{},{forwardToReplicas:r}=a,s=R(a,["forwardToReplicas"]),n=q.createMappedRequestOptions(s);return r&&(n.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/synonyms/clear",e.indexName)},n),(o,d)=>D(e)(o.taskID,d))},ns=e=>(t,r)=>l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/deleteByQuery",e.indexName),data:t},r),(s,n)=>D(e)(s.taskID,n)),as=e=>t=>l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Delete,path:l.encode("1/indexes/%s",e.indexName)},t),(r,s)=>D(e)(r.taskID,s)),os=e=>(t,r)=>l.createWaitablePromise(yt(e)([t],r).then(s=>({taskID:s.taskIDs[0]})),(s,n)=>D(e)(s.taskID,n)),yt=e=>(t,r)=>{let s=t.map(n=>({objectID:n}));return te(e)(s,k.DeleteObject,r)},is=e=>(t,r)=>{let o=r||{},{forwardToReplicas:s}=o,n=R(o,["forwardToReplicas"]),a=q.createMappedRequestOptions(n);return s&&(a.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Delete,path:l.encode("1/indexes/%s/rules/%s",e.indexName,t)},a),(d,y)=>D(e)(d.taskID,y))},cs=e=>(t,r)=>{let o=r||{},{forwardToReplicas:s}=o,n=R(o,["forwardToReplicas"]),a=q.createMappedRequestOptions(n);return s&&(a.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Delete,path:l.encode("1/indexes/%s/synonyms/%s",e.indexName,t)},a),(d,y)=>D(e)(d.taskID,y))},us=e=>t=>gt(e)(t).then(()=>!0).catch(r=>{if(r.status!==404)throw r;return!1}),ls=e=>(t,r)=>{let y=r||{},{query:s,paginate:n}=y,a=R(y,["query","paginate"]),o=0,d=()=>ft(e)(s||"",g(u({},a),{page:o})).then(b=>{for(let[f,p]of Object.entries(b.hits))if(t(p))return{object:p,position:parseInt(f,10),page:o};if(o++,n===!1||o>=b.nbPages)throw ut();return d()});return d()},ds=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/%s",e.indexName,t)},r),ps=()=>(e,t)=>{for(let[r,s]of Object.entries(e.hits))if(s.objectID===t)return parseInt(r,10);return-1},ms=e=>(t,r)=>{let o=r||{},{attributesToRetrieve:s}=o,n=R(o,["attributesToRetrieve"]),a=t.map(d=>u({indexName:e.indexName,objectID:d},s?{attributesToRetrieve:s}:{}));return e.transporter.read({method:m.MethodEnum.Post,path:"1/indexes/*/objects",data:{requests:a}},n)},hs=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/rules/%s",e.indexName,t)},r),gt=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/settings",e.indexName),data:{getVersion:2}},t),ys=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/synonyms/%s",e.indexName,t)},r),bt=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/task/%s",e.indexName,t.toString())},r),gs=e=>(t,r)=>l.createWaitablePromise(Pt(e)([t],r).then(s=>({objectID:s.objectIDs[0],taskID:s.taskIDs[0]})),(s,n)=>D(e)(s.taskID,n)),Pt=e=>(t,r)=>{let o=r||{},{createIfNotExists:s}=o,n=R(o,["createIfNotExists"]),a=s?k.PartialUpdateObject:k.PartialUpdateObjectNoCreate;return te(e)(t,a,n)},fs=e=>(t,r)=>{let O=r||{},{safe:s,autoGenerateObjectIDIfNotExist:n,batchSize:a}=O,o=R(O,["safe","autoGenerateObjectIDIfNotExist","batchSize"]),d=(P,x,v,j)=>l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/operation",P),data:{operation:v,destination:x}},j),(T,V)=>D(e)(T.taskID,V)),y=Math.random().toString(36).substring(7),b=`${e.indexName}_tmp_${y}`,f=he({appId:e.appId,transporter:e.transporter,indexName:b}),p=[],h=d(e.indexName,b,"copy",g(u({},o),{scope:["settings","synonyms","rules"]}));p.push(h);let S=(s?h.wait(o):h).then(()=>{let P=f(t,g(u({},o),{autoGenerateObjectIDIfNotExist:n,batchSize:a}));return p.push(P),s?P.wait(o):P}).then(()=>{let P=d(b,e.indexName,"move",o);return p.push(P),s?P.wait(o):P}).then(()=>Promise.all(p)).then(([P,x,v])=>({objectIDs:x.objectIDs,taskIDs:[P.taskID,...x.taskIDs,v.taskID]}));return l.createWaitablePromise(S,(P,x)=>Promise.all(p.map(v=>v.wait(x))))},bs=e=>(t,r)=>ye(e)(t,g(u({},r),{clearExistingRules:!0})),Ps=e=>(t,r)=>ge(e)(t,g(u({},r),{replaceExistingSynonyms:!0})),js=e=>(t,r)=>l.createWaitablePromise(he(e)([t],r).then(s=>({objectID:s.objectIDs[0],taskID:s.taskIDs[0]})),(s,n)=>D(e)(s.taskID,n)),he=e=>(t,r)=>{let o=r||{},{autoGenerateObjectIDIfNotExist:s}=o,n=R(o,["autoGenerateObjectIDIfNotExist"]),a=s?k.AddObject:k.UpdateObject;if(a===k.UpdateObject){for(let d of t)if(d.objectID===void 0)return l.createWaitablePromise(Promise.reject(ct()))}return te(e)(t,a,n)},Os=e=>(t,r)=>ye(e)([t],r),ye=e=>(t,r)=>{let d=r||{},{forwardToReplicas:s,clearExistingRules:n}=d,a=R(d,["forwardToReplicas","clearExistingRules"]),o=q.createMappedRequestOptions(a);return s&&(o.queryParameters.forwardToReplicas=1),n&&(o.queryParameters.clearExistingRules=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/rules/batch",e.indexName),data:t},o),(y,b)=>D(e)(y.taskID,b))},Is=e=>(t,r)=>ge(e)([t],r),ge=e=>(t,r)=>{let d=r||{},{forwardToReplicas:s,replaceExistingSynonyms:n}=d,a=R(d,["forwardToReplicas","replaceExistingSynonyms"]),o=q.createMappedRequestOptions(a);return s&&(o.queryParameters.forwardToReplicas=1),n&&(o.queryParameters.replaceExistingSynonyms=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/synonyms/batch",e.indexName),data:t},o),(y,b)=>D(e)(y.taskID,b))},ft=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/query",e.indexName),data:{query:t},cacheable:!0},r),dt=e=>(t,r,s)=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/facets/%s/query",e.indexName,t),data:{facetQuery:r},cacheable:!0},s),mt=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/rules/search",e.indexName),data:{query:t}},r),ht=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/synonyms/search",e.indexName),data:{query:t}},r),As=e=>(t,r)=>{let o=r||{},{forwardToReplicas:s}=o,n=R(o,["forwardToReplicas"]),a=q.createMappedRequestOptions(n);return s&&(a.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Put,path:l.encode("1/indexes/%s/settings",e.indexName),data:t},a),(d,y)=>D(e)(d.taskID,y))},D=e=>(t,r)=>l.createRetryablePromise(s=>bt(e)(t,r).then(n=>n.status!=="published"?s():void 0)),Ss={AddObject:"addObject",Analytics:"analytics",Browser:"browse",DeleteIndex:"deleteIndex",DeleteObject:"deleteObject",EditSettings:"editSettings",ListIndexes:"listIndexes",Logs:"logs",Recommendation:"recommendation",Search:"search",SeeUnretrievableAttributes:"seeUnretrievableAttributes",Settings:"settings",Usage:"usage"},k={AddObject:"addObject",UpdateObject:"updateObject",PartialUpdateObject:"partialUpdateObject",PartialUpdateObjectNoCreate:"partialUpdateObjectNoCreate",DeleteObject:"deleteObject"},ee={Settings:"settings",Synonyms:"synonyms",Rules:"rules"},Ds={None:"none",StopIfEnoughMatches:"stopIfEnoughMatches"},Rs={Synonym:"synonym",OneWaySynonym:"oneWaySynonym",AltCorrection1:"altCorrection1",AltCorrection2:"altCorrection2",Placeholder:"placeholder"};i.ApiKeyACLEnum=Ss;i.BatchActionEnum=k;i.ScopeEnum=ee;i.StrategyEnum=Ds;i.SynonymEnum=Rs;i.addApiKey=Rr;i.assignUserID=vr;i.assignUserIDs=xr;i.batch=pt;i.browseObjects=Yr;i.browseRules=Zr;i.browseSynonyms=es;i.chunkedBatch=te;i.clearObjects=ts;i.clearRules=rs;i.clearSynonyms=ss;i.copyIndex=Z;i.copyRules=qr;i.copySettings=Er;i.copySynonyms=Tr;i.createBrowsablePromise=Y;i.createMissingObjectIDError=ct;i.createObjectNotFoundError=ut;i.createSearchClient=Dr;i.createValidUntilNotFoundError=lt;i.deleteApiKey=Mr;i.deleteBy=ns;i.deleteIndex=as;i.deleteObject=os;i.deleteObjects=yt;i.deleteRule=is;i.deleteSynonym=cs;i.exists=us;i.findObject=ls;i.generateSecuredApiKey=wr;i.getApiKey=$;i.getLogs=kr;i.getObject=ds;i.getObjectPosition=ps;i.getObjects=ms;i.getRule=hs;i.getSecuredApiKeyRemainingValidity=Cr;i.getSettings=gt;i.getSynonym=ys;i.getTask=bt;i.getTopUserIDs=Ur;i.getUserID=Nr;i.hasPendingMappings=Wr;i.initIndex=L;i.listApiKeys=Hr;i.listClusters=_r;i.listIndices=Fr;i.listUserIDs=Br;i.moveIndex=Kr;i.multipleBatch=zr;i.multipleGetObjects=Gr;i.multipleQueries=$r;i.multipleSearchForFacetValues=Lr;i.partialUpdateObject=gs;i.partialUpdateObjects=Pt;i.removeUserID=Vr;i.replaceAllObjects=fs;i.replaceAllRules=bs;i.replaceAllSynonyms=Ps;i.restoreApiKey=Qr;i.saveObject=js;i.saveObjects=he;i.saveRule=Os;i.saveRules=ye;i.saveSynonym=Is;i.saveSynonyms=ge;i.search=ft;i.searchForFacetValues=dt;i.searchRules=mt;i.searchSynonyms=ht;i.searchUserIDs=Jr;i.setSettings=As;i.updateApiKey=Xr;i.waitTask=D});var It=I((on,Ot)=>{Ot.exports=jt()});var At=I(re=>{"use strict";Object.defineProperty(re,"__esModule",{value:!0});function vs(){return{debug(e,t){return Promise.resolve()},info(e,t){return Promise.resolve()},error(e,t){return Promise.resolve()}}}var xs={Debug:1,Info:2,Error:3};re.LogLevelEnum=xs;re.createNullLogger=vs});var Dt=I((un,St)=>{St.exports=At()});var xt=I(fe=>{"use strict";Object.defineProperty(fe,"__esModule",{value:!0});var Rt=require("http"),vt=require("https"),qs=require("url");function Es(){let e={keepAlive:!0},t=new Rt.Agent(e),r=new vt.Agent(e);return{send(s){return new Promise(n=>{let a=qs.parse(s.url),o=a.query===null?a.pathname:`${a.pathname}?${a.query}`,d=u({agent:a.protocol==="https:"?r:t,hostname:a.hostname,path:o,method:s.method,headers:s.headers},a.port!==void 0?{port:a.port||""}:{}),y=(a.protocol==="https:"?vt:Rt).request(d,h=>{let S="";h.on("data",O=>S+=O),h.on("end",()=>{clearTimeout(f),clearTimeout(p),n({status:h.statusCode||0,content:S,isTimedOut:!1})})}),b=(h,S)=>setTimeout(()=>{y.abort(),n({status:0,content:S,isTimedOut:!0})},h*1e3),f=b(s.connectTimeout,"Connection timeout"),p;y.on("error",h=>{clearTimeout(f),clearTimeout(p),n({status:0,content:h.message,isTimedOut:!1})}),y.once("response",()=>{clearTimeout(f),p=b(s.responseTimeout,"Socket timeout")}),s.data!==void 0&&y.write(s.data),y.end()})},destroy(){return t.destroy(),r.destroy(),Promise.resolve()}}}fe.createNodeHttpRequester=Es});var Et=I((dn,qt)=>{qt.exports=xt()});var kt=I((pn,Tt)=>{"use strict";var Mt=Ee(),Ts=we(),W=st(),be=F(),Pe=it(),c=It(),Ms=Dt(),ws=Et(),ks=K();function wt(e,t,r){let s={appId:e,apiKey:t,timeouts:{connect:2,read:5,write:30},requester:ws.createNodeHttpRequester(),logger:Ms.createNullLogger(),responsesCache:Mt.createNullCache(),requestsCache:Mt.createNullCache(),hostsCache:Ts.createInMemoryCache(),userAgent:ks.createUserAgent(be.version).add({segment:"Node.js",version:process.versions.node})};return c.createSearchClient(g(u(u({},s),r),{methods:{search:c.multipleQueries,searchForFacetValues:c.multipleSearchForFacetValues,multipleBatch:c.multipleBatch,multipleGetObjects:c.multipleGetObjects,multipleQueries:c.multipleQueries,copyIndex:c.copyIndex,copySettings:c.copySettings,copyRules:c.copyRules,copySynonyms:c.copySynonyms,moveIndex:c.moveIndex,listIndices:c.listIndices,getLogs:c.getLogs,listClusters:c.listClusters,multipleSearchForFacetValues:c.multipleSearchForFacetValues,getApiKey:c.getApiKey,addApiKey:c.addApiKey,listApiKeys:c.listApiKeys,updateApiKey:c.updateApiKey,deleteApiKey:c.deleteApiKey,restoreApiKey:c.restoreApiKey,assignUserID:c.assignUserID,assignUserIDs:c.assignUserIDs,getUserID:c.getUserID,searchUserIDs:c.searchUserIDs,listUserIDs:c.listUserIDs,getTopUserIDs:c.getTopUserIDs,removeUserID:c.removeUserID,hasPendingMappings:c.hasPendingMappings,generateSecuredApiKey:c.generateSecuredApiKey,getSecuredApiKeyRemainingValidity:c.getSecuredApiKeyRemainingValidity,destroy:be.destroy,initIndex:n=>a=>c.initIndex(n)(a,{methods:{batch:c.batch,delete:c.deleteIndex,getObject:c.getObject,getObjects:c.getObjects,saveObject:c.saveObject,saveObjects:c.saveObjects,search:c.search,searchForFacetValues:c.searchForFacetValues,waitTask:c.waitTask,setSettings:c.setSettings,getSettings:c.getSettings,partialUpdateObject:c.partialUpdateObject,partialUpdateObjects:c.partialUpdateObjects,deleteObject:c.deleteObject,deleteObjects:c.deleteObjects,deleteBy:c.deleteBy,clearObjects:c.clearObjects,browseObjects:c.browseObjects,getObjectPosition:c.getObjectPosition,findObject:c.findObject,exists:c.exists,saveSynonym:c.saveSynonym,saveSynonyms:c.saveSynonyms,getSynonym:c.getSynonym,searchSynonyms:c.searchSynonyms,browseSynonyms:c.browseSynonyms,deleteSynonym:c.deleteSynonym,clearSynonyms:c.clearSynonyms,replaceAllObjects:c.replaceAllObjects,replaceAllSynonyms:c.replaceAllSynonyms,searchRules:c.searchRules,getRule:c.getRule,deleteRule:c.deleteRule,saveRule:c.saveRule,saveRules:c.saveRules,replaceAllRules:c.replaceAllRules,browseRules:c.browseRules,clearRules:c.clearRules}}),initAnalytics:()=>n=>W.createAnalyticsClient(g(u(u({},s),n),{methods:{addABTest:W.addABTest,getABTest:W.getABTest,getABTests:W.getABTests,stopABTest:W.stopABTest,deleteABTest:W.deleteABTest}})),initRecommendation:()=>n=>Pe.createRecommendationClient(g(u(u({},s),n),{methods:{getPersonalizationStrategy:Pe.getPersonalizationStrategy,setPersonalizationStrategy:Pe.setPersonalizationStrategy}}))}}))}wt.version=be.version;Tt.exports=wt});var Ut=I((mn,je)=>{var Ct=kt();je.exports=Ct;je.exports.default=Ct});var Ws={};Vt(Ws,{default:()=>Ks});var Oe=C(require("@yarnpkg/core")),E=C(require("@yarnpkg/core")),Ie=C(require("@yarnpkg/plugin-essentials")),Ht=C(require("semver"));var se=C(require("@yarnpkg/core")),Nt=C(Ut()),Cs="e8e1bd300d860104bb8c58453ffa1eb4",Us="OFCNCOG2CU",Wt=async(e,t)=>{var a;let r=se.structUtils.stringifyIdent(e),n=Ns(t).initIndex("npm-search");try{return((a=(await n.getObject(r,{attributesToRetrieve:["types"]})).types)==null?void 0:a.ts)==="definitely-typed"}catch(o){return!1}},Ns=e=>(0,Nt.default)(Us,Cs,{requester:{async send(r){try{let s=await se.httpUtils.request(r.url,r.data||null,{configuration:e,headers:r.headers});return{content:s.body,isTimedOut:!1,status:s.statusCode}}catch(s){return{content:s.response.body,isTimedOut:!1,status:s.response.statusCode}}}}});var _t=e=>e.scope?`${e.scope}__${e.name}`:`${e.name}`,Hs=async(e,t,r,s)=>{if(r.scope==="types")return;let{project:n}=e,{configuration:a}=n,o=a.makeResolver(),d={project:n,resolver:o,report:new E.ThrowReport};if(!await Wt(r,a))return;let b=_t(r),f=E.structUtils.parseRange(r.range).selector;if(!E.semverUtils.validRange(f)){let P=await o.getCandidates(r,new Map,d);f=E.structUtils.parseRange(P[0].reference).selector}let p=Ht.default.coerce(f);if(p===null)return;let h=`${Ie.suggestUtils.Modifier.CARET}${p.major}`,S=E.structUtils.makeDescriptor(E.structUtils.makeIdent("types",b),h),O=E.miscUtils.mapAndFind(n.workspaces,P=>{var T,V;let x=(T=P.manifest.dependencies.get(r.identHash))==null?void 0:T.descriptorHash,v=(V=P.manifest.devDependencies.get(r.identHash))==null?void 0:V.descriptorHash;if(x!==r.descriptorHash&&v!==r.descriptorHash)return E.miscUtils.mapAndFind.skip;let j=[];for(let Ae of Oe.Manifest.allDependencies){let Se=P.manifest[Ae].get(S.identHash);typeof Se!="undefined"&&j.push([Ae,Se])}return j.length===0?E.miscUtils.mapAndFind.skip:j});if(typeof O!="undefined")for(let[P,x]of O)e.manifest[P].set(x.identHash,x);else{try{if((await o.getCandidates(S,new Map,d)).length===0)return}catch{return}e.manifest[Ie.suggestUtils.Target.DEVELOPMENT].set(S.identHash,S)}},_s=async(e,t,r)=>{if(r.scope==="types")return;let s=_t(r),n=E.structUtils.makeIdent("types",s);for(let a of Oe.Manifest.allDependencies)typeof e.manifest[a].get(n.identHash)!="undefined"&&e.manifest[a].delete(n.identHash)},Fs=(e,t)=>{t.publishConfig&&t.publishConfig.typings&&(t.typings=t.publishConfig.typings),t.publishConfig&&t.publishConfig.types&&(t.types=t.publishConfig.types)},Bs={hooks:{afterWorkspaceDependencyAddition:Hs,afterWorkspaceDependencyRemoval:_s,beforeWorkspacePacking:Fs}},Ks=Bs;return Ws;})(); 7 | return plugin; 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | 3 | plugins: 4 | - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs 5 | spec: "@yarnpkg/plugin-interactive-tools" 6 | - path: .yarn/plugins/@yarnpkg/plugin-typescript.cjs 7 | spec: "@yarnpkg/plugin-typescript" 8 | 9 | yarnPath: .yarn/releases/yarn-3.3.1.cjs 10 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Development 4 | 5 | ### Build 6 | 7 | After `yarn build/npm run build` command, you can see `thanks-contributors.[darwin|win32|linux].node` file in project root. This is the native addon built from [lib.rs](./src/lib.rs). 8 | 9 | ### CI 10 | 11 | With GitHub actions, every commits and pull request will be built and tested automatically in [`node@14`, `@node16`] x [`macOS`, `Linux`, `Windows`] matrix. You will never be afraid of the native addon broken in these platforms. 12 | 13 | ### Release 14 | 15 | Release native package is very difficult in old days. Native packages may ask developers who use its to install `build toolchain` like `gcc/llvm` , `node-gyp` or something more. 16 | 17 | With `GitHub actions`, we can easily prebuild `binary` for major platforms. And with `N-API`, we should never afraid of **ABI Compatible**. 18 | 19 | The other problem is how to deliver prebuild `binary` to users. Download it in `postinstall` script is a common way which most packages do it right now. The problem of this solution is it introduced many other packages to download binary which has not been used by `runtime codes`. The other problem is some user may not easily download the binary from `GitHub/CDN` if they are behind private network (But in most case, they have a private NPM mirror). 20 | 21 | In this package we choose a better way to solve this problem. We release different `npm packages` for different platform. And add it to `optionalDependencies` before release the `Major` package to npm. 22 | 23 | `NPM` will choose which native package should download from `registry` automatically. You can see [npm](./npm) dir for details. And you can also run `yarn add @napi-rs/thanks-contributors` to see how it works. 24 | 25 | ### Develop requirements 26 | 27 | - Install latest `Rust` 28 | - Install `Node.js@14+` which fully supported `Node-API` 29 | - Install `yarn@1.x` 30 | 31 | ### Test in local 32 | 33 | - `yarn` 34 | - `yarn build:debug` 35 | - `node bin.js --help` 36 | 37 | ### Release package 38 | 39 | Ensure you have set you **NPM_TOKEN** in `GitHub` project setting. 40 | 41 | In `Settings -> Secrets`, add **NPM_TOKEN** into it. 42 | 43 | When you want release package: 44 | 45 | ``` 46 | npm version [ | major | minor | patch | premajor | preminor | prepatch | prerelease [--preid=] | from-git] 47 | 48 | git push 49 | ``` 50 | 51 | GitHub actions will do the rest job for you. 52 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | edition = "2021" 3 | name = "thanks-contributors" 4 | description = "This little script accesses GitHub's API to get all contributors and their PRs between two distinct points in the history of commits. This is helpful for changelogs where you'd want to list all contributions for that release (so e.g. changes between v1 and v1.1)." 5 | version = "0.0.0" 6 | 7 | [lib] 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | chrono = "0.4" 12 | clap = { version = "4", features = ["derive", "wrap_help"] } 13 | clap-verbosity-flag = "2.0.0" 14 | dotenv = "0.15" 15 | env_logger = "0.10.0" 16 | lazy_static = "1.4.0" 17 | log = "0.4" 18 | napi = { version = "2", features = ["napi8", "serde_json", "async"] } 19 | napi-derive = "2" 20 | regex = "1" 21 | reqwest = { version = "0.11", features = ["json", "native-tls-vendored"] } 22 | serde = { version = "1", features = ["derive"] } 23 | serde_json = "1" 24 | 25 | [build-dependencies] 26 | napi-build = "2" 27 | 28 | [profile.release] 29 | lto = true 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 LekoArts 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Thanks Contributors! 2 | 3 | This little script accesses GitHub's API to get all contributors and their PRs between two distinct points in the history of commits. This is helpful for changelogs where you'd want to list all contributions for that release (so e.g. changes between v1 and v1.1). 4 | 5 | ## Usage 6 | 7 | ```shell 8 | npx @lekoarts/thanks-contributors [OPTIONS] [OWNER] [REPO] 9 | ``` 10 | 11 | First, it get's the list of commits between `base...head` (equivalent to `git log 12 | base..head`), then parses their authors and creates a markdown list of each 13 | contributor and their contribution. 14 | 15 | ```shell 16 | Usage: @lekoarts/thanks-contributors [OPTIONS] [OWNER] [REPO] 17 | 18 | Arguments: 19 | 20 | Pointer from where to start looking for changes 21 | 22 | 23 | Pointer until where to stop looking for changes 24 | 25 | [OWNER] 26 | Name of the owner/user/organization of the repository 27 | 28 | [default: gatsbyjs] 29 | 30 | [REPO] 31 | Name of the repository 32 | 33 | [default: gatsby] 34 | 35 | Options: 36 | -i, --include-org-members 37 | Include organization members into the list [default: false] 38 | 39 | [possible values: true, false] 40 | 41 | -e, --excludes ... 42 | List of members to exclude from the list. Usage: -e=member1,member2 [default: "renovate-bot", "renovate[bot]"] 43 | 44 | -v, --verbose... 45 | More output per occurrence 46 | 47 | -q, --quiet... 48 | Less output per occurrence 49 | 50 | -h, --help 51 | Print help information (use `-h` for a summary) 52 | ``` 53 | 54 | You must have an environment variable called `GITHUB_ACCESS_TOKEN` either exported in your CLI or defined inside an `.env` file in the directory you're running the CLI in. 55 | 56 | The script automatically excludes the members of the organization ("owner" in this case). If you want to exclude specific users, you'll need to provide the `--excludes` flag. 57 | 58 | You can use the options `-v` to `-vvvv` to display additional logging (warnings, info, debug, trace). 59 | 60 | The results are stored inside a `output` folder in the current directory. 61 | 62 | ### Example 63 | 64 | ```shell 65 | npx @lekoarts/thanks-contributors gatsby@5.1.0-next.0 gatsby@5.1.0 gatsbyjs gatsby 66 | ``` 67 | 68 | ## Resulting output 69 | 70 | It'll create a markdown list, grouped by user login. If a person had more than one commit, it creates a nested list. Example: 71 | 72 | ```md 73 | - [harry](https://www.github.com/harry): Update something [PR #1](https://github.com/foobar/pull/1) 74 | - [hermione](https://www.github.com/hermione) 75 | - Update something [PR #2](https://github.com/foobar/pull/2) 76 | - Update something more [PR #3](https://github.com/foobar/pull/3) 77 | ``` 78 | 79 | If the url can't be found only the name will be printed. 80 | 81 | ## Caveats 82 | 83 | - Getting the PR number only works if you consistently add the number in the commit itself, e.g. in `feat: My cool feature (#123)`. This automatically happens in GitHub's UI if you use squash commits. 84 | -------------------------------------------------------------------------------- /__tests__/__snapshots__/cli.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[`cli > should error on invalid commits range 1`] = ` 4 | "[Error: Failed to parse response body: error decoding response body: missing field \`commits\` at line 1 column 125] { 5 | code: 'GenericFailure' 6 | }" 7 | `; 8 | 9 | exports[`cli > should error without required arguments 1`] = ` 10 | "error: the following required arguments were not provided: 11 | 12 | 13 | 14 | Usage: @lekoarts/thanks-contributors [OWNER] [REPO] 15 | 16 | For more information, try '--help'." 17 | `; 18 | 19 | exports[`cli > should show help command 1`] = ` 20 | "This little script accesses GitHub's API to get all contributors and their PRs between two distinct 21 | points in the history of commits. This is helpful for changelogs where you'd want to list all 22 | contributions for that release (so e.g. changes between v1 and v1.1). 23 | 24 | Usage: @lekoarts/thanks-contributors [OPTIONS] [OWNER] [REPO] 25 | 26 | Arguments: 27 | 28 | Pointer from where to start looking for changes 29 | 30 | 31 | Pointer until where to stop looking for changes 32 | 33 | [OWNER] 34 | Name of the owner/user/organization of the repository 35 | 36 | [default: gatsbyjs] 37 | 38 | [REPO] 39 | Name of the repository 40 | 41 | [default: gatsby] 42 | 43 | Options: 44 | -i, --include-org-members 45 | Include organization members into the list [default: false] 46 | 47 | [possible values: true, false] 48 | 49 | -e, --excludes ... 50 | List of members to exclude from the list. Usage: -e=member1,member2 [default: 51 | "renovate-bot", "renovate[bot]"] 52 | 53 | -v, --verbose... 54 | Increase logging verbosity 55 | 56 | -q, --quiet... 57 | Decrease logging verbosity 58 | 59 | -h, --help 60 | Print help (see a summary with '-h')" 61 | `; 62 | -------------------------------------------------------------------------------- /__tests__/cli.ts: -------------------------------------------------------------------------------- 1 | import { invokeCli } from "../vitest.utils" 2 | 3 | describe(`cli`, () => { 4 | it(`should show help command`, () => { 5 | const { exitCode, stdout } = invokeCli([`--help`]) 6 | 7 | expect(stdout).toMatchSnapshot() 8 | expect(exitCode).toBe(0) 9 | }) 10 | it(`should error without required arguments`, () => { 11 | const { exitCode, stdout } = invokeCli([]) 12 | 13 | expect(stdout).toMatchSnapshot() 14 | expect(exitCode).toBe(2) 15 | }) 16 | it(`should error on invalid commits range`, () => { 17 | const { exitCode, stdout } = invokeCli([`100.0.1`, `100.0.2`]) 18 | 19 | expect(stdout).toMatchSnapshot() 20 | expect(exitCode).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /bin.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const cli = require("./index") 4 | const arguments = process.argv.slice(2) 5 | 6 | cli.run(arguments).catch((e) => { 7 | console.error(e) 8 | process.exit(1) 9 | }) 10 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | extern crate napi_build; 2 | 3 | fn main() { 4 | napi_build::setup(); 5 | } 6 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /* auto-generated by NAPI-RS */ 5 | 6 | export declare function run(args: Array): Promise 7 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /* prettier-ignore */ 4 | 5 | /* auto-generated by NAPI-RS */ 6 | 7 | const { existsSync, readFileSync } = require('fs') 8 | const { join } = require('path') 9 | 10 | const { platform, arch } = process 11 | 12 | let nativeBinding = null 13 | let localFileExisted = false 14 | let loadError = null 15 | 16 | function isMusl() { 17 | // For Node 10 18 | if (!process.report || typeof process.report.getReport !== 'function') { 19 | try { 20 | const lddPath = require('child_process').execSync('which ldd').toString().trim() 21 | return readFileSync(lddPath, 'utf8').includes('musl') 22 | } catch (e) { 23 | return true 24 | } 25 | } else { 26 | const { glibcVersionRuntime } = process.report.getReport().header 27 | return !glibcVersionRuntime 28 | } 29 | } 30 | 31 | switch (platform) { 32 | case 'android': 33 | switch (arch) { 34 | case 'arm64': 35 | localFileExisted = existsSync(join(__dirname, 'thanks-contributors.android-arm64.node')) 36 | try { 37 | if (localFileExisted) { 38 | nativeBinding = require('./thanks-contributors.android-arm64.node') 39 | } else { 40 | nativeBinding = require('@lekoarts/thanks-contributors-android-arm64') 41 | } 42 | } catch (e) { 43 | loadError = e 44 | } 45 | break 46 | case 'arm': 47 | localFileExisted = existsSync(join(__dirname, 'thanks-contributors.android-arm-eabi.node')) 48 | try { 49 | if (localFileExisted) { 50 | nativeBinding = require('./thanks-contributors.android-arm-eabi.node') 51 | } else { 52 | nativeBinding = require('@lekoarts/thanks-contributors-android-arm-eabi') 53 | } 54 | } catch (e) { 55 | loadError = e 56 | } 57 | break 58 | default: 59 | throw new Error(`Unsupported architecture on Android ${arch}`) 60 | } 61 | break 62 | case 'win32': 63 | switch (arch) { 64 | case 'x64': 65 | localFileExisted = existsSync( 66 | join(__dirname, 'thanks-contributors.win32-x64-msvc.node') 67 | ) 68 | try { 69 | if (localFileExisted) { 70 | nativeBinding = require('./thanks-contributors.win32-x64-msvc.node') 71 | } else { 72 | nativeBinding = require('@lekoarts/thanks-contributors-win32-x64-msvc') 73 | } 74 | } catch (e) { 75 | loadError = e 76 | } 77 | break 78 | case 'ia32': 79 | localFileExisted = existsSync( 80 | join(__dirname, 'thanks-contributors.win32-ia32-msvc.node') 81 | ) 82 | try { 83 | if (localFileExisted) { 84 | nativeBinding = require('./thanks-contributors.win32-ia32-msvc.node') 85 | } else { 86 | nativeBinding = require('@lekoarts/thanks-contributors-win32-ia32-msvc') 87 | } 88 | } catch (e) { 89 | loadError = e 90 | } 91 | break 92 | case 'arm64': 93 | localFileExisted = existsSync( 94 | join(__dirname, 'thanks-contributors.win32-arm64-msvc.node') 95 | ) 96 | try { 97 | if (localFileExisted) { 98 | nativeBinding = require('./thanks-contributors.win32-arm64-msvc.node') 99 | } else { 100 | nativeBinding = require('@lekoarts/thanks-contributors-win32-arm64-msvc') 101 | } 102 | } catch (e) { 103 | loadError = e 104 | } 105 | break 106 | default: 107 | throw new Error(`Unsupported architecture on Windows: ${arch}`) 108 | } 109 | break 110 | case 'darwin': 111 | localFileExisted = existsSync(join(__dirname, 'thanks-contributors.darwin-universal.node')) 112 | try { 113 | if (localFileExisted) { 114 | nativeBinding = require('./thanks-contributors.darwin-universal.node') 115 | } else { 116 | nativeBinding = require('@lekoarts/thanks-contributors-darwin-universal') 117 | } 118 | break 119 | } catch {} 120 | switch (arch) { 121 | case 'x64': 122 | localFileExisted = existsSync(join(__dirname, 'thanks-contributors.darwin-x64.node')) 123 | try { 124 | if (localFileExisted) { 125 | nativeBinding = require('./thanks-contributors.darwin-x64.node') 126 | } else { 127 | nativeBinding = require('@lekoarts/thanks-contributors-darwin-x64') 128 | } 129 | } catch (e) { 130 | loadError = e 131 | } 132 | break 133 | case 'arm64': 134 | localFileExisted = existsSync( 135 | join(__dirname, 'thanks-contributors.darwin-arm64.node') 136 | ) 137 | try { 138 | if (localFileExisted) { 139 | nativeBinding = require('./thanks-contributors.darwin-arm64.node') 140 | } else { 141 | nativeBinding = require('@lekoarts/thanks-contributors-darwin-arm64') 142 | } 143 | } catch (e) { 144 | loadError = e 145 | } 146 | break 147 | default: 148 | throw new Error(`Unsupported architecture on macOS: ${arch}`) 149 | } 150 | break 151 | case 'freebsd': 152 | if (arch !== 'x64') { 153 | throw new Error(`Unsupported architecture on FreeBSD: ${arch}`) 154 | } 155 | localFileExisted = existsSync(join(__dirname, 'thanks-contributors.freebsd-x64.node')) 156 | try { 157 | if (localFileExisted) { 158 | nativeBinding = require('./thanks-contributors.freebsd-x64.node') 159 | } else { 160 | nativeBinding = require('@lekoarts/thanks-contributors-freebsd-x64') 161 | } 162 | } catch (e) { 163 | loadError = e 164 | } 165 | break 166 | case 'linux': 167 | switch (arch) { 168 | case 'x64': 169 | if (isMusl()) { 170 | localFileExisted = existsSync( 171 | join(__dirname, 'thanks-contributors.linux-x64-musl.node') 172 | ) 173 | try { 174 | if (localFileExisted) { 175 | nativeBinding = require('./thanks-contributors.linux-x64-musl.node') 176 | } else { 177 | nativeBinding = require('@lekoarts/thanks-contributors-linux-x64-musl') 178 | } 179 | } catch (e) { 180 | loadError = e 181 | } 182 | } else { 183 | localFileExisted = existsSync( 184 | join(__dirname, 'thanks-contributors.linux-x64-gnu.node') 185 | ) 186 | try { 187 | if (localFileExisted) { 188 | nativeBinding = require('./thanks-contributors.linux-x64-gnu.node') 189 | } else { 190 | nativeBinding = require('@lekoarts/thanks-contributors-linux-x64-gnu') 191 | } 192 | } catch (e) { 193 | loadError = e 194 | } 195 | } 196 | break 197 | case 'arm64': 198 | if (isMusl()) { 199 | localFileExisted = existsSync( 200 | join(__dirname, 'thanks-contributors.linux-arm64-musl.node') 201 | ) 202 | try { 203 | if (localFileExisted) { 204 | nativeBinding = require('./thanks-contributors.linux-arm64-musl.node') 205 | } else { 206 | nativeBinding = require('@lekoarts/thanks-contributors-linux-arm64-musl') 207 | } 208 | } catch (e) { 209 | loadError = e 210 | } 211 | } else { 212 | localFileExisted = existsSync( 213 | join(__dirname, 'thanks-contributors.linux-arm64-gnu.node') 214 | ) 215 | try { 216 | if (localFileExisted) { 217 | nativeBinding = require('./thanks-contributors.linux-arm64-gnu.node') 218 | } else { 219 | nativeBinding = require('@lekoarts/thanks-contributors-linux-arm64-gnu') 220 | } 221 | } catch (e) { 222 | loadError = e 223 | } 224 | } 225 | break 226 | case 'arm': 227 | if (isMusl()) { 228 | localFileExisted = existsSync( 229 | join(__dirname, 'thanks-contributors.linux-arm-musleabihf.node') 230 | ) 231 | try { 232 | if (localFileExisted) { 233 | nativeBinding = require('./thanks-contributors.linux-arm-musleabihf.node') 234 | } else { 235 | nativeBinding = require('@lekoarts/thanks-contributors-linux-arm-musleabihf') 236 | } 237 | } catch (e) { 238 | loadError = e 239 | } 240 | } else { 241 | localFileExisted = existsSync( 242 | join(__dirname, 'thanks-contributors.linux-arm-gnueabihf.node') 243 | ) 244 | try { 245 | if (localFileExisted) { 246 | nativeBinding = require('./thanks-contributors.linux-arm-gnueabihf.node') 247 | } else { 248 | nativeBinding = require('@lekoarts/thanks-contributors-linux-arm-gnueabihf') 249 | } 250 | } catch (e) { 251 | loadError = e 252 | } 253 | } 254 | break 255 | case 'riscv64': 256 | if (isMusl()) { 257 | localFileExisted = existsSync( 258 | join(__dirname, 'thanks-contributors.linux-riscv64-musl.node') 259 | ) 260 | try { 261 | if (localFileExisted) { 262 | nativeBinding = require('./thanks-contributors.linux-riscv64-musl.node') 263 | } else { 264 | nativeBinding = require('@lekoarts/thanks-contributors-linux-riscv64-musl') 265 | } 266 | } catch (e) { 267 | loadError = e 268 | } 269 | } else { 270 | localFileExisted = existsSync( 271 | join(__dirname, 'thanks-contributors.linux-riscv64-gnu.node') 272 | ) 273 | try { 274 | if (localFileExisted) { 275 | nativeBinding = require('./thanks-contributors.linux-riscv64-gnu.node') 276 | } else { 277 | nativeBinding = require('@lekoarts/thanks-contributors-linux-riscv64-gnu') 278 | } 279 | } catch (e) { 280 | loadError = e 281 | } 282 | } 283 | break 284 | case 's390x': 285 | localFileExisted = existsSync( 286 | join(__dirname, 'thanks-contributors.linux-s390x-gnu.node') 287 | ) 288 | try { 289 | if (localFileExisted) { 290 | nativeBinding = require('./thanks-contributors.linux-s390x-gnu.node') 291 | } else { 292 | nativeBinding = require('@lekoarts/thanks-contributors-linux-s390x-gnu') 293 | } 294 | } catch (e) { 295 | loadError = e 296 | } 297 | break 298 | default: 299 | throw new Error(`Unsupported architecture on Linux: ${arch}`) 300 | } 301 | break 302 | default: 303 | throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`) 304 | } 305 | 306 | if (!nativeBinding) { 307 | if (loadError) { 308 | throw loadError 309 | } 310 | throw new Error(`Failed to load native binding`) 311 | } 312 | 313 | const { run } = nativeBinding 314 | 315 | module.exports.run = run 316 | -------------------------------------------------------------------------------- /npm/darwin-arm64/README.md: -------------------------------------------------------------------------------- 1 | # `@lekoarts/thanks-contributors-darwin-arm64` 2 | 3 | This is the **aarch64-apple-darwin** binary for `@lekoarts/thanks-contributors` 4 | -------------------------------------------------------------------------------- /npm/darwin-arm64/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lekoarts/thanks-contributors-darwin-arm64", 3 | "version": "1.2.1", 4 | "os": [ 5 | "darwin" 6 | ], 7 | "cpu": [ 8 | "arm64" 9 | ], 10 | "main": "thanks-contributors.darwin-arm64.node", 11 | "files": [ 12 | "thanks-contributors.darwin-arm64.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /npm/darwin-x64/README.md: -------------------------------------------------------------------------------- 1 | # `@lekoarts/thanks-contributors-darwin-x64` 2 | 3 | This is the **x86_64-apple-darwin** binary for `@lekoarts/thanks-contributors` 4 | -------------------------------------------------------------------------------- /npm/darwin-x64/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lekoarts/thanks-contributors-darwin-x64", 3 | "version": "1.2.1", 4 | "os": [ 5 | "darwin" 6 | ], 7 | "cpu": [ 8 | "x64" 9 | ], 10 | "main": "thanks-contributors.darwin-x64.node", 11 | "files": [ 12 | "thanks-contributors.darwin-x64.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /npm/linux-arm-gnueabihf/README.md: -------------------------------------------------------------------------------- 1 | # `@lekoarts/thanks-contributors-linux-arm-gnueabihf` 2 | 3 | This is the **armv7-unknown-linux-gnueabihf** binary for `@lekoarts/thanks-contributors` 4 | -------------------------------------------------------------------------------- /npm/linux-arm-gnueabihf/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lekoarts/thanks-contributors-linux-arm-gnueabihf", 3 | "version": "1.1.0", 4 | "os": [ 5 | "linux" 6 | ], 7 | "cpu": [ 8 | "arm" 9 | ], 10 | "main": "thanks-contributors.linux-arm-gnueabihf.node", 11 | "files": [ 12 | "thanks-contributors.linux-arm-gnueabihf.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /npm/linux-arm64-gnu/README.md: -------------------------------------------------------------------------------- 1 | # `@lekoarts/thanks-contributors-linux-arm64-gnu` 2 | 3 | This is the **aarch64-unknown-linux-gnu** binary for `@lekoarts/thanks-contributors` 4 | -------------------------------------------------------------------------------- /npm/linux-arm64-gnu/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lekoarts/thanks-contributors-linux-arm64-gnu", 3 | "version": "1.1.0", 4 | "os": [ 5 | "linux" 6 | ], 7 | "cpu": [ 8 | "arm64" 9 | ], 10 | "main": "thanks-contributors.linux-arm64-gnu.node", 11 | "files": [ 12 | "thanks-contributors.linux-arm64-gnu.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /npm/linux-arm64-musl/README.md: -------------------------------------------------------------------------------- 1 | # `@lekoarts/thanks-contributors-linux-arm64-musl` 2 | 3 | This is the **aarch64-unknown-linux-musl** binary for `@lekoarts/thanks-contributors` 4 | -------------------------------------------------------------------------------- /npm/linux-arm64-musl/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lekoarts/thanks-contributors-linux-arm64-musl", 3 | "version": "1.2.1", 4 | "os": [ 5 | "linux" 6 | ], 7 | "cpu": [ 8 | "arm64" 9 | ], 10 | "main": "thanks-contributors.linux-arm64-musl.node", 11 | "files": [ 12 | "thanks-contributors.linux-arm64-musl.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /npm/linux-x64-gnu/README.md: -------------------------------------------------------------------------------- 1 | # `@lekoarts/thanks-contributors-linux-x64-gnu` 2 | 3 | This is the **x86_64-unknown-linux-gnu** binary for `@lekoarts/thanks-contributors` 4 | -------------------------------------------------------------------------------- /npm/linux-x64-gnu/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lekoarts/thanks-contributors-linux-x64-gnu", 3 | "version": "1.2.1", 4 | "os": [ 5 | "linux" 6 | ], 7 | "cpu": [ 8 | "x64" 9 | ], 10 | "main": "thanks-contributors.linux-x64-gnu.node", 11 | "files": [ 12 | "thanks-contributors.linux-x64-gnu.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /npm/linux-x64-musl/README.md: -------------------------------------------------------------------------------- 1 | # `@lekoarts/thanks-contributors-linux-x64-musl` 2 | 3 | This is the **x86_64-unknown-linux-musl** binary for `@lekoarts/thanks-contributors` 4 | -------------------------------------------------------------------------------- /npm/linux-x64-musl/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lekoarts/thanks-contributors-linux-x64-musl", 3 | "version": "1.2.1", 4 | "os": [ 5 | "linux" 6 | ], 7 | "cpu": [ 8 | "x64" 9 | ], 10 | "main": "thanks-contributors.linux-x64-musl.node", 11 | "files": [ 12 | "thanks-contributors.linux-x64-musl.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /npm/win32-x64-msvc/README.md: -------------------------------------------------------------------------------- 1 | # `@lekoarts/thanks-contributors-win32-x64-msvc` 2 | 3 | This is the **x86_64-pc-windows-msvc** binary for `@lekoarts/thanks-contributors` 4 | -------------------------------------------------------------------------------- /npm/win32-x64-msvc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lekoarts/thanks-contributors-win32-x64-msvc", 3 | "version": "1.2.1", 4 | "os": [ 5 | "win32" 6 | ], 7 | "cpu": [ 8 | "x64" 9 | ], 10 | "main": "thanks-contributors.win32-x64-msvc.node", 11 | "files": [ 12 | "thanks-contributors.win32-x64-msvc.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lekoarts/thanks-contributors", 3 | "version": "1.2.1", 4 | "main": "index.js", 5 | "bin": "bin.js", 6 | "description": "This little script accesses GitHub's API to get all contributors and their PRs between two distinct points in the history of commits. This is helpful for changelogs where you'd want to list all contributions for that release (so e.g. changes between v1 and v1.1).", 7 | "types": "index.d.ts", 8 | "napi": { 9 | "name": "thanks-contributors", 10 | "triples": { 11 | "additional": [ 12 | "aarch64-apple-darwin", 13 | "aarch64-unknown-linux-musl", 14 | "x86_64-unknown-linux-musl" 15 | ] 16 | } 17 | }, 18 | "files": [ 19 | "bin.js", 20 | "index.js", 21 | "index.d.ts" 22 | ], 23 | "license": "MIT", 24 | "devDependencies": { 25 | "@napi-rs/cli": "^2.18.4", 26 | "@types/prettier": "^3.0.0", 27 | "execa": "^9.3.0", 28 | "prettier": "^3.3.2", 29 | "strip-ansi": "^7.1.0", 30 | "vitest": "^2.0.2" 31 | }, 32 | "engines": { 33 | "node": ">= 14" 34 | }, 35 | "scripts": { 36 | "napi": "napi", 37 | "artifacts": "napi artifacts", 38 | "build": "napi build --platform --release", 39 | "build:debug": "napi build --platform", 40 | "prepublishOnly": "napi prepublish -t npm", 41 | "version": "napi version", 42 | "test:watch": "vitest watch", 43 | "test": "vitest run", 44 | "format": "prettier --write ." 45 | }, 46 | "prettier": { 47 | "printWidth": 120, 48 | "semi": false, 49 | "trailingComma": "es5" 50 | }, 51 | "packageManager": "yarn@3.3.1" 52 | } 53 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | tab_spaces = 2 2 | edition = "2021" 3 | -------------------------------------------------------------------------------- /src/api.rs: -------------------------------------------------------------------------------- 1 | use napi::bindgen_prelude::Result; 2 | use reqwest::header::{AUTHORIZATION, USER_AGENT}; 3 | use serde::Deserialize; 4 | 5 | use crate::error::reqwest_error; 6 | 7 | pub async fn compare_commits( 8 | owner: &str, 9 | repo: &str, 10 | base: String, 11 | head: String, 12 | gh_token: &str, 13 | ) -> Result> { 14 | let client = reqwest::Client::new(); 15 | let response = client 16 | .get(format!( 17 | "https://api.github.com/repos/{owner}/{repo}/compare/{base}...{head}" 18 | )) 19 | .header(USER_AGENT, "thanks-contributors") 20 | .header(AUTHORIZATION, format!("token {gh_token}")) 21 | .send() 22 | .await 23 | .map_err(reqwest_error)? 24 | .json::() 25 | .await 26 | .map_err(reqwest_error)?; 27 | 28 | Ok(response.commits) 29 | } 30 | 31 | pub async fn list_members(owner: &str, gh_token: &str) -> Result> { 32 | let client = reqwest::Client::new(); 33 | let response = client 34 | .get(format!( 35 | "https://api.github.com/orgs/{owner}/members?per_page=100" 36 | )) 37 | .header(USER_AGENT, "thanks-contributors") 38 | .header(AUTHORIZATION, format!("token {gh_token}")) 39 | .send() 40 | .await 41 | .map_err(reqwest_error)? 42 | .json::>() 43 | .await 44 | .map_err(reqwest_error)?; 45 | 46 | let list_of_logins = response.into_iter().map(|m| m.login).collect(); 47 | 48 | Ok(list_of_logins) 49 | } 50 | 51 | #[derive(Debug, Deserialize)] 52 | pub struct CompareCommitsResponse { 53 | pub commits: Vec, 54 | } 55 | 56 | #[derive(Debug, Deserialize)] 57 | pub struct Commit { 58 | pub url: String, 59 | pub commit: CommitMeta, 60 | pub author: Option, 61 | } 62 | 63 | #[derive(Debug, Deserialize)] 64 | pub struct CommitMeta { 65 | pub url: String, 66 | pub message: String, 67 | pub author: CommitMetaAuthor, 68 | } 69 | 70 | #[derive(Debug, Deserialize)] 71 | pub struct CommitMetaAuthor { 72 | pub name: String, 73 | } 74 | 75 | #[derive(Debug, Deserialize)] 76 | pub struct CommitAuthor { 77 | pub login: String, 78 | pub html_url: String, 79 | } 80 | 81 | #[derive(Debug, Deserialize)] 82 | pub struct Member { 83 | pub login: String, 84 | } 85 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use std::env::VarError; 2 | 3 | use clap::CommandFactory; 4 | use napi::Error as NapiError; 5 | 6 | pub fn format_cli_error(err: clap::Error) -> NapiError { 7 | let mut app = I::command(); 8 | let reason = err.format(&mut app); 9 | 10 | NapiError::from_reason(format!("{reason}")) 11 | } 12 | 13 | pub fn env_var_error(err: VarError) -> NapiError { 14 | match err { 15 | VarError::NotPresent => { 16 | NapiError::from_reason("Environment variable 'GITHUB_ACCESS_TOKEN' not present".to_owned()) 17 | } 18 | VarError::NotUnicode(_) => { 19 | NapiError::from_reason("Environment variable 'GITHUB_ACCESS_TOKEN' not unicode".to_owned()) 20 | } 21 | } 22 | } 23 | 24 | pub fn reqwest_error(err: reqwest::Error) -> NapiError { 25 | if err.is_timeout() { 26 | NapiError::from_reason(format!("Request timed out: {err}")) 27 | } else if err.is_status() { 28 | NapiError::from_reason(format!( 29 | "Unexpected status code {code}: {err}", 30 | code = err.status().unwrap_or_default().as_u16(), 31 | err = err 32 | )) 33 | } else if err.is_decode() { 34 | NapiError::from_reason(format!("Failed to parse response body: {err}")) 35 | } else if err.is_body() { 36 | NapiError::from_reason(format!("Failed to serialize request body: {err}")) 37 | } else { 38 | NapiError::from_reason(format!( 39 | "An unknown error occurred while sending the request: {err}" 40 | )) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate napi_derive; 3 | 4 | use crate::api::{compare_commits, list_members}; 5 | use crate::error::{env_var_error, format_cli_error}; 6 | use crate::utils::{create_entries, create_output, get_current_date, group_by_author}; 7 | use clap::{CommandFactory, FromArgMatches, Parser}; 8 | use clap_verbosity_flag::Verbosity; 9 | use dotenv::dotenv; 10 | use log::{debug, info}; 11 | use napi::bindgen_prelude::{Error as NapiError, Result}; 12 | use std::env; 13 | use std::fs; 14 | 15 | pub mod api; 16 | pub mod error; 17 | pub mod utils; 18 | 19 | #[allow(dead_code)] 20 | #[napi] 21 | async fn run(args: Vec) -> Result<()> { 22 | // Support .env files 23 | dotenv().ok(); 24 | 25 | // Arguments are coming from bin.js 26 | let matches = Cli::command().get_matches_from(args); 27 | let cli = Cli::from_arg_matches(&matches).map_err(format_cli_error::)?; 28 | 29 | env_logger::Builder::new() 30 | .filter_level(cli.verbose.log_level_filter()) 31 | .init(); 32 | 33 | // By default, don't include org members 34 | let should_include_org_members = cli.include_org_members.unwrap_or(false); 35 | // By default, exclude renovate bot 36 | let parsed_excludes = match cli.excludes { 37 | Some(e) => e, 38 | None => vec!["renovate[bot]".to_string(), "renovate-bot".to_string()], 39 | }; 40 | 41 | debug!("Parsed Excludes: {:#?}", parsed_excludes); 42 | 43 | let gh_token = env::var("GITHUB_ACCESS_TOKEN").map_err(env_var_error)?; 44 | 45 | let commits = compare_commits(&cli.owner, &cli.repo, cli.base, cli.head, &gh_token).await?; 46 | let org_members = list_members(&cli.owner, &gh_token).await?; 47 | 48 | debug!("Commits: {:#?}", commits); 49 | debug!("Org members: {:#?}", org_members); 50 | 51 | if commits.is_empty() { 52 | return Err(NapiError::from_reason( 53 | "Couldn't find any relevant commits. Are you sure you used the correct head & base?" 54 | .to_owned(), 55 | )); 56 | } 57 | 58 | info!("Fetched {} commits", commits.len()); 59 | 60 | let entries = create_entries( 61 | commits, 62 | should_include_org_members, 63 | parsed_excludes, 64 | org_members, 65 | ); 66 | 67 | info!("Process {} filtered commits", entries.len()); 68 | 69 | let groups = group_by_author(entries); 70 | let output = create_output(groups, &cli.owner, &cli.repo); 71 | 72 | let current_dir = env::current_dir()?; 73 | let directory_path = current_dir.join("output"); 74 | let filepath = directory_path.join(format!("{}.md", get_current_date())); 75 | 76 | fs::create_dir_all(directory_path).unwrap(); 77 | fs::write(&filepath, output).unwrap(); 78 | 79 | println!("Successfully created {}", &filepath.display()); 80 | 81 | Ok(()) 82 | } 83 | 84 | #[derive(Parser)] 85 | #[clap( 86 | author = "LekoArts", 87 | name = "@lekoarts/thanks-contributors", 88 | about = "Generate a list of contributors for a commit range", 89 | long_about = "This little script accesses GitHub's API to get all contributors and their PRs between two distinct points in the history of commits. This is helpful for changelogs where you'd want to list all contributions for that release (so e.g. changes between v1 and v1.1)." 90 | )] 91 | #[clap(no_binary_name = true)] 92 | struct Cli { 93 | /// Pointer from where to start looking for changes 94 | #[clap(required = true)] 95 | base: String, 96 | /// Pointer until where to stop looking for changes 97 | #[clap(required = true)] 98 | head: String, 99 | /// Name of the owner/user/organization of the repository 100 | #[clap(default_value = "gatsbyjs")] 101 | owner: String, 102 | /// Name of the repository 103 | #[clap(default_value = "gatsby")] 104 | repo: String, 105 | /// Include organization members into the list [default: false] 106 | #[clap(short, long)] 107 | include_org_members: Option, 108 | /// List of members to exclude from the list. Usage: -e=member1,member2 [default: "renovate-bot", "renovate[bot]"] 109 | #[clap( 110 | short, 111 | long, 112 | num_args = 1.., 113 | use_value_delimiter = true, 114 | value_delimiter = ',', 115 | )] 116 | excludes: Option>, 117 | #[clap(flatten)] 118 | verbose: Verbosity, 119 | } 120 | 121 | #[cfg(test)] 122 | mod tests { 123 | use super::*; 124 | 125 | #[test] 126 | fn verify_cli() { 127 | use clap::CommandFactory; 128 | Cli::command().debug_assert() 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/utils.rs: -------------------------------------------------------------------------------- 1 | use chrono::{ 2 | format::{DelayedFormat, StrftimeItems}, 3 | DateTime, Utc, 4 | }; 5 | use lazy_static::lazy_static; 6 | use regex::Regex; 7 | use std::collections::BTreeMap; 8 | 9 | use crate::api::Commit; 10 | 11 | pub fn get_current_date<'a>() -> DelayedFormat> { 12 | let now: DateTime = Utc::now(); 13 | now.format("%Y-%m-%d_%H-%M-%S") 14 | } 15 | 16 | pub fn group_by_author(input: Vec) -> BTreeMap> { 17 | // Use a BTreeMap since its keys are sorted alphabetically 18 | let mut groups: BTreeMap> = BTreeMap::new(); 19 | 20 | for e in input { 21 | let group = groups.entry(e.author.clone()).or_default(); 22 | group.push(e); 23 | } 24 | 25 | groups 26 | } 27 | 28 | pub fn get_pr_link(entry: &Entry, owner: &str, repo: &str) -> String { 29 | let Some(number) = &entry.pr_number else { 30 | return String::from(""); 31 | }; 32 | 33 | format!("[PR #{number}](https://github.com/{owner}/{repo}/pull/{number})") 34 | } 35 | 36 | pub fn parse_msg_and_pr(input: &str) -> MsgAndPr { 37 | lazy_static! { 38 | // Regex is not dynamic so .unwrap is fine 39 | static ref RE: Regex = Regex::new(r"^(?P.*)\(#(?P[0-9]+)\)").unwrap(); 40 | } 41 | 42 | match RE.captures(input) { 43 | Some(caps) => { 44 | let message = caps.name("msg").map(|m| m.as_str().trim_end().to_string()); 45 | let pr_number = caps.name("pr").map(|m| m.as_str().to_string()); 46 | 47 | MsgAndPr { message, pr_number } 48 | } 49 | None => MsgAndPr { 50 | message: None, 51 | pr_number: None, 52 | }, 53 | } 54 | } 55 | 56 | pub fn create_entries( 57 | commits: Vec, 58 | should_include_org_members: bool, 59 | parsed_excludes: Vec, 60 | org_members: Vec, 61 | ) -> Vec { 62 | commits 63 | .into_iter() 64 | .map(|c| { 65 | let first_line = c.commit.message.lines().next().map_or("", |f| f); 66 | let msg_and_pr = parse_msg_and_pr(first_line); 67 | 68 | let mut author = c.commit.author.name; 69 | let mut author_url: Option = None; 70 | 71 | if let Some(a) = c.author { 72 | author = a.login; 73 | author_url = Some(a.html_url); 74 | }; 75 | 76 | Entry { 77 | author, 78 | author_url, 79 | message: msg_and_pr.message, 80 | pr_number: msg_and_pr.pr_number, 81 | } 82 | }) 83 | .filter(|i| { 84 | if should_include_org_members { 85 | true 86 | } else { 87 | // Exclude members from the final list of entries 88 | !parsed_excludes 89 | .iter() 90 | .chain(&org_members) 91 | .any(|x| x == &i.author) 92 | } 93 | }) 94 | .collect() 95 | } 96 | 97 | pub fn create_output(groups: BTreeMap>, owner: &str, repo: &str) -> String { 98 | let mut output = String::new(); 99 | 100 | for (author_name, author_entries) in groups { 101 | let md_author = match &author_entries[0].author_url { 102 | Some(url) => format!("[{author_name}]({url})"), 103 | None => author_name, 104 | }; 105 | 106 | if author_entries.len() > 1 { 107 | let mut md_author_list = String::new(); 108 | for entry in author_entries { 109 | if let Some(msg) = &entry.message { 110 | let line = format!(" - {} {}\n", msg, get_pr_link(&entry, owner, repo)); 111 | md_author_list.push_str(&line) 112 | }; 113 | } 114 | 115 | let text = format!("- {md_author}\n{md_author_list}"); 116 | 117 | output.push_str(&text); 118 | } else { 119 | let pr_link = get_pr_link(&author_entries[0], owner, repo); 120 | 121 | if let Some(msg) = &author_entries[0].message { 122 | let text = format!("- {md_author}: {msg} {pr_link}\n"); 123 | output.push_str(&text); 124 | }; 125 | } 126 | } 127 | 128 | output 129 | } 130 | 131 | #[derive(Eq, PartialEq, Debug)] 132 | pub struct MsgAndPr { 133 | pub message: Option, 134 | pub pr_number: Option, 135 | } 136 | 137 | #[derive(Clone, PartialEq, Eq, Debug)] 138 | pub struct Entry { 139 | pub author: String, 140 | pub author_url: Option, 141 | pub message: Option, 142 | pub pr_number: Option, 143 | } 144 | 145 | #[cfg(test)] 146 | mod tests { 147 | use crate::api::{CommitAuthor, CommitMeta, CommitMetaAuthor}; 148 | 149 | use super::*; 150 | 151 | fn entry_a_one() -> Entry { 152 | Entry { 153 | author: "author-a".to_string(), 154 | author_url: Some("author-a-url".to_string()), 155 | message: Some("fix(scope): Message".to_string()), 156 | pr_number: Some("1".to_string()), 157 | } 158 | } 159 | 160 | fn entry_a_two() -> Entry { 161 | Entry { 162 | author: "author-a".to_string(), 163 | author_url: Some("author-a-url".to_string()), 164 | message: Some("fix(scope): Message".to_string()), 165 | pr_number: Some("2".to_string()), 166 | } 167 | } 168 | 169 | fn entry_b() -> Entry { 170 | Entry { 171 | author: "author-b".to_string(), 172 | author_url: Some("author-b-url".to_string()), 173 | message: Some("fix(scope): Message".to_string()), 174 | pr_number: Some("3".to_string()), 175 | } 176 | } 177 | 178 | fn entry_c() -> Entry { 179 | Entry { 180 | author: "author-c".to_string(), 181 | author_url: None, 182 | message: Some("fix(scope): Message".to_string()), 183 | pr_number: Some("4".to_string()), 184 | } 185 | } 186 | 187 | #[test] 188 | fn group_by_author_correct() { 189 | let input: Vec = vec![entry_a_one(), entry_a_two(), entry_b()]; 190 | 191 | let mut assert = BTreeMap::new(); 192 | assert.insert("author-a".to_string(), vec![entry_a_one(), entry_a_two()]); 193 | assert.insert("author-b".to_string(), vec![entry_b()]); 194 | 195 | assert_eq!(group_by_author(input), assert) 196 | } 197 | 198 | #[test] 199 | fn group_by_author_empty_input() { 200 | assert_eq!(group_by_author(vec![]), BTreeMap::new()) 201 | } 202 | 203 | #[test] 204 | fn pr_link_no_number() { 205 | assert_eq!( 206 | get_pr_link( 207 | &Entry { 208 | author: "foo".to_string(), 209 | author_url: None, 210 | message: None, 211 | pr_number: None, 212 | }, 213 | "owner", 214 | "repo" 215 | ), 216 | "".to_string() 217 | ) 218 | } 219 | 220 | #[test] 221 | fn pr_link_correct() { 222 | assert_eq!( 223 | get_pr_link( 224 | &Entry { 225 | author: "foo".to_string(), 226 | author_url: None, 227 | message: None, 228 | pr_number: Some("123".to_string()), 229 | }, 230 | "owner", 231 | "repo" 232 | ), 233 | "[PR #123](https://github.com/owner/repo/pull/123)".to_string() 234 | ) 235 | } 236 | 237 | #[test] 238 | fn parse_msg_and_pr_no_result() { 239 | assert_eq!( 240 | parse_msg_and_pr("(((test)))"), 241 | MsgAndPr { 242 | message: None, 243 | pr_number: None 244 | } 245 | ) 246 | } 247 | 248 | #[test] 249 | fn parse_msg_and_pr_correct() { 250 | assert_eq!( 251 | parse_msg_and_pr("fix(scope): Message (#123)"), 252 | MsgAndPr { 253 | message: Some("fix(scope): Message".to_string()), 254 | pr_number: Some("123".to_string()) 255 | } 256 | ) 257 | } 258 | 259 | #[test] 260 | fn parse_msg_and_pr_correct_backport() { 261 | assert_eq!( 262 | parse_msg_and_pr("fix(scope): Message (#123) (#456)"), 263 | MsgAndPr { 264 | message: Some("fix(scope): Message (#123)".to_string()), 265 | pr_number: Some("456".to_string()) 266 | } 267 | ) 268 | } 269 | 270 | #[test] 271 | fn parse_msg_and_pr_only_msg() { 272 | assert_eq!( 273 | parse_msg_and_pr("fix(scope): Message"), 274 | MsgAndPr { 275 | message: None, 276 | pr_number: None 277 | } 278 | ) 279 | } 280 | 281 | fn get_org_members() -> Vec { 282 | vec!["author-d".to_string()] 283 | } 284 | 285 | fn get_excludes() -> Vec { 286 | vec!["author-e".to_string()] 287 | } 288 | 289 | fn commits_data() -> Vec { 290 | vec![ 291 | Commit { 292 | url: "url-1".to_string(), 293 | commit: CommitMeta { 294 | url: "url-1".to_string(), 295 | message: "fix(scope): Message (#1)".to_string(), 296 | author: CommitMetaAuthor { 297 | name: "author-a".to_string(), 298 | }, 299 | }, 300 | author: Some(CommitAuthor { 301 | login: "author-a".to_string(), 302 | html_url: "author-a-url".to_string(), 303 | }), 304 | }, 305 | Commit { 306 | url: "url-2".to_string(), 307 | commit: CommitMeta { 308 | url: "url-2".to_string(), 309 | message: "fix(scope): Message (#2)".to_string(), 310 | author: CommitMetaAuthor { 311 | name: "author-a".to_string(), 312 | }, 313 | }, 314 | author: Some(CommitAuthor { 315 | login: "author-a".to_string(), 316 | html_url: "author-a-url".to_string(), 317 | }), 318 | }, 319 | Commit { 320 | url: "url-3".to_string(), 321 | commit: CommitMeta { 322 | url: "url-3".to_string(), 323 | message: "fix(scope): Message (#3)".to_string(), 324 | author: CommitMetaAuthor { 325 | name: "author-b".to_string(), 326 | }, 327 | }, 328 | author: Some(CommitAuthor { 329 | login: "author-b".to_string(), 330 | html_url: "author-b-url".to_string(), 331 | }), 332 | }, 333 | Commit { 334 | url: "url-4".to_string(), 335 | commit: CommitMeta { 336 | url: "url-4".to_string(), 337 | message: "fix(scope): Message (#4)".to_string(), 338 | author: CommitMetaAuthor { 339 | name: "author-c".to_string(), 340 | }, 341 | }, 342 | author: None, 343 | }, 344 | Commit { 345 | url: "url-5".to_string(), 346 | commit: CommitMeta { 347 | url: "url-5".to_string(), 348 | message: "fix(scope): Message (#5)".to_string(), 349 | author: CommitMetaAuthor { 350 | name: "author-d".to_string(), 351 | }, 352 | }, 353 | author: None, 354 | }, 355 | Commit { 356 | url: "url-6".to_string(), 357 | commit: CommitMeta { 358 | url: "url-6".to_string(), 359 | message: "fix(scope): Message (#6)".to_string(), 360 | author: CommitMetaAuthor { 361 | name: "author-e".to_string(), 362 | }, 363 | }, 364 | author: None, 365 | }, 366 | ] 367 | } 368 | 369 | #[test] 370 | fn create_entries_defaults() { 371 | assert_eq!( 372 | create_entries(commits_data(), false, vec![], get_org_members()), 373 | vec![ 374 | Entry { 375 | author: "author-a".to_string(), 376 | author_url: Some("author-a-url".to_string()), 377 | message: Some("fix(scope): Message".to_string()), 378 | pr_number: Some("1".to_string()) 379 | }, 380 | Entry { 381 | author: "author-a".to_string(), 382 | author_url: Some("author-a-url".to_string()), 383 | message: Some("fix(scope): Message".to_string()), 384 | pr_number: Some("2".to_string()) 385 | }, 386 | Entry { 387 | author: "author-b".to_string(), 388 | author_url: Some("author-b-url".to_string()), 389 | message: Some("fix(scope): Message".to_string()), 390 | pr_number: Some("3".to_string()) 391 | }, 392 | Entry { 393 | author: "author-c".to_string(), 394 | author_url: None, 395 | message: Some("fix(scope): Message".to_string()), 396 | pr_number: Some("4".to_string()) 397 | }, 398 | Entry { 399 | author: "author-e".to_string(), 400 | author_url: None, 401 | message: Some("fix(scope): Message".to_string()), 402 | pr_number: Some("6".to_string()) 403 | } 404 | ] 405 | ) 406 | } 407 | 408 | #[test] 409 | fn create_entries_include_org_members() { 410 | assert_eq!( 411 | create_entries(commits_data(), true, vec![], get_org_members()), 412 | vec![ 413 | Entry { 414 | author: "author-a".to_string(), 415 | author_url: Some("author-a-url".to_string()), 416 | message: Some("fix(scope): Message".to_string()), 417 | pr_number: Some("1".to_string()) 418 | }, 419 | Entry { 420 | author: "author-a".to_string(), 421 | author_url: Some("author-a-url".to_string()), 422 | message: Some("fix(scope): Message".to_string()), 423 | pr_number: Some("2".to_string()) 424 | }, 425 | Entry { 426 | author: "author-b".to_string(), 427 | author_url: Some("author-b-url".to_string()), 428 | message: Some("fix(scope): Message".to_string()), 429 | pr_number: Some("3".to_string()) 430 | }, 431 | Entry { 432 | author: "author-c".to_string(), 433 | author_url: None, 434 | message: Some("fix(scope): Message".to_string()), 435 | pr_number: Some("4".to_string()) 436 | }, 437 | Entry { 438 | author: "author-d".to_string(), 439 | author_url: None, 440 | message: Some("fix(scope): Message".to_string()), 441 | pr_number: Some("5".to_string()) 442 | }, 443 | Entry { 444 | author: "author-e".to_string(), 445 | author_url: None, 446 | message: Some("fix(scope): Message".to_string()), 447 | pr_number: Some("6".to_string()) 448 | } 449 | ] 450 | ) 451 | } 452 | 453 | #[test] 454 | fn create_entries_defaults_with_excludes() { 455 | assert_eq!( 456 | create_entries(commits_data(), false, get_excludes(), get_org_members()), 457 | vec![ 458 | Entry { 459 | author: "author-a".to_string(), 460 | author_url: Some("author-a-url".to_string()), 461 | message: Some("fix(scope): Message".to_string()), 462 | pr_number: Some("1".to_string()) 463 | }, 464 | Entry { 465 | author: "author-a".to_string(), 466 | author_url: Some("author-a-url".to_string()), 467 | message: Some("fix(scope): Message".to_string()), 468 | pr_number: Some("2".to_string()) 469 | }, 470 | Entry { 471 | author: "author-b".to_string(), 472 | author_url: Some("author-b-url".to_string()), 473 | message: Some("fix(scope): Message".to_string()), 474 | pr_number: Some("3".to_string()) 475 | }, 476 | Entry { 477 | author: "author-c".to_string(), 478 | author_url: None, 479 | message: Some("fix(scope): Message".to_string()), 480 | pr_number: Some("4".to_string()) 481 | } 482 | ] 483 | ) 484 | } 485 | 486 | #[test] 487 | fn create_output_single_entry() { 488 | let mut groups = BTreeMap::new(); 489 | groups.insert("author-b".to_string(), vec![entry_b()]); 490 | 491 | assert_eq!(create_output(groups, "owner", "repo"), "- [author-b](author-b-url): fix(scope): Message [PR #3](https://github.com/owner/repo/pull/3)\n".to_string()) 492 | } 493 | 494 | #[test] 495 | fn create_output_multiple_entries() { 496 | let mut groups = BTreeMap::new(); 497 | groups.insert("author-a".to_string(), vec![entry_a_one(), entry_a_two()]); 498 | 499 | assert_eq!(create_output(groups, "owner", "repo"), "- [author-a](author-a-url)\n - fix(scope): Message [PR #1](https://github.com/owner/repo/pull/1)\n - fix(scope): Message [PR #2](https://github.com/owner/repo/pull/2)\n".to_string()) 500 | } 501 | 502 | #[test] 503 | fn create_output_no_author_url() { 504 | let mut groups = BTreeMap::new(); 505 | groups.insert("author-c".to_string(), vec![entry_c()]); 506 | 507 | assert_eq!( 508 | create_output(groups, "owner", "repo"), 509 | "- author-c: fix(scope): Message [PR #4](https://github.com/owner/repo/pull/4)\n".to_string() 510 | ) 511 | } 512 | 513 | #[test] 514 | fn create_output_no_author_url_multiple_entries() { 515 | let mut groups = BTreeMap::new(); 516 | groups.insert("author-c".to_string(), vec![entry_c(), entry_c()]); 517 | 518 | assert_eq!(create_output(groups, "owner", "repo"), "- author-c\n - fix(scope): Message [PR #4](https://github.com/owner/repo/pull/4)\n - fix(scope): Message [PR #4](https://github.com/owner/repo/pull/4)\n".to_string()) 519 | } 520 | } 521 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./__tests__/**/*", "./vitest.utils.ts"], 3 | "compilerOptions": { 4 | "types": ["vitest/globals"], 5 | "esModuleInterop": true 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config" 2 | 3 | export default defineConfig({ 4 | test: { 5 | globals: true, 6 | include: [`__tests__/*.ts`], 7 | coverage: { 8 | reporter: [`text`, `json`, `html`], 9 | }, 10 | }, 11 | }) 12 | -------------------------------------------------------------------------------- /vitest.utils.ts: -------------------------------------------------------------------------------- 1 | import { execaSync } from "execa" 2 | import { join } from "path" 3 | import strip from "strip-ansi" 4 | 5 | type CreateLogsMatcherOutput = { 6 | should: { 7 | contain: (match: string) => void 8 | } 9 | } 10 | 11 | const createLogsMatcher = (output: string): CreateLogsMatcherOutput => { 12 | return { 13 | should: { 14 | contain: (match) => { 15 | expect(output).toMatch(new RegExp(match.replace(/\s+/g, `\\s+`))) 16 | }, 17 | }, 18 | } 19 | } 20 | 21 | const cliBinLocation = join(__dirname, `bin.js`) 22 | 23 | type InvokeCliResult = { 24 | exitCode: number 25 | stdout: string 26 | logs: CreateLogsMatcherOutput 27 | } 28 | 29 | export function invokeCli(args: Array): InvokeCliResult { 30 | try { 31 | const results = execaSync(process.execPath, [cliBinLocation].concat(args), { 32 | cwd: __dirname, 33 | }) 34 | return { 35 | exitCode: results.exitCode, 36 | stdout: strip(results.stdout.toString()), 37 | logs: createLogsMatcher(strip(results.stdout.toString())), 38 | } 39 | } catch (err) { 40 | return { 41 | exitCode: err.exitCode, 42 | stdout: strip(err.stderr.toString()), 43 | logs: createLogsMatcher(strip(err.stderr?.toString() || ``)), 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # This file is generated by running "yarn install" inside your project. 2 | # Manual changes might be lost - proceed with caution! 3 | 4 | __metadata: 5 | version: 6 6 | cacheKey: 8 7 | 8 | "@ampproject/remapping@npm:^2.3.0": 9 | version: 2.3.0 10 | resolution: "@ampproject/remapping@npm:2.3.0" 11 | dependencies: 12 | "@jridgewell/gen-mapping": ^0.3.5 13 | "@jridgewell/trace-mapping": ^0.3.24 14 | checksum: d3ad7b89d973df059c4e8e6d7c972cbeb1bb2f18f002a3bd04ae0707da214cb06cc06929b65aa2313b9347463df2914772298bae8b1d7973f246bb3f2ab3e8f0 15 | languageName: node 16 | linkType: hard 17 | 18 | "@esbuild/aix-ppc64@npm:0.21.5": 19 | version: 0.21.5 20 | resolution: "@esbuild/aix-ppc64@npm:0.21.5" 21 | conditions: os=aix & cpu=ppc64 22 | languageName: node 23 | linkType: hard 24 | 25 | "@esbuild/android-arm64@npm:0.21.5": 26 | version: 0.21.5 27 | resolution: "@esbuild/android-arm64@npm:0.21.5" 28 | conditions: os=android & cpu=arm64 29 | languageName: node 30 | linkType: hard 31 | 32 | "@esbuild/android-arm@npm:0.21.5": 33 | version: 0.21.5 34 | resolution: "@esbuild/android-arm@npm:0.21.5" 35 | conditions: os=android & cpu=arm 36 | languageName: node 37 | linkType: hard 38 | 39 | "@esbuild/android-x64@npm:0.21.5": 40 | version: 0.21.5 41 | resolution: "@esbuild/android-x64@npm:0.21.5" 42 | conditions: os=android & cpu=x64 43 | languageName: node 44 | linkType: hard 45 | 46 | "@esbuild/darwin-arm64@npm:0.21.5": 47 | version: 0.21.5 48 | resolution: "@esbuild/darwin-arm64@npm:0.21.5" 49 | conditions: os=darwin & cpu=arm64 50 | languageName: node 51 | linkType: hard 52 | 53 | "@esbuild/darwin-x64@npm:0.21.5": 54 | version: 0.21.5 55 | resolution: "@esbuild/darwin-x64@npm:0.21.5" 56 | conditions: os=darwin & cpu=x64 57 | languageName: node 58 | linkType: hard 59 | 60 | "@esbuild/freebsd-arm64@npm:0.21.5": 61 | version: 0.21.5 62 | resolution: "@esbuild/freebsd-arm64@npm:0.21.5" 63 | conditions: os=freebsd & cpu=arm64 64 | languageName: node 65 | linkType: hard 66 | 67 | "@esbuild/freebsd-x64@npm:0.21.5": 68 | version: 0.21.5 69 | resolution: "@esbuild/freebsd-x64@npm:0.21.5" 70 | conditions: os=freebsd & cpu=x64 71 | languageName: node 72 | linkType: hard 73 | 74 | "@esbuild/linux-arm64@npm:0.21.5": 75 | version: 0.21.5 76 | resolution: "@esbuild/linux-arm64@npm:0.21.5" 77 | conditions: os=linux & cpu=arm64 78 | languageName: node 79 | linkType: hard 80 | 81 | "@esbuild/linux-arm@npm:0.21.5": 82 | version: 0.21.5 83 | resolution: "@esbuild/linux-arm@npm:0.21.5" 84 | conditions: os=linux & cpu=arm 85 | languageName: node 86 | linkType: hard 87 | 88 | "@esbuild/linux-ia32@npm:0.21.5": 89 | version: 0.21.5 90 | resolution: "@esbuild/linux-ia32@npm:0.21.5" 91 | conditions: os=linux & cpu=ia32 92 | languageName: node 93 | linkType: hard 94 | 95 | "@esbuild/linux-loong64@npm:0.21.5": 96 | version: 0.21.5 97 | resolution: "@esbuild/linux-loong64@npm:0.21.5" 98 | conditions: os=linux & cpu=loong64 99 | languageName: node 100 | linkType: hard 101 | 102 | "@esbuild/linux-mips64el@npm:0.21.5": 103 | version: 0.21.5 104 | resolution: "@esbuild/linux-mips64el@npm:0.21.5" 105 | conditions: os=linux & cpu=mips64el 106 | languageName: node 107 | linkType: hard 108 | 109 | "@esbuild/linux-ppc64@npm:0.21.5": 110 | version: 0.21.5 111 | resolution: "@esbuild/linux-ppc64@npm:0.21.5" 112 | conditions: os=linux & cpu=ppc64 113 | languageName: node 114 | linkType: hard 115 | 116 | "@esbuild/linux-riscv64@npm:0.21.5": 117 | version: 0.21.5 118 | resolution: "@esbuild/linux-riscv64@npm:0.21.5" 119 | conditions: os=linux & cpu=riscv64 120 | languageName: node 121 | linkType: hard 122 | 123 | "@esbuild/linux-s390x@npm:0.21.5": 124 | version: 0.21.5 125 | resolution: "@esbuild/linux-s390x@npm:0.21.5" 126 | conditions: os=linux & cpu=s390x 127 | languageName: node 128 | linkType: hard 129 | 130 | "@esbuild/linux-x64@npm:0.21.5": 131 | version: 0.21.5 132 | resolution: "@esbuild/linux-x64@npm:0.21.5" 133 | conditions: os=linux & cpu=x64 134 | languageName: node 135 | linkType: hard 136 | 137 | "@esbuild/netbsd-x64@npm:0.21.5": 138 | version: 0.21.5 139 | resolution: "@esbuild/netbsd-x64@npm:0.21.5" 140 | conditions: os=netbsd & cpu=x64 141 | languageName: node 142 | linkType: hard 143 | 144 | "@esbuild/openbsd-x64@npm:0.21.5": 145 | version: 0.21.5 146 | resolution: "@esbuild/openbsd-x64@npm:0.21.5" 147 | conditions: os=openbsd & cpu=x64 148 | languageName: node 149 | linkType: hard 150 | 151 | "@esbuild/sunos-x64@npm:0.21.5": 152 | version: 0.21.5 153 | resolution: "@esbuild/sunos-x64@npm:0.21.5" 154 | conditions: os=sunos & cpu=x64 155 | languageName: node 156 | linkType: hard 157 | 158 | "@esbuild/win32-arm64@npm:0.21.5": 159 | version: 0.21.5 160 | resolution: "@esbuild/win32-arm64@npm:0.21.5" 161 | conditions: os=win32 & cpu=arm64 162 | languageName: node 163 | linkType: hard 164 | 165 | "@esbuild/win32-ia32@npm:0.21.5": 166 | version: 0.21.5 167 | resolution: "@esbuild/win32-ia32@npm:0.21.5" 168 | conditions: os=win32 & cpu=ia32 169 | languageName: node 170 | linkType: hard 171 | 172 | "@esbuild/win32-x64@npm:0.21.5": 173 | version: 0.21.5 174 | resolution: "@esbuild/win32-x64@npm:0.21.5" 175 | conditions: os=win32 & cpu=x64 176 | languageName: node 177 | linkType: hard 178 | 179 | "@gar/promisify@npm:^1.1.3": 180 | version: 1.1.3 181 | resolution: "@gar/promisify@npm:1.1.3" 182 | checksum: 4059f790e2d07bf3c3ff3e0fec0daa8144fe35c1f6e0111c9921bd32106adaa97a4ab096ad7dab1e28ee6a9060083c4d1a4ada42a7f5f3f7a96b8812e2b757c1 183 | languageName: node 184 | linkType: hard 185 | 186 | "@jridgewell/gen-mapping@npm:^0.3.5": 187 | version: 0.3.5 188 | resolution: "@jridgewell/gen-mapping@npm:0.3.5" 189 | dependencies: 190 | "@jridgewell/set-array": ^1.2.1 191 | "@jridgewell/sourcemap-codec": ^1.4.10 192 | "@jridgewell/trace-mapping": ^0.3.24 193 | checksum: ff7a1764ebd76a5e129c8890aa3e2f46045109dabde62b0b6c6a250152227647178ff2069ea234753a690d8f3c4ac8b5e7b267bbee272bffb7f3b0a370ab6e52 194 | languageName: node 195 | linkType: hard 196 | 197 | "@jridgewell/resolve-uri@npm:^3.1.0": 198 | version: 3.1.2 199 | resolution: "@jridgewell/resolve-uri@npm:3.1.2" 200 | checksum: 83b85f72c59d1c080b4cbec0fef84528963a1b5db34e4370fa4bd1e3ff64a0d80e0cee7369d11d73c704e0286fb2865b530acac7a871088fbe92b5edf1000870 201 | languageName: node 202 | linkType: hard 203 | 204 | "@jridgewell/set-array@npm:^1.2.1": 205 | version: 1.2.1 206 | resolution: "@jridgewell/set-array@npm:1.2.1" 207 | checksum: 832e513a85a588f8ed4f27d1279420d8547743cc37fcad5a5a76fc74bb895b013dfe614d0eed9cb860048e6546b798f8f2652020b4b2ba0561b05caa8c654b10 208 | languageName: node 209 | linkType: hard 210 | 211 | "@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.15": 212 | version: 1.5.0 213 | resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" 214 | checksum: 05df4f2538b3b0f998ea4c1cd34574d0feba216fa5d4ccaef0187d12abf82eafe6021cec8b49f9bb4d90f2ba4582ccc581e72986a5fcf4176ae0cfeb04cf52ec 215 | languageName: node 216 | linkType: hard 217 | 218 | "@jridgewell/trace-mapping@npm:^0.3.24": 219 | version: 0.3.25 220 | resolution: "@jridgewell/trace-mapping@npm:0.3.25" 221 | dependencies: 222 | "@jridgewell/resolve-uri": ^3.1.0 223 | "@jridgewell/sourcemap-codec": ^1.4.14 224 | checksum: 9d3c40d225e139987b50c48988f8717a54a8c994d8a948ee42e1412e08988761d0754d7d10b803061cc3aebf35f92a5dbbab493bd0e1a9ef9e89a2130e83ba34 225 | languageName: node 226 | linkType: hard 227 | 228 | "@lekoarts/thanks-contributors@workspace:.": 229 | version: 0.0.0-use.local 230 | resolution: "@lekoarts/thanks-contributors@workspace:." 231 | dependencies: 232 | "@napi-rs/cli": ^2.18.4 233 | "@types/prettier": ^3.0.0 234 | execa: ^9.3.0 235 | prettier: ^3.3.2 236 | strip-ansi: ^7.1.0 237 | vitest: ^2.0.2 238 | bin: 239 | thanks-contributors: bin.js 240 | languageName: unknown 241 | linkType: soft 242 | 243 | "@napi-rs/cli@npm:^2.18.4": 244 | version: 2.18.4 245 | resolution: "@napi-rs/cli@npm:2.18.4" 246 | bin: 247 | napi: scripts/index.js 248 | checksum: f243e5c822a4a9103fba49193eda2023cb08c1ef9c0b521d8a0ece860ef13f9f2b4d5ac106c3d9e5792d22ed2196213e336cf59d9c2ee81241ac4b4b8ca6ea30 249 | languageName: node 250 | linkType: hard 251 | 252 | "@npmcli/fs@npm:^2.1.0": 253 | version: 2.1.2 254 | resolution: "@npmcli/fs@npm:2.1.2" 255 | dependencies: 256 | "@gar/promisify": ^1.1.3 257 | semver: ^7.3.5 258 | checksum: 405074965e72d4c9d728931b64d2d38e6ea12066d4fad651ac253d175e413c06fe4350970c783db0d749181da8fe49c42d3880bd1cbc12cd68e3a7964d820225 259 | languageName: node 260 | linkType: hard 261 | 262 | "@npmcli/move-file@npm:^2.0.0": 263 | version: 2.0.1 264 | resolution: "@npmcli/move-file@npm:2.0.1" 265 | dependencies: 266 | mkdirp: ^1.0.4 267 | rimraf: ^3.0.2 268 | checksum: 52dc02259d98da517fae4cb3a0a3850227bdae4939dda1980b788a7670636ca2b4a01b58df03dd5f65c1e3cb70c50fa8ce5762b582b3f499ec30ee5ce1fd9380 269 | languageName: node 270 | linkType: hard 271 | 272 | "@rollup/rollup-android-arm-eabi@npm:4.18.1": 273 | version: 4.18.1 274 | resolution: "@rollup/rollup-android-arm-eabi@npm:4.18.1" 275 | conditions: os=android & cpu=arm 276 | languageName: node 277 | linkType: hard 278 | 279 | "@rollup/rollup-android-arm64@npm:4.18.1": 280 | version: 4.18.1 281 | resolution: "@rollup/rollup-android-arm64@npm:4.18.1" 282 | conditions: os=android & cpu=arm64 283 | languageName: node 284 | linkType: hard 285 | 286 | "@rollup/rollup-darwin-arm64@npm:4.18.1": 287 | version: 4.18.1 288 | resolution: "@rollup/rollup-darwin-arm64@npm:4.18.1" 289 | conditions: os=darwin & cpu=arm64 290 | languageName: node 291 | linkType: hard 292 | 293 | "@rollup/rollup-darwin-x64@npm:4.18.1": 294 | version: 4.18.1 295 | resolution: "@rollup/rollup-darwin-x64@npm:4.18.1" 296 | conditions: os=darwin & cpu=x64 297 | languageName: node 298 | linkType: hard 299 | 300 | "@rollup/rollup-linux-arm-gnueabihf@npm:4.18.1": 301 | version: 4.18.1 302 | resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.18.1" 303 | conditions: os=linux & cpu=arm & libc=glibc 304 | languageName: node 305 | linkType: hard 306 | 307 | "@rollup/rollup-linux-arm-musleabihf@npm:4.18.1": 308 | version: 4.18.1 309 | resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.18.1" 310 | conditions: os=linux & cpu=arm & libc=musl 311 | languageName: node 312 | linkType: hard 313 | 314 | "@rollup/rollup-linux-arm64-gnu@npm:4.18.1": 315 | version: 4.18.1 316 | resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.18.1" 317 | conditions: os=linux & cpu=arm64 & libc=glibc 318 | languageName: node 319 | linkType: hard 320 | 321 | "@rollup/rollup-linux-arm64-musl@npm:4.18.1": 322 | version: 4.18.1 323 | resolution: "@rollup/rollup-linux-arm64-musl@npm:4.18.1" 324 | conditions: os=linux & cpu=arm64 & libc=musl 325 | languageName: node 326 | linkType: hard 327 | 328 | "@rollup/rollup-linux-powerpc64le-gnu@npm:4.18.1": 329 | version: 4.18.1 330 | resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.18.1" 331 | conditions: os=linux & cpu=ppc64 & libc=glibc 332 | languageName: node 333 | linkType: hard 334 | 335 | "@rollup/rollup-linux-riscv64-gnu@npm:4.18.1": 336 | version: 4.18.1 337 | resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.18.1" 338 | conditions: os=linux & cpu=riscv64 & libc=glibc 339 | languageName: node 340 | linkType: hard 341 | 342 | "@rollup/rollup-linux-s390x-gnu@npm:4.18.1": 343 | version: 4.18.1 344 | resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.18.1" 345 | conditions: os=linux & cpu=s390x & libc=glibc 346 | languageName: node 347 | linkType: hard 348 | 349 | "@rollup/rollup-linux-x64-gnu@npm:4.18.1": 350 | version: 4.18.1 351 | resolution: "@rollup/rollup-linux-x64-gnu@npm:4.18.1" 352 | conditions: os=linux & cpu=x64 & libc=glibc 353 | languageName: node 354 | linkType: hard 355 | 356 | "@rollup/rollup-linux-x64-musl@npm:4.18.1": 357 | version: 4.18.1 358 | resolution: "@rollup/rollup-linux-x64-musl@npm:4.18.1" 359 | conditions: os=linux & cpu=x64 & libc=musl 360 | languageName: node 361 | linkType: hard 362 | 363 | "@rollup/rollup-win32-arm64-msvc@npm:4.18.1": 364 | version: 4.18.1 365 | resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.18.1" 366 | conditions: os=win32 & cpu=arm64 367 | languageName: node 368 | linkType: hard 369 | 370 | "@rollup/rollup-win32-ia32-msvc@npm:4.18.1": 371 | version: 4.18.1 372 | resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.18.1" 373 | conditions: os=win32 & cpu=ia32 374 | languageName: node 375 | linkType: hard 376 | 377 | "@rollup/rollup-win32-x64-msvc@npm:4.18.1": 378 | version: 4.18.1 379 | resolution: "@rollup/rollup-win32-x64-msvc@npm:4.18.1" 380 | conditions: os=win32 & cpu=x64 381 | languageName: node 382 | linkType: hard 383 | 384 | "@sec-ant/readable-stream@npm:^0.4.1": 385 | version: 0.4.1 386 | resolution: "@sec-ant/readable-stream@npm:0.4.1" 387 | checksum: eb56f72a70995f725269f1c1c206d6dbeb090e88413b1302a456c600041175a7a484c2f0172454f7bed65a8ab95ffed7647d8ad03e6c23b1e3bbc9845f78cd17 388 | languageName: node 389 | linkType: hard 390 | 391 | "@sindresorhus/merge-streams@npm:^4.0.0": 392 | version: 4.0.0 393 | resolution: "@sindresorhus/merge-streams@npm:4.0.0" 394 | checksum: 5759d31dfd822999bbe3ddcf72d4b15dc3d99ea51dd5b3210888f3348234eaff0f44bc999bef6b3c328daeb34e862a63b2c4abe5590acec541f93bc6fa016c9d 395 | languageName: node 396 | linkType: hard 397 | 398 | "@tootallnate/once@npm:2": 399 | version: 2.0.0 400 | resolution: "@tootallnate/once@npm:2.0.0" 401 | checksum: ad87447820dd3f24825d2d947ebc03072b20a42bfc96cbafec16bff8bbda6c1a81fcb0be56d5b21968560c5359a0af4038a68ba150c3e1694fe4c109a063bed8 402 | languageName: node 403 | linkType: hard 404 | 405 | "@types/estree@npm:1.0.5, @types/estree@npm:^1.0.0": 406 | version: 1.0.5 407 | resolution: "@types/estree@npm:1.0.5" 408 | checksum: dd8b5bed28e6213b7acd0fb665a84e693554d850b0df423ac8076cc3ad5823a6bc26b0251d080bdc545af83179ede51dd3f6fa78cad2c46ed1f29624ddf3e41a 409 | languageName: node 410 | linkType: hard 411 | 412 | "@types/prettier@npm:^3.0.0": 413 | version: 3.0.0 414 | resolution: "@types/prettier@npm:3.0.0" 415 | dependencies: 416 | prettier: "*" 417 | checksum: a2a512d304e5bcf78f38089dc88ad19215e6ab871d435a17aef3ce538a63b07c0e359c18db23989dc1ed9fff96d99eee1f680416080184df5c7e0e3bf767e165 418 | languageName: node 419 | linkType: hard 420 | 421 | "@vitest/expect@npm:2.0.2": 422 | version: 2.0.2 423 | resolution: "@vitest/expect@npm:2.0.2" 424 | dependencies: 425 | "@vitest/spy": 2.0.2 426 | "@vitest/utils": 2.0.2 427 | chai: ^5.1.1 428 | tinyrainbow: ^1.2.0 429 | checksum: d7a1c05e5b852f332777376fa442a0dff893d09f3b0ad9a9bd8292155aad4f63026c785e4725ffa59bd58e7d2c1fd816f7208c4347620b2644943afd37c2cc9f 430 | languageName: node 431 | linkType: hard 432 | 433 | "@vitest/pretty-format@npm:2.0.2, @vitest/pretty-format@npm:^2.0.2": 434 | version: 2.0.2 435 | resolution: "@vitest/pretty-format@npm:2.0.2" 436 | dependencies: 437 | tinyrainbow: ^1.2.0 438 | checksum: 0a37f536862548cf531b0d46857c464d90ad06163b28590fbb51ba96242ffeff902b778bb0667dec93b455d07b0be4d549e6619a1aead1d35ad76d2a1c9e6089 439 | languageName: node 440 | linkType: hard 441 | 442 | "@vitest/runner@npm:2.0.2": 443 | version: 2.0.2 444 | resolution: "@vitest/runner@npm:2.0.2" 445 | dependencies: 446 | "@vitest/utils": 2.0.2 447 | pathe: ^1.1.2 448 | checksum: 8e9564a66d0726e22e2a52e4095450ce26f46284c885fd1ea83b89ccbd5bcbd105a0b76058952ab2d84aaa118d23f9db21ca697d547069735fd3f3bb2c1e14fa 449 | languageName: node 450 | linkType: hard 451 | 452 | "@vitest/snapshot@npm:2.0.2": 453 | version: 2.0.2 454 | resolution: "@vitest/snapshot@npm:2.0.2" 455 | dependencies: 456 | "@vitest/pretty-format": 2.0.2 457 | magic-string: ^0.30.10 458 | pathe: ^1.1.2 459 | checksum: bbefd8ab715802cd2dfc4a109029e5e6511a1461694825c852e40712b23fb89d8f8573ceca7568111757c86af7403d3fdf1dff0efe24e0f7f0b1dffee454a0c6 460 | languageName: node 461 | linkType: hard 462 | 463 | "@vitest/spy@npm:2.0.2": 464 | version: 2.0.2 465 | resolution: "@vitest/spy@npm:2.0.2" 466 | dependencies: 467 | tinyspy: ^3.0.0 468 | checksum: 41b1e7438385eb622b59ebcb37a548e8c31ae5599f7f3a69e1f65e82abd4ecfea08c54a34dc10ed0e409a02eb56ee073e54e2f6cd895525abde0116ef8f27039 469 | languageName: node 470 | linkType: hard 471 | 472 | "@vitest/utils@npm:2.0.2": 473 | version: 2.0.2 474 | resolution: "@vitest/utils@npm:2.0.2" 475 | dependencies: 476 | "@vitest/pretty-format": 2.0.2 477 | estree-walker: ^3.0.3 478 | loupe: ^3.1.1 479 | tinyrainbow: ^1.2.0 480 | checksum: ec07f4db8c19f3bcd8f11b43172207ebc95508e3f41e37c8a11940edfc3421d6e7f20b1e00e6f4dcb4ab5ed9bd1d8514254cefedd4789627184d26ee8fb0387e 481 | languageName: node 482 | linkType: hard 483 | 484 | "abbrev@npm:^1.0.0": 485 | version: 1.1.1 486 | resolution: "abbrev@npm:1.1.1" 487 | checksum: a4a97ec07d7ea112c517036882b2ac22f3109b7b19077dc656316d07d308438aac28e4d9746dc4d84bf6b1e75b4a7b0a5f3cb30592419f128ca9a8cee3bcfa17 488 | languageName: node 489 | linkType: hard 490 | 491 | "agent-base@npm:6, agent-base@npm:^6.0.2": 492 | version: 6.0.2 493 | resolution: "agent-base@npm:6.0.2" 494 | dependencies: 495 | debug: 4 496 | checksum: f52b6872cc96fd5f622071b71ef200e01c7c4c454ee68bc9accca90c98cfb39f2810e3e9aa330435835eedc8c23f4f8a15267f67c6e245d2b33757575bdac49d 497 | languageName: node 498 | linkType: hard 499 | 500 | "agentkeepalive@npm:^4.2.1": 501 | version: 4.2.1 502 | resolution: "agentkeepalive@npm:4.2.1" 503 | dependencies: 504 | debug: ^4.1.0 505 | depd: ^1.1.2 506 | humanize-ms: ^1.2.1 507 | checksum: 39cb49ed8cf217fd6da058a92828a0a84e0b74c35550f82ee0a10e1ee403c4b78ade7948be2279b188b7a7303f5d396ea2738b134731e464bf28de00a4f72a18 508 | languageName: node 509 | linkType: hard 510 | 511 | "aggregate-error@npm:^3.0.0": 512 | version: 3.1.0 513 | resolution: "aggregate-error@npm:3.1.0" 514 | dependencies: 515 | clean-stack: ^2.0.0 516 | indent-string: ^4.0.0 517 | checksum: 1101a33f21baa27a2fa8e04b698271e64616b886795fd43c31068c07533c7b3facfcaf4e9e0cab3624bd88f729a592f1c901a1a229c9e490eafce411a8644b79 518 | languageName: node 519 | linkType: hard 520 | 521 | "ansi-regex@npm:^5.0.1": 522 | version: 5.0.1 523 | resolution: "ansi-regex@npm:5.0.1" 524 | checksum: 2aa4bb54caf2d622f1afdad09441695af2a83aa3fe8b8afa581d205e57ed4261c183c4d3877cee25794443fde5876417d859c108078ab788d6af7e4fe52eb66b 525 | languageName: node 526 | linkType: hard 527 | 528 | "ansi-regex@npm:^6.0.1": 529 | version: 6.0.1 530 | resolution: "ansi-regex@npm:6.0.1" 531 | checksum: 1ff8b7667cded1de4fa2c9ae283e979fc87036864317da86a2e546725f96406746411d0d85e87a2d12fa5abd715d90006de7fa4fa0477c92321ad3b4c7d4e169 532 | languageName: node 533 | linkType: hard 534 | 535 | "aproba@npm:^1.0.3 || ^2.0.0": 536 | version: 2.0.0 537 | resolution: "aproba@npm:2.0.0" 538 | checksum: 5615cadcfb45289eea63f8afd064ab656006361020e1735112e346593856f87435e02d8dcc7ff0d11928bc7d425f27bc7c2a84f6c0b35ab0ff659c814c138a24 539 | languageName: node 540 | linkType: hard 541 | 542 | "are-we-there-yet@npm:^3.0.0": 543 | version: 3.0.1 544 | resolution: "are-we-there-yet@npm:3.0.1" 545 | dependencies: 546 | delegates: ^1.0.0 547 | readable-stream: ^3.6.0 548 | checksum: 52590c24860fa7173bedeb69a4c05fb573473e860197f618b9a28432ee4379049336727ae3a1f9c4cb083114601c1140cee578376164d0e651217a9843f9fe83 549 | languageName: node 550 | linkType: hard 551 | 552 | "assertion-error@npm:^2.0.1": 553 | version: 2.0.1 554 | resolution: "assertion-error@npm:2.0.1" 555 | checksum: a0789dd882211b87116e81e2648ccb7f60340b34f19877dd020b39ebb4714e475eb943e14ba3e22201c221ef6645b7bfe10297e76b6ac95b48a9898c1211ce66 556 | languageName: node 557 | linkType: hard 558 | 559 | "balanced-match@npm:^1.0.0": 560 | version: 1.0.2 561 | resolution: "balanced-match@npm:1.0.2" 562 | checksum: 9706c088a283058a8a99e0bf91b0a2f75497f185980d9ffa8b304de1d9e58ebda7c72c07ebf01dadedaac5b2907b2c6f566f660d62bd336c3468e960403b9d65 563 | languageName: node 564 | linkType: hard 565 | 566 | "brace-expansion@npm:^1.1.7": 567 | version: 1.1.11 568 | resolution: "brace-expansion@npm:1.1.11" 569 | dependencies: 570 | balanced-match: ^1.0.0 571 | concat-map: 0.0.1 572 | checksum: faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 573 | languageName: node 574 | linkType: hard 575 | 576 | "brace-expansion@npm:^2.0.1": 577 | version: 2.0.1 578 | resolution: "brace-expansion@npm:2.0.1" 579 | dependencies: 580 | balanced-match: ^1.0.0 581 | checksum: a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 582 | languageName: node 583 | linkType: hard 584 | 585 | "cac@npm:^6.7.14": 586 | version: 6.7.14 587 | resolution: "cac@npm:6.7.14" 588 | checksum: 45a2496a9443abbe7f52a49b22fbe51b1905eff46e03fd5e6c98e3f85077be3f8949685a1849b1a9cd2bc3e5567dfebcf64f01ce01847baf918f1b37c839791a 589 | languageName: node 590 | linkType: hard 591 | 592 | "cacache@npm:^16.1.0": 593 | version: 16.1.3 594 | resolution: "cacache@npm:16.1.3" 595 | dependencies: 596 | "@npmcli/fs": ^2.1.0 597 | "@npmcli/move-file": ^2.0.0 598 | chownr: ^2.0.0 599 | fs-minipass: ^2.1.0 600 | glob: ^8.0.1 601 | infer-owner: ^1.0.4 602 | lru-cache: ^7.7.1 603 | minipass: ^3.1.6 604 | minipass-collect: ^1.0.2 605 | minipass-flush: ^1.0.5 606 | minipass-pipeline: ^1.2.4 607 | mkdirp: ^1.0.4 608 | p-map: ^4.0.0 609 | promise-inflight: ^1.0.1 610 | rimraf: ^3.0.2 611 | ssri: ^9.0.0 612 | tar: ^6.1.11 613 | unique-filename: ^2.0.0 614 | checksum: d91409e6e57d7d9a3a25e5dcc589c84e75b178ae8ea7de05cbf6b783f77a5fae938f6e8fda6f5257ed70000be27a681e1e44829251bfffe4c10216002f8f14e6 615 | languageName: node 616 | linkType: hard 617 | 618 | "chai@npm:^5.1.1": 619 | version: 5.1.1 620 | resolution: "chai@npm:5.1.1" 621 | dependencies: 622 | assertion-error: ^2.0.1 623 | check-error: ^2.1.1 624 | deep-eql: ^5.0.1 625 | loupe: ^3.1.0 626 | pathval: ^2.0.0 627 | checksum: 1e0a5e1b5febdfa8ceb97b9aff608286861ecb86533863119b2f39f07c08fb59f3c1791ab554947f009b9d71d509b9e4e734fb12133cb81f231c2c2ee7c1e738 628 | languageName: node 629 | linkType: hard 630 | 631 | "check-error@npm:^2.1.1": 632 | version: 2.1.1 633 | resolution: "check-error@npm:2.1.1" 634 | checksum: d785ed17b1d4a4796b6e75c765a9a290098cf52ff9728ce0756e8ffd4293d2e419dd30c67200aee34202463b474306913f2fcfaf1890641026d9fc6966fea27a 635 | languageName: node 636 | linkType: hard 637 | 638 | "chownr@npm:^2.0.0": 639 | version: 2.0.0 640 | resolution: "chownr@npm:2.0.0" 641 | checksum: c57cf9dd0791e2f18a5ee9c1a299ae6e801ff58fee96dc8bfd0dcb4738a6ce58dd252a3605b1c93c6418fe4f9d5093b28ffbf4d66648cb2a9c67eaef9679be2f 642 | languageName: node 643 | linkType: hard 644 | 645 | "clean-stack@npm:^2.0.0": 646 | version: 2.2.0 647 | resolution: "clean-stack@npm:2.2.0" 648 | checksum: 2ac8cd2b2f5ec986a3c743935ec85b07bc174d5421a5efc8017e1f146a1cf5f781ae962618f416352103b32c9cd7e203276e8c28241bbe946160cab16149fb68 649 | languageName: node 650 | linkType: hard 651 | 652 | "color-support@npm:^1.1.3": 653 | version: 1.1.3 654 | resolution: "color-support@npm:1.1.3" 655 | bin: 656 | color-support: bin.js 657 | checksum: 9b7356817670b9a13a26ca5af1c21615463b500783b739b7634a0c2047c16cef4b2865d7576875c31c3cddf9dd621fa19285e628f20198b233a5cfdda6d0793b 658 | languageName: node 659 | linkType: hard 660 | 661 | "concat-map@npm:0.0.1": 662 | version: 0.0.1 663 | resolution: "concat-map@npm:0.0.1" 664 | checksum: 902a9f5d8967a3e2faf138d5cb784b9979bad2e6db5357c5b21c568df4ebe62bcb15108af1b2253744844eb964fc023fbd9afbbbb6ddd0bcc204c6fb5b7bf3af 665 | languageName: node 666 | linkType: hard 667 | 668 | "console-control-strings@npm:^1.1.0": 669 | version: 1.1.0 670 | resolution: "console-control-strings@npm:1.1.0" 671 | checksum: 8755d76787f94e6cf79ce4666f0c5519906d7f5b02d4b884cf41e11dcd759ed69c57da0670afd9236d229a46e0f9cf519db0cd829c6dca820bb5a5c3def584ed 672 | languageName: node 673 | linkType: hard 674 | 675 | "cross-spawn@npm:^7.0.3": 676 | version: 7.0.3 677 | resolution: "cross-spawn@npm:7.0.3" 678 | dependencies: 679 | path-key: ^3.1.0 680 | shebang-command: ^2.0.0 681 | which: ^2.0.1 682 | checksum: 671cc7c7288c3a8406f3c69a3ae2fc85555c04169e9d611def9a675635472614f1c0ed0ef80955d5b6d4e724f6ced67f0ad1bb006c2ea643488fcfef994d7f52 683 | languageName: node 684 | linkType: hard 685 | 686 | "debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.3.3": 687 | version: 4.3.4 688 | resolution: "debug@npm:4.3.4" 689 | dependencies: 690 | ms: 2.1.2 691 | peerDependenciesMeta: 692 | supports-color: 693 | optional: true 694 | checksum: 3dbad3f94ea64f34431a9cbf0bafb61853eda57bff2880036153438f50fb5a84f27683ba0d8e5426bf41a8c6ff03879488120cf5b3a761e77953169c0600a708 695 | languageName: node 696 | linkType: hard 697 | 698 | "debug@npm:^4.3.5": 699 | version: 4.3.5 700 | resolution: "debug@npm:4.3.5" 701 | dependencies: 702 | ms: 2.1.2 703 | peerDependenciesMeta: 704 | supports-color: 705 | optional: true 706 | checksum: 7c002b51e256257f936dda09eb37167df952758c57badf6bf44bdc40b89a4bcb8e5a0a2e4c7b53f97c69e2970dd5272d33a757378a12c8f8e64ea7bf99e8e86e 707 | languageName: node 708 | linkType: hard 709 | 710 | "deep-eql@npm:^5.0.1": 711 | version: 5.0.2 712 | resolution: "deep-eql@npm:5.0.2" 713 | checksum: 6aaaadb4c19cbce42e26b2bbe5bd92875f599d2602635dc97f0294bae48da79e89470aedee05f449e0ca8c65e9fd7e7872624d1933a1db02713d99c2ca8d1f24 714 | languageName: node 715 | linkType: hard 716 | 717 | "delegates@npm:^1.0.0": 718 | version: 1.0.0 719 | resolution: "delegates@npm:1.0.0" 720 | checksum: a51744d9b53c164ba9c0492471a1a2ffa0b6727451bdc89e31627fdf4adda9d51277cfcbfb20f0a6f08ccb3c436f341df3e92631a3440226d93a8971724771fd 721 | languageName: node 722 | linkType: hard 723 | 724 | "depd@npm:^1.1.2": 725 | version: 1.1.2 726 | resolution: "depd@npm:1.1.2" 727 | checksum: 6b406620d269619852885ce15965272b829df6f409724415e0002c8632ab6a8c0a08ec1f0bd2add05dc7bd7507606f7e2cc034fa24224ab829580040b835ecd9 728 | languageName: node 729 | linkType: hard 730 | 731 | "emoji-regex@npm:^8.0.0": 732 | version: 8.0.0 733 | resolution: "emoji-regex@npm:8.0.0" 734 | checksum: d4c5c39d5a9868b5fa152f00cada8a936868fd3367f33f71be515ecee4c803132d11b31a6222b2571b1e5f7e13890156a94880345594d0ce7e3c9895f560f192 735 | languageName: node 736 | linkType: hard 737 | 738 | "encoding@npm:^0.1.13": 739 | version: 0.1.13 740 | resolution: "encoding@npm:0.1.13" 741 | dependencies: 742 | iconv-lite: ^0.6.2 743 | checksum: bb98632f8ffa823996e508ce6a58ffcf5856330fde839ae42c9e1f436cc3b5cc651d4aeae72222916545428e54fd0f6aa8862fd8d25bdbcc4589f1e3f3715e7f 744 | languageName: node 745 | linkType: hard 746 | 747 | "env-paths@npm:^2.2.0": 748 | version: 2.2.1 749 | resolution: "env-paths@npm:2.2.1" 750 | checksum: 65b5df55a8bab92229ab2b40dad3b387fad24613263d103a97f91c9fe43ceb21965cd3392b1ccb5d77088021e525c4e0481adb309625d0cb94ade1d1fb8dc17e 751 | languageName: node 752 | linkType: hard 753 | 754 | "err-code@npm:^2.0.2": 755 | version: 2.0.3 756 | resolution: "err-code@npm:2.0.3" 757 | checksum: 8b7b1be20d2de12d2255c0bc2ca638b7af5171142693299416e6a9339bd7d88fc8d7707d913d78e0993176005405a236b066b45666b27b797252c771156ace54 758 | languageName: node 759 | linkType: hard 760 | 761 | "esbuild@npm:^0.21.3": 762 | version: 0.21.5 763 | resolution: "esbuild@npm:0.21.5" 764 | dependencies: 765 | "@esbuild/aix-ppc64": 0.21.5 766 | "@esbuild/android-arm": 0.21.5 767 | "@esbuild/android-arm64": 0.21.5 768 | "@esbuild/android-x64": 0.21.5 769 | "@esbuild/darwin-arm64": 0.21.5 770 | "@esbuild/darwin-x64": 0.21.5 771 | "@esbuild/freebsd-arm64": 0.21.5 772 | "@esbuild/freebsd-x64": 0.21.5 773 | "@esbuild/linux-arm": 0.21.5 774 | "@esbuild/linux-arm64": 0.21.5 775 | "@esbuild/linux-ia32": 0.21.5 776 | "@esbuild/linux-loong64": 0.21.5 777 | "@esbuild/linux-mips64el": 0.21.5 778 | "@esbuild/linux-ppc64": 0.21.5 779 | "@esbuild/linux-riscv64": 0.21.5 780 | "@esbuild/linux-s390x": 0.21.5 781 | "@esbuild/linux-x64": 0.21.5 782 | "@esbuild/netbsd-x64": 0.21.5 783 | "@esbuild/openbsd-x64": 0.21.5 784 | "@esbuild/sunos-x64": 0.21.5 785 | "@esbuild/win32-arm64": 0.21.5 786 | "@esbuild/win32-ia32": 0.21.5 787 | "@esbuild/win32-x64": 0.21.5 788 | dependenciesMeta: 789 | "@esbuild/aix-ppc64": 790 | optional: true 791 | "@esbuild/android-arm": 792 | optional: true 793 | "@esbuild/android-arm64": 794 | optional: true 795 | "@esbuild/android-x64": 796 | optional: true 797 | "@esbuild/darwin-arm64": 798 | optional: true 799 | "@esbuild/darwin-x64": 800 | optional: true 801 | "@esbuild/freebsd-arm64": 802 | optional: true 803 | "@esbuild/freebsd-x64": 804 | optional: true 805 | "@esbuild/linux-arm": 806 | optional: true 807 | "@esbuild/linux-arm64": 808 | optional: true 809 | "@esbuild/linux-ia32": 810 | optional: true 811 | "@esbuild/linux-loong64": 812 | optional: true 813 | "@esbuild/linux-mips64el": 814 | optional: true 815 | "@esbuild/linux-ppc64": 816 | optional: true 817 | "@esbuild/linux-riscv64": 818 | optional: true 819 | "@esbuild/linux-s390x": 820 | optional: true 821 | "@esbuild/linux-x64": 822 | optional: true 823 | "@esbuild/netbsd-x64": 824 | optional: true 825 | "@esbuild/openbsd-x64": 826 | optional: true 827 | "@esbuild/sunos-x64": 828 | optional: true 829 | "@esbuild/win32-arm64": 830 | optional: true 831 | "@esbuild/win32-ia32": 832 | optional: true 833 | "@esbuild/win32-x64": 834 | optional: true 835 | bin: 836 | esbuild: bin/esbuild 837 | checksum: 2911c7b50b23a9df59a7d6d4cdd3a4f85855787f374dce751148dbb13305e0ce7e880dde1608c2ab7a927fc6cec3587b80995f7fc87a64b455f8b70b55fd8ec1 838 | languageName: node 839 | linkType: hard 840 | 841 | "estree-walker@npm:^3.0.3": 842 | version: 3.0.3 843 | resolution: "estree-walker@npm:3.0.3" 844 | dependencies: 845 | "@types/estree": ^1.0.0 846 | checksum: a65728d5727b71de172c5df323385755a16c0fdab8234dc756c3854cfee343261ddfbb72a809a5660fac8c75d960bb3e21aa898c2d7e9b19bb298482ca58a3af 847 | languageName: node 848 | linkType: hard 849 | 850 | "execa@npm:^8.0.1": 851 | version: 8.0.1 852 | resolution: "execa@npm:8.0.1" 853 | dependencies: 854 | cross-spawn: ^7.0.3 855 | get-stream: ^8.0.1 856 | human-signals: ^5.0.0 857 | is-stream: ^3.0.0 858 | merge-stream: ^2.0.0 859 | npm-run-path: ^5.1.0 860 | onetime: ^6.0.0 861 | signal-exit: ^4.1.0 862 | strip-final-newline: ^3.0.0 863 | checksum: cac1bf86589d1d9b73bdc5dda65c52012d1a9619c44c526891956745f7b366ca2603d29fe3f7460bacc2b48c6eab5d6a4f7afe0534b31473d3708d1265545e1f 864 | languageName: node 865 | linkType: hard 866 | 867 | "execa@npm:^9.3.0": 868 | version: 9.3.0 869 | resolution: "execa@npm:9.3.0" 870 | dependencies: 871 | "@sindresorhus/merge-streams": ^4.0.0 872 | cross-spawn: ^7.0.3 873 | figures: ^6.1.0 874 | get-stream: ^9.0.0 875 | human-signals: ^7.0.0 876 | is-plain-obj: ^4.1.0 877 | is-stream: ^4.0.1 878 | npm-run-path: ^5.2.0 879 | pretty-ms: ^9.0.0 880 | signal-exit: ^4.1.0 881 | strip-final-newline: ^4.0.0 882 | yoctocolors: ^2.0.0 883 | checksum: d07b28405edf74e3db7ec63b07e54318c58f1a97522064e4e760a257b4d3a9888d9fa7add62ff28c9c26b062a3a311bceea52dea23bf27433a8a19d85a95bdf4 884 | languageName: node 885 | linkType: hard 886 | 887 | "figures@npm:^6.1.0": 888 | version: 6.1.0 889 | resolution: "figures@npm:6.1.0" 890 | dependencies: 891 | is-unicode-supported: ^2.0.0 892 | checksum: 35c81239d4fa40b75c2c7c010833b0bc8861c27187e4c9388fca1d9731103ec9989b70ee3b664ef426ddd9abe02ec5f4fd973424aa8c6fd3ea5d3bf57a2d01b4 893 | languageName: node 894 | linkType: hard 895 | 896 | "fs-minipass@npm:^2.0.0, fs-minipass@npm:^2.1.0": 897 | version: 2.1.0 898 | resolution: "fs-minipass@npm:2.1.0" 899 | dependencies: 900 | minipass: ^3.0.0 901 | checksum: 1b8d128dae2ac6cc94230cc5ead341ba3e0efaef82dab46a33d171c044caaa6ca001364178d42069b2809c35a1c3c35079a32107c770e9ffab3901b59af8c8b1 902 | languageName: node 903 | linkType: hard 904 | 905 | "fs.realpath@npm:^1.0.0": 906 | version: 1.0.0 907 | resolution: "fs.realpath@npm:1.0.0" 908 | checksum: 99ddea01a7e75aa276c250a04eedeffe5662bce66c65c07164ad6264f9de18fb21be9433ead460e54cff20e31721c811f4fb5d70591799df5f85dce6d6746fd0 909 | languageName: node 910 | linkType: hard 911 | 912 | "fsevents@npm:~2.3.2": 913 | version: 2.3.2 914 | resolution: "fsevents@npm:2.3.2" 915 | dependencies: 916 | node-gyp: latest 917 | checksum: 97ade64e75091afee5265e6956cb72ba34db7819b4c3e94c431d4be2b19b8bb7a2d4116da417950c3425f17c8fe693d25e20212cac583ac1521ad066b77ae31f 918 | conditions: os=darwin 919 | languageName: node 920 | linkType: hard 921 | 922 | "fsevents@npm:~2.3.3": 923 | version: 2.3.3 924 | resolution: "fsevents@npm:2.3.3" 925 | dependencies: 926 | node-gyp: latest 927 | checksum: 11e6ea6fea15e42461fc55b4b0e4a0a3c654faa567f1877dbd353f39156f69def97a69936d1746619d656c4b93de2238bf731f6085a03a50cabf287c9d024317 928 | conditions: os=darwin 929 | languageName: node 930 | linkType: hard 931 | 932 | "fsevents@patch:fsevents@~2.3.2#~builtin": 933 | version: 2.3.2 934 | resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1" 935 | dependencies: 936 | node-gyp: latest 937 | conditions: os=darwin 938 | languageName: node 939 | linkType: hard 940 | 941 | "fsevents@patch:fsevents@~2.3.3#~builtin": 942 | version: 2.3.3 943 | resolution: "fsevents@patch:fsevents@npm%3A2.3.3#~builtin::version=2.3.3&hash=df0bf1" 944 | dependencies: 945 | node-gyp: latest 946 | conditions: os=darwin 947 | languageName: node 948 | linkType: hard 949 | 950 | "gauge@npm:^4.0.3": 951 | version: 4.0.4 952 | resolution: "gauge@npm:4.0.4" 953 | dependencies: 954 | aproba: ^1.0.3 || ^2.0.0 955 | color-support: ^1.1.3 956 | console-control-strings: ^1.1.0 957 | has-unicode: ^2.0.1 958 | signal-exit: ^3.0.7 959 | string-width: ^4.2.3 960 | strip-ansi: ^6.0.1 961 | wide-align: ^1.1.5 962 | checksum: 788b6bfe52f1dd8e263cda800c26ac0ca2ff6de0b6eee2fe0d9e3abf15e149b651bd27bf5226be10e6e3edb5c4e5d5985a5a1a98137e7a892f75eff76467ad2d 963 | languageName: node 964 | linkType: hard 965 | 966 | "get-func-name@npm:^2.0.1": 967 | version: 2.0.2 968 | resolution: "get-func-name@npm:2.0.2" 969 | checksum: 3f62f4c23647de9d46e6f76d2b3eafe58933a9b3830c60669e4180d6c601ce1b4aa310ba8366143f55e52b139f992087a9f0647274e8745621fa2af7e0acf13b 970 | languageName: node 971 | linkType: hard 972 | 973 | "get-stream@npm:^8.0.1": 974 | version: 8.0.1 975 | resolution: "get-stream@npm:8.0.1" 976 | checksum: 01e3d3cf29e1393f05f44d2f00445c5f9ec3d1c49e8179b31795484b9c117f4c695e5e07b88b50785d5c8248a788c85d9913a79266fc77e3ef11f78f10f1b974 977 | languageName: node 978 | linkType: hard 979 | 980 | "get-stream@npm:^9.0.0": 981 | version: 9.0.1 982 | resolution: "get-stream@npm:9.0.1" 983 | dependencies: 984 | "@sec-ant/readable-stream": ^0.4.1 985 | is-stream: ^4.0.1 986 | checksum: 631df71d7bd60a7f373094d3c352e2ce412b82d30b1b0ec562e5a4aced976173a4cc0dabef019050e1aceaffb1f0e086349ab3d14377b0b7280510bd75bd3e1e 987 | languageName: node 988 | linkType: hard 989 | 990 | "glob@npm:^7.1.3, glob@npm:^7.1.4": 991 | version: 7.2.3 992 | resolution: "glob@npm:7.2.3" 993 | dependencies: 994 | fs.realpath: ^1.0.0 995 | inflight: ^1.0.4 996 | inherits: 2 997 | minimatch: ^3.1.1 998 | once: ^1.3.0 999 | path-is-absolute: ^1.0.0 1000 | checksum: 29452e97b38fa704dabb1d1045350fb2467cf0277e155aa9ff7077e90ad81d1ea9d53d3ee63bd37c05b09a065e90f16aec4a65f5b8de401d1dac40bc5605d133 1001 | languageName: node 1002 | linkType: hard 1003 | 1004 | "glob@npm:^8.0.1": 1005 | version: 8.0.3 1006 | resolution: "glob@npm:8.0.3" 1007 | dependencies: 1008 | fs.realpath: ^1.0.0 1009 | inflight: ^1.0.4 1010 | inherits: 2 1011 | minimatch: ^5.0.1 1012 | once: ^1.3.0 1013 | checksum: 50bcdea19d8e79d8de5f460b1939ffc2b3299eac28deb502093fdca22a78efebc03e66bf54f0abc3d3d07d8134d19a32850288b7440d77e072aa55f9d33b18c5 1014 | languageName: node 1015 | linkType: hard 1016 | 1017 | "graceful-fs@npm:^4.2.6": 1018 | version: 4.2.10 1019 | resolution: "graceful-fs@npm:4.2.10" 1020 | checksum: 3f109d70ae123951905d85032ebeae3c2a5a7a997430df00ea30df0e3a6c60cf6689b109654d6fdacd28810a053348c4d14642da1d075049e6be1ba5216218da 1021 | languageName: node 1022 | linkType: hard 1023 | 1024 | "has-unicode@npm:^2.0.1": 1025 | version: 2.0.1 1026 | resolution: "has-unicode@npm:2.0.1" 1027 | checksum: 1eab07a7436512db0be40a710b29b5dc21fa04880b7f63c9980b706683127e3c1b57cb80ea96d47991bdae2dfe479604f6a1ba410106ee1046a41d1bd0814400 1028 | languageName: node 1029 | linkType: hard 1030 | 1031 | "http-cache-semantics@npm:^4.1.0": 1032 | version: 4.1.0 1033 | resolution: "http-cache-semantics@npm:4.1.0" 1034 | checksum: 974de94a81c5474be07f269f9fd8383e92ebb5a448208223bfb39e172a9dbc26feff250192ecc23b9593b3f92098e010406b0f24bd4d588d631f80214648ed42 1035 | languageName: node 1036 | linkType: hard 1037 | 1038 | "http-proxy-agent@npm:^5.0.0": 1039 | version: 5.0.0 1040 | resolution: "http-proxy-agent@npm:5.0.0" 1041 | dependencies: 1042 | "@tootallnate/once": 2 1043 | agent-base: 6 1044 | debug: 4 1045 | checksum: e2ee1ff1656a131953839b2a19cd1f3a52d97c25ba87bd2559af6ae87114abf60971e498021f9b73f9fd78aea8876d1fb0d4656aac8a03c6caa9fc175f22b786 1046 | languageName: node 1047 | linkType: hard 1048 | 1049 | "https-proxy-agent@npm:^5.0.0": 1050 | version: 5.0.1 1051 | resolution: "https-proxy-agent@npm:5.0.1" 1052 | dependencies: 1053 | agent-base: 6 1054 | debug: 4 1055 | checksum: 571fccdf38184f05943e12d37d6ce38197becdd69e58d03f43637f7fa1269cf303a7d228aa27e5b27bbd3af8f09fd938e1c91dcfefff2df7ba77c20ed8dfc765 1056 | languageName: node 1057 | linkType: hard 1058 | 1059 | "human-signals@npm:^5.0.0": 1060 | version: 5.0.0 1061 | resolution: "human-signals@npm:5.0.0" 1062 | checksum: 6504560d5ed91444f16bea3bd9dfc66110a339442084e56c3e7fa7bbdf3f406426d6563d662bdce67064b165eac31eeabfc0857ed170aaa612cf14ec9f9a464c 1063 | languageName: node 1064 | linkType: hard 1065 | 1066 | "human-signals@npm:^7.0.0": 1067 | version: 7.0.0 1068 | resolution: "human-signals@npm:7.0.0" 1069 | checksum: 5e05a7dbb6d021371ddb854c58b19aa372cc616b34e8eec0d27098d699be0571e29b2b98869053d898badb9594b7ed5058642660b04fb1e41b7bd1f83e472d16 1070 | languageName: node 1071 | linkType: hard 1072 | 1073 | "humanize-ms@npm:^1.2.1": 1074 | version: 1.2.1 1075 | resolution: "humanize-ms@npm:1.2.1" 1076 | dependencies: 1077 | ms: ^2.0.0 1078 | checksum: 9c7a74a2827f9294c009266c82031030eae811ca87b0da3dceb8d6071b9bde22c9f3daef0469c3c533cc67a97d8a167cd9fc0389350e5f415f61a79b171ded16 1079 | languageName: node 1080 | linkType: hard 1081 | 1082 | "iconv-lite@npm:^0.6.2": 1083 | version: 0.6.3 1084 | resolution: "iconv-lite@npm:0.6.3" 1085 | dependencies: 1086 | safer-buffer: ">= 2.1.2 < 3.0.0" 1087 | checksum: 3f60d47a5c8fc3313317edfd29a00a692cc87a19cac0159e2ce711d0ebc9019064108323b5e493625e25594f11c6236647d8e256fbe7a58f4a3b33b89e6d30bf 1088 | languageName: node 1089 | linkType: hard 1090 | 1091 | "imurmurhash@npm:^0.1.4": 1092 | version: 0.1.4 1093 | resolution: "imurmurhash@npm:0.1.4" 1094 | checksum: 7cae75c8cd9a50f57dadd77482359f659eaebac0319dd9368bcd1714f55e65badd6929ca58569da2b6494ef13fdd5598cd700b1eba23f8b79c5f19d195a3ecf7 1095 | languageName: node 1096 | linkType: hard 1097 | 1098 | "indent-string@npm:^4.0.0": 1099 | version: 4.0.0 1100 | resolution: "indent-string@npm:4.0.0" 1101 | checksum: 824cfb9929d031dabf059bebfe08cf3137365e112019086ed3dcff6a0a7b698cb80cf67ccccde0e25b9e2d7527aa6cc1fed1ac490c752162496caba3e6699612 1102 | languageName: node 1103 | linkType: hard 1104 | 1105 | "infer-owner@npm:^1.0.4": 1106 | version: 1.0.4 1107 | resolution: "infer-owner@npm:1.0.4" 1108 | checksum: 181e732764e4a0611576466b4b87dac338972b839920b2a8cde43642e4ed6bd54dc1fb0b40874728f2a2df9a1b097b8ff83b56d5f8f8e3927f837fdcb47d8a89 1109 | languageName: node 1110 | linkType: hard 1111 | 1112 | "inflight@npm:^1.0.4": 1113 | version: 1.0.6 1114 | resolution: "inflight@npm:1.0.6" 1115 | dependencies: 1116 | once: ^1.3.0 1117 | wrappy: 1 1118 | checksum: f4f76aa072ce19fae87ce1ef7d221e709afb59d445e05d47fba710e85470923a75de35bfae47da6de1b18afc3ce83d70facf44cfb0aff89f0a3f45c0a0244dfd 1119 | languageName: node 1120 | linkType: hard 1121 | 1122 | "inherits@npm:2, inherits@npm:^2.0.3": 1123 | version: 2.0.4 1124 | resolution: "inherits@npm:2.0.4" 1125 | checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 1126 | languageName: node 1127 | linkType: hard 1128 | 1129 | "ip@npm:^2.0.0": 1130 | version: 2.0.0 1131 | resolution: "ip@npm:2.0.0" 1132 | checksum: cfcfac6b873b701996d71ec82a7dd27ba92450afdb421e356f44044ed688df04567344c36cbacea7d01b1c39a4c732dc012570ebe9bebfb06f27314bca625349 1133 | languageName: node 1134 | linkType: hard 1135 | 1136 | "is-fullwidth-code-point@npm:^3.0.0": 1137 | version: 3.0.0 1138 | resolution: "is-fullwidth-code-point@npm:3.0.0" 1139 | checksum: 44a30c29457c7fb8f00297bce733f0a64cd22eca270f83e58c105e0d015e45c019491a4ab2faef91ab51d4738c670daff901c799f6a700e27f7314029e99e348 1140 | languageName: node 1141 | linkType: hard 1142 | 1143 | "is-lambda@npm:^1.0.1": 1144 | version: 1.0.1 1145 | resolution: "is-lambda@npm:1.0.1" 1146 | checksum: 93a32f01940220532e5948538699ad610d5924ac86093fcee83022252b363eb0cc99ba53ab084a04e4fb62bf7b5731f55496257a4c38adf87af9c4d352c71c35 1147 | languageName: node 1148 | linkType: hard 1149 | 1150 | "is-plain-obj@npm:^4.1.0": 1151 | version: 4.1.0 1152 | resolution: "is-plain-obj@npm:4.1.0" 1153 | checksum: 6dc45da70d04a81f35c9310971e78a6a3c7a63547ef782e3a07ee3674695081b6ca4e977fbb8efc48dae3375e0b34558d2bcd722aec9bddfa2d7db5b041be8ce 1154 | languageName: node 1155 | linkType: hard 1156 | 1157 | "is-stream@npm:^3.0.0": 1158 | version: 3.0.0 1159 | resolution: "is-stream@npm:3.0.0" 1160 | checksum: 172093fe99119ffd07611ab6d1bcccfe8bc4aa80d864b15f43e63e54b7abc71e779acd69afdb854c4e2a67fdc16ae710e370eda40088d1cfc956a50ed82d8f16 1161 | languageName: node 1162 | linkType: hard 1163 | 1164 | "is-stream@npm:^4.0.1": 1165 | version: 4.0.1 1166 | resolution: "is-stream@npm:4.0.1" 1167 | checksum: cbea3f1fc271b21ceb228819d0c12a0965a02b57f39423925f99530b4eb86935235f258f06310b67cd02b2d10b49e9a0998f5ececf110ab7d3760bae4055ad23 1168 | languageName: node 1169 | linkType: hard 1170 | 1171 | "is-unicode-supported@npm:^2.0.0": 1172 | version: 2.0.0 1173 | resolution: "is-unicode-supported@npm:2.0.0" 1174 | checksum: 000b80639dedaf59a385f1c0a57f97a4d1435e0723716f24cc19ad94253a7a0a9f838bdc9ac49b10a29ac93b01f52ae9b2ed358a8876caf1eb74d73b4ede92b2 1175 | languageName: node 1176 | linkType: hard 1177 | 1178 | "isexe@npm:^2.0.0": 1179 | version: 2.0.0 1180 | resolution: "isexe@npm:2.0.0" 1181 | checksum: 26bf6c5480dda5161c820c5b5c751ae1e766c587b1f951ea3fcfc973bafb7831ae5b54a31a69bd670220e42e99ec154475025a468eae58ea262f813fdc8d1c62 1182 | languageName: node 1183 | linkType: hard 1184 | 1185 | "loupe@npm:^3.1.0, loupe@npm:^3.1.1": 1186 | version: 3.1.1 1187 | resolution: "loupe@npm:3.1.1" 1188 | dependencies: 1189 | get-func-name: ^2.0.1 1190 | checksum: c7efa6bc6d71f25ca03eb13c9a069e35ed86799e308ca27a7a3eff8cdf9500e7c22d1f2411468d154a8e960e91e5e685e0c6c83e96db748f177c1adf30811153 1191 | languageName: node 1192 | linkType: hard 1193 | 1194 | "lru-cache@npm:^6.0.0": 1195 | version: 6.0.0 1196 | resolution: "lru-cache@npm:6.0.0" 1197 | dependencies: 1198 | yallist: ^4.0.0 1199 | checksum: f97f499f898f23e4585742138a22f22526254fdba6d75d41a1c2526b3b6cc5747ef59c5612ba7375f42aca4f8461950e925ba08c991ead0651b4918b7c978297 1200 | languageName: node 1201 | linkType: hard 1202 | 1203 | "lru-cache@npm:^7.7.1": 1204 | version: 7.14.1 1205 | resolution: "lru-cache@npm:7.14.1" 1206 | checksum: d72c6713c6a6d86836a7a6523b3f1ac6764768cca47ec99341c3e76db06aacd4764620e5e2cda719a36848785a52a70e531822dc2b33fb071fa709683746c104 1207 | languageName: node 1208 | linkType: hard 1209 | 1210 | "magic-string@npm:^0.30.10": 1211 | version: 0.30.10 1212 | resolution: "magic-string@npm:0.30.10" 1213 | dependencies: 1214 | "@jridgewell/sourcemap-codec": ^1.4.15 1215 | checksum: 456fd47c39b296c47dff967e1965121ace35417eab7f45a99e681e725b8661b48e1573c366ee67a27715025b3740773c46b088f115421c7365ea4ea6fa10d399 1216 | languageName: node 1217 | linkType: hard 1218 | 1219 | "make-fetch-happen@npm:^10.0.3": 1220 | version: 10.2.1 1221 | resolution: "make-fetch-happen@npm:10.2.1" 1222 | dependencies: 1223 | agentkeepalive: ^4.2.1 1224 | cacache: ^16.1.0 1225 | http-cache-semantics: ^4.1.0 1226 | http-proxy-agent: ^5.0.0 1227 | https-proxy-agent: ^5.0.0 1228 | is-lambda: ^1.0.1 1229 | lru-cache: ^7.7.1 1230 | minipass: ^3.1.6 1231 | minipass-collect: ^1.0.2 1232 | minipass-fetch: ^2.0.3 1233 | minipass-flush: ^1.0.5 1234 | minipass-pipeline: ^1.2.4 1235 | negotiator: ^0.6.3 1236 | promise-retry: ^2.0.1 1237 | socks-proxy-agent: ^7.0.0 1238 | ssri: ^9.0.0 1239 | checksum: 2332eb9a8ec96f1ffeeea56ccefabcb4193693597b132cd110734d50f2928842e22b84cfa1508e921b8385cdfd06dda9ad68645fed62b50fff629a580f5fb72c 1240 | languageName: node 1241 | linkType: hard 1242 | 1243 | "merge-stream@npm:^2.0.0": 1244 | version: 2.0.0 1245 | resolution: "merge-stream@npm:2.0.0" 1246 | checksum: 6fa4dcc8d86629705cea944a4b88ef4cb0e07656ebf223fa287443256414283dd25d91c1cd84c77987f2aec5927af1a9db6085757cb43d90eb170ebf4b47f4f4 1247 | languageName: node 1248 | linkType: hard 1249 | 1250 | "mimic-fn@npm:^4.0.0": 1251 | version: 4.0.0 1252 | resolution: "mimic-fn@npm:4.0.0" 1253 | checksum: 995dcece15ee29aa16e188de6633d43a3db4611bcf93620e7e62109ec41c79c0f34277165b8ce5e361205049766e371851264c21ac64ca35499acb5421c2ba56 1254 | languageName: node 1255 | linkType: hard 1256 | 1257 | "minimatch@npm:^3.1.1": 1258 | version: 3.1.2 1259 | resolution: "minimatch@npm:3.1.2" 1260 | dependencies: 1261 | brace-expansion: ^1.1.7 1262 | checksum: c154e566406683e7bcb746e000b84d74465b3a832c45d59912b9b55cd50dee66e5c4b1e5566dba26154040e51672f9aa450a9aef0c97cfc7336b78b7afb9540a 1263 | languageName: node 1264 | linkType: hard 1265 | 1266 | "minimatch@npm:^5.0.1": 1267 | version: 5.1.2 1268 | resolution: "minimatch@npm:5.1.2" 1269 | dependencies: 1270 | brace-expansion: ^2.0.1 1271 | checksum: 32ffda25b9fb8270a1c1beafdb7489dc0e411af553495136509a945691f63c9b6b000eeeaaf8bffe3efa609c1d6d3bc0f5a106f6c3443b5c05da649100ded964 1272 | languageName: node 1273 | linkType: hard 1274 | 1275 | "minipass-collect@npm:^1.0.2": 1276 | version: 1.0.2 1277 | resolution: "minipass-collect@npm:1.0.2" 1278 | dependencies: 1279 | minipass: ^3.0.0 1280 | checksum: 14df761028f3e47293aee72888f2657695ec66bd7d09cae7ad558da30415fdc4752bbfee66287dcc6fd5e6a2fa3466d6c484dc1cbd986525d9393b9523d97f10 1281 | languageName: node 1282 | linkType: hard 1283 | 1284 | "minipass-fetch@npm:^2.0.3": 1285 | version: 2.1.2 1286 | resolution: "minipass-fetch@npm:2.1.2" 1287 | dependencies: 1288 | encoding: ^0.1.13 1289 | minipass: ^3.1.6 1290 | minipass-sized: ^1.0.3 1291 | minizlib: ^2.1.2 1292 | dependenciesMeta: 1293 | encoding: 1294 | optional: true 1295 | checksum: 3f216be79164e915fc91210cea1850e488793c740534985da017a4cbc7a5ff50506956d0f73bb0cb60e4fe91be08b6b61ef35101706d3ef5da2c8709b5f08f91 1296 | languageName: node 1297 | linkType: hard 1298 | 1299 | "minipass-flush@npm:^1.0.5": 1300 | version: 1.0.5 1301 | resolution: "minipass-flush@npm:1.0.5" 1302 | dependencies: 1303 | minipass: ^3.0.0 1304 | checksum: 56269a0b22bad756a08a94b1ffc36b7c9c5de0735a4dd1ab2b06c066d795cfd1f0ac44a0fcae13eece5589b908ecddc867f04c745c7009be0b566421ea0944cf 1305 | languageName: node 1306 | linkType: hard 1307 | 1308 | "minipass-pipeline@npm:^1.2.4": 1309 | version: 1.2.4 1310 | resolution: "minipass-pipeline@npm:1.2.4" 1311 | dependencies: 1312 | minipass: ^3.0.0 1313 | checksum: b14240dac0d29823c3d5911c286069e36d0b81173d7bdf07a7e4a91ecdef92cdff4baaf31ea3746f1c61e0957f652e641223970870e2353593f382112257971b 1314 | languageName: node 1315 | linkType: hard 1316 | 1317 | "minipass-sized@npm:^1.0.3": 1318 | version: 1.0.3 1319 | resolution: "minipass-sized@npm:1.0.3" 1320 | dependencies: 1321 | minipass: ^3.0.0 1322 | checksum: 79076749fcacf21b5d16dd596d32c3b6bf4d6e62abb43868fac21674078505c8b15eaca4e47ed844985a4514854f917d78f588fcd029693709417d8f98b2bd60 1323 | languageName: node 1324 | linkType: hard 1325 | 1326 | "minipass@npm:^3.0.0, minipass@npm:^3.1.1, minipass@npm:^3.1.6": 1327 | version: 3.3.6 1328 | resolution: "minipass@npm:3.3.6" 1329 | dependencies: 1330 | yallist: ^4.0.0 1331 | checksum: a30d083c8054cee83cdcdc97f97e4641a3f58ae743970457b1489ce38ee1167b3aaf7d815cd39ec7a99b9c40397fd4f686e83750e73e652b21cb516f6d845e48 1332 | languageName: node 1333 | linkType: hard 1334 | 1335 | "minipass@npm:^4.0.0": 1336 | version: 4.0.0 1337 | resolution: "minipass@npm:4.0.0" 1338 | dependencies: 1339 | yallist: ^4.0.0 1340 | checksum: 7a609afbf394abfcf9c48e6c90226f471676c8f2a67f07f6838871afb03215ede431d1433feffe1b855455bcb13ef0eb89162841b9796109d6fed8d89790f381 1341 | languageName: node 1342 | linkType: hard 1343 | 1344 | "minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": 1345 | version: 2.1.2 1346 | resolution: "minizlib@npm:2.1.2" 1347 | dependencies: 1348 | minipass: ^3.0.0 1349 | yallist: ^4.0.0 1350 | checksum: f1fdeac0b07cf8f30fcf12f4b586795b97be856edea22b5e9072707be51fc95d41487faec3f265b42973a304fe3a64acd91a44a3826a963e37b37bafde0212c3 1351 | languageName: node 1352 | linkType: hard 1353 | 1354 | "mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": 1355 | version: 1.0.4 1356 | resolution: "mkdirp@npm:1.0.4" 1357 | bin: 1358 | mkdirp: bin/cmd.js 1359 | checksum: a96865108c6c3b1b8e1d5e9f11843de1e077e57737602de1b82030815f311be11f96f09cce59bd5b903d0b29834733e5313f9301e3ed6d6f6fba2eae0df4298f 1360 | languageName: node 1361 | linkType: hard 1362 | 1363 | "ms@npm:2.1.2": 1364 | version: 2.1.2 1365 | resolution: "ms@npm:2.1.2" 1366 | checksum: 673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f 1367 | languageName: node 1368 | linkType: hard 1369 | 1370 | "ms@npm:^2.0.0": 1371 | version: 2.1.3 1372 | resolution: "ms@npm:2.1.3" 1373 | checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d 1374 | languageName: node 1375 | linkType: hard 1376 | 1377 | "nanoid@npm:^3.3.7": 1378 | version: 3.3.7 1379 | resolution: "nanoid@npm:3.3.7" 1380 | bin: 1381 | nanoid: bin/nanoid.cjs 1382 | checksum: d36c427e530713e4ac6567d488b489a36582ef89da1d6d4e3b87eded11eb10d7042a877958c6f104929809b2ab0bafa17652b076cdf84324aa75b30b722204f2 1383 | languageName: node 1384 | linkType: hard 1385 | 1386 | "negotiator@npm:^0.6.3": 1387 | version: 0.6.3 1388 | resolution: "negotiator@npm:0.6.3" 1389 | checksum: b8ffeb1e262eff7968fc90a2b6767b04cfd9842582a9d0ece0af7049537266e7b2506dfb1d107a32f06dd849ab2aea834d5830f7f4d0e5cb7d36e1ae55d021d9 1390 | languageName: node 1391 | linkType: hard 1392 | 1393 | "node-gyp@npm:latest": 1394 | version: 9.3.1 1395 | resolution: "node-gyp@npm:9.3.1" 1396 | dependencies: 1397 | env-paths: ^2.2.0 1398 | glob: ^7.1.4 1399 | graceful-fs: ^4.2.6 1400 | make-fetch-happen: ^10.0.3 1401 | nopt: ^6.0.0 1402 | npmlog: ^6.0.0 1403 | rimraf: ^3.0.2 1404 | semver: ^7.3.5 1405 | tar: ^6.1.2 1406 | which: ^2.0.2 1407 | bin: 1408 | node-gyp: bin/node-gyp.js 1409 | checksum: b860e9976fa645ca0789c69e25387401b4396b93c8375489b5151a6c55cf2640a3b6183c212b38625ef7c508994930b72198338e3d09b9d7ade5acc4aaf51ea7 1410 | languageName: node 1411 | linkType: hard 1412 | 1413 | "nopt@npm:^6.0.0": 1414 | version: 6.0.0 1415 | resolution: "nopt@npm:6.0.0" 1416 | dependencies: 1417 | abbrev: ^1.0.0 1418 | bin: 1419 | nopt: bin/nopt.js 1420 | checksum: 82149371f8be0c4b9ec2f863cc6509a7fd0fa729929c009f3a58e4eb0c9e4cae9920e8f1f8eb46e7d032fec8fb01bede7f0f41a67eb3553b7b8e14fa53de1dac 1421 | languageName: node 1422 | linkType: hard 1423 | 1424 | "npm-run-path@npm:^5.1.0": 1425 | version: 5.1.0 1426 | resolution: "npm-run-path@npm:5.1.0" 1427 | dependencies: 1428 | path-key: ^4.0.0 1429 | checksum: dc184eb5ec239d6a2b990b43236845332ef12f4e0beaa9701de724aa797fe40b6bbd0157fb7639d24d3ab13f5d5cf22d223a19c6300846b8126f335f788bee66 1430 | languageName: node 1431 | linkType: hard 1432 | 1433 | "npm-run-path@npm:^5.2.0": 1434 | version: 5.3.0 1435 | resolution: "npm-run-path@npm:5.3.0" 1436 | dependencies: 1437 | path-key: ^4.0.0 1438 | checksum: ae8e7a89da9594fb9c308f6555c73f618152340dcaae423e5fb3620026fefbec463618a8b761920382d666fa7a2d8d240b6fe320e8a6cdd54dc3687e2b659d25 1439 | languageName: node 1440 | linkType: hard 1441 | 1442 | "npmlog@npm:^6.0.0": 1443 | version: 6.0.2 1444 | resolution: "npmlog@npm:6.0.2" 1445 | dependencies: 1446 | are-we-there-yet: ^3.0.0 1447 | console-control-strings: ^1.1.0 1448 | gauge: ^4.0.3 1449 | set-blocking: ^2.0.0 1450 | checksum: ae238cd264a1c3f22091cdd9e2b106f684297d3c184f1146984ecbe18aaa86343953f26b9520dedd1b1372bc0316905b736c1932d778dbeb1fcf5a1001390e2a 1451 | languageName: node 1452 | linkType: hard 1453 | 1454 | "once@npm:^1.3.0": 1455 | version: 1.4.0 1456 | resolution: "once@npm:1.4.0" 1457 | dependencies: 1458 | wrappy: 1 1459 | checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 1460 | languageName: node 1461 | linkType: hard 1462 | 1463 | "onetime@npm:^6.0.0": 1464 | version: 6.0.0 1465 | resolution: "onetime@npm:6.0.0" 1466 | dependencies: 1467 | mimic-fn: ^4.0.0 1468 | checksum: 0846ce78e440841335d4e9182ef69d5762e9f38aa7499b19f42ea1c4cd40f0b4446094c455c713f9adac3f4ae86f613bb5e30c99e52652764d06a89f709b3788 1469 | languageName: node 1470 | linkType: hard 1471 | 1472 | "p-map@npm:^4.0.0": 1473 | version: 4.0.0 1474 | resolution: "p-map@npm:4.0.0" 1475 | dependencies: 1476 | aggregate-error: ^3.0.0 1477 | checksum: cb0ab21ec0f32ddffd31dfc250e3afa61e103ef43d957cc45497afe37513634589316de4eb88abdfd969fe6410c22c0b93ab24328833b8eb1ccc087fc0442a1c 1478 | languageName: node 1479 | linkType: hard 1480 | 1481 | "parse-ms@npm:^4.0.0": 1482 | version: 4.0.0 1483 | resolution: "parse-ms@npm:4.0.0" 1484 | checksum: 673c801d9f957ff79962d71ed5a24850163f4181a90dd30c4e3666b3a804f53b77f1f0556792e8b2adbb5d58757907d1aa51d7d7dc75997c2a56d72937cbc8b7 1485 | languageName: node 1486 | linkType: hard 1487 | 1488 | "path-is-absolute@npm:^1.0.0": 1489 | version: 1.0.1 1490 | resolution: "path-is-absolute@npm:1.0.1" 1491 | checksum: 060840f92cf8effa293bcc1bea81281bd7d363731d214cbe5c227df207c34cd727430f70c6037b5159c8a870b9157cba65e775446b0ab06fd5ecc7e54615a3b8 1492 | languageName: node 1493 | linkType: hard 1494 | 1495 | "path-key@npm:^3.1.0": 1496 | version: 3.1.1 1497 | resolution: "path-key@npm:3.1.1" 1498 | checksum: 55cd7a9dd4b343412a8386a743f9c746ef196e57c823d90ca3ab917f90ab9f13dd0ded27252ba49dbdfcab2b091d998bc446f6220cd3cea65db407502a740020 1499 | languageName: node 1500 | linkType: hard 1501 | 1502 | "path-key@npm:^4.0.0": 1503 | version: 4.0.0 1504 | resolution: "path-key@npm:4.0.0" 1505 | checksum: 8e6c314ae6d16b83e93032c61020129f6f4484590a777eed709c4a01b50e498822b00f76ceaf94bc64dbd90b327df56ceadce27da3d83393790f1219e07721d7 1506 | languageName: node 1507 | linkType: hard 1508 | 1509 | "pathe@npm:^1.1.2": 1510 | version: 1.1.2 1511 | resolution: "pathe@npm:1.1.2" 1512 | checksum: ec5f778d9790e7b9ffc3e4c1df39a5bb1ce94657a4e3ad830c1276491ca9d79f189f47609884671db173400256b005f4955f7952f52a2aeb5834ad5fb4faf134 1513 | languageName: node 1514 | linkType: hard 1515 | 1516 | "pathval@npm:^2.0.0": 1517 | version: 2.0.0 1518 | resolution: "pathval@npm:2.0.0" 1519 | checksum: 682b6a6289de7990909effef7dae9aa7bb6218c0426727bccf66a35b34e7bfbc65615270c5e44e3c9557a5cb44b1b9ef47fc3cb18bce6ad3ba92bcd28467ed7d 1520 | languageName: node 1521 | linkType: hard 1522 | 1523 | "picocolors@npm:^1.0.1": 1524 | version: 1.0.1 1525 | resolution: "picocolors@npm:1.0.1" 1526 | checksum: fa68166d1f56009fc02a34cdfd112b0dd3cf1ef57667ac57281f714065558c01828cdf4f18600ad6851cbe0093952ed0660b1e0156bddf2184b6aaf5817553a5 1527 | languageName: node 1528 | linkType: hard 1529 | 1530 | "postcss@npm:^8.4.39": 1531 | version: 8.4.39 1532 | resolution: "postcss@npm:8.4.39" 1533 | dependencies: 1534 | nanoid: ^3.3.7 1535 | picocolors: ^1.0.1 1536 | source-map-js: ^1.2.0 1537 | checksum: 14b130c90f165961772bdaf99c67f907f3d16494adf0868e57ef68baa67e0d1f6762db9d41ab0f4d09bab6fb7888588dba3596afd1a235fd5c2d43fba7006ac6 1538 | languageName: node 1539 | linkType: hard 1540 | 1541 | "prettier@npm:*, prettier@npm:^3.3.2": 1542 | version: 3.3.2 1543 | resolution: "prettier@npm:3.3.2" 1544 | bin: 1545 | prettier: bin/prettier.cjs 1546 | checksum: 5557d8caed0b182f68123c2e1e370ef105251d1dd75800fadaece3d061daf96b1389141634febf776050f9d732c7ae8fd444ff0b4a61b20535e7610552f32c69 1547 | languageName: node 1548 | linkType: hard 1549 | 1550 | "pretty-ms@npm:^9.0.0": 1551 | version: 9.0.0 1552 | resolution: "pretty-ms@npm:9.0.0" 1553 | dependencies: 1554 | parse-ms: ^4.0.0 1555 | checksum: 072b17547e09cb232e8e4c7be0281e256b6d8acd18dfb2fdd715d50330d1689fdaa877f53cf90c62ed419ef842f0f5fb94a2cd8ed1aa6d7608ad48834219435d 1556 | languageName: node 1557 | linkType: hard 1558 | 1559 | "promise-inflight@npm:^1.0.1": 1560 | version: 1.0.1 1561 | resolution: "promise-inflight@npm:1.0.1" 1562 | checksum: 22749483091d2c594261517f4f80e05226d4d5ecc1fc917e1886929da56e22b5718b7f2a75f3807e7a7d471bc3be2907fe92e6e8f373ddf5c64bae35b5af3981 1563 | languageName: node 1564 | linkType: hard 1565 | 1566 | "promise-retry@npm:^2.0.1": 1567 | version: 2.0.1 1568 | resolution: "promise-retry@npm:2.0.1" 1569 | dependencies: 1570 | err-code: ^2.0.2 1571 | retry: ^0.12.0 1572 | checksum: f96a3f6d90b92b568a26f71e966cbbc0f63ab85ea6ff6c81284dc869b41510e6cdef99b6b65f9030f0db422bf7c96652a3fff9f2e8fb4a0f069d8f4430359429 1573 | languageName: node 1574 | linkType: hard 1575 | 1576 | "readable-stream@npm:^3.6.0": 1577 | version: 3.6.0 1578 | resolution: "readable-stream@npm:3.6.0" 1579 | dependencies: 1580 | inherits: ^2.0.3 1581 | string_decoder: ^1.1.1 1582 | util-deprecate: ^1.0.1 1583 | checksum: d4ea81502d3799439bb955a3a5d1d808592cf3133350ed352aeaa499647858b27b1c4013984900238b0873ec8d0d8defce72469fb7a83e61d53f5ad61cb80dc8 1584 | languageName: node 1585 | linkType: hard 1586 | 1587 | "retry@npm:^0.12.0": 1588 | version: 0.12.0 1589 | resolution: "retry@npm:0.12.0" 1590 | checksum: 623bd7d2e5119467ba66202d733ec3c2e2e26568074923bc0585b6b99db14f357e79bdedb63cab56cec47491c4a0da7e6021a7465ca6dc4f481d3898fdd3158c 1591 | languageName: node 1592 | linkType: hard 1593 | 1594 | "rimraf@npm:^3.0.2": 1595 | version: 3.0.2 1596 | resolution: "rimraf@npm:3.0.2" 1597 | dependencies: 1598 | glob: ^7.1.3 1599 | bin: 1600 | rimraf: bin.js 1601 | checksum: 87f4164e396f0171b0a3386cc1877a817f572148ee13a7e113b238e48e8a9f2f31d009a92ec38a591ff1567d9662c6b67fd8818a2dbbaed74bc26a87a2a4a9a0 1602 | languageName: node 1603 | linkType: hard 1604 | 1605 | "rollup@npm:^4.13.0": 1606 | version: 4.18.1 1607 | resolution: "rollup@npm:4.18.1" 1608 | dependencies: 1609 | "@rollup/rollup-android-arm-eabi": 4.18.1 1610 | "@rollup/rollup-android-arm64": 4.18.1 1611 | "@rollup/rollup-darwin-arm64": 4.18.1 1612 | "@rollup/rollup-darwin-x64": 4.18.1 1613 | "@rollup/rollup-linux-arm-gnueabihf": 4.18.1 1614 | "@rollup/rollup-linux-arm-musleabihf": 4.18.1 1615 | "@rollup/rollup-linux-arm64-gnu": 4.18.1 1616 | "@rollup/rollup-linux-arm64-musl": 4.18.1 1617 | "@rollup/rollup-linux-powerpc64le-gnu": 4.18.1 1618 | "@rollup/rollup-linux-riscv64-gnu": 4.18.1 1619 | "@rollup/rollup-linux-s390x-gnu": 4.18.1 1620 | "@rollup/rollup-linux-x64-gnu": 4.18.1 1621 | "@rollup/rollup-linux-x64-musl": 4.18.1 1622 | "@rollup/rollup-win32-arm64-msvc": 4.18.1 1623 | "@rollup/rollup-win32-ia32-msvc": 4.18.1 1624 | "@rollup/rollup-win32-x64-msvc": 4.18.1 1625 | "@types/estree": 1.0.5 1626 | fsevents: ~2.3.2 1627 | dependenciesMeta: 1628 | "@rollup/rollup-android-arm-eabi": 1629 | optional: true 1630 | "@rollup/rollup-android-arm64": 1631 | optional: true 1632 | "@rollup/rollup-darwin-arm64": 1633 | optional: true 1634 | "@rollup/rollup-darwin-x64": 1635 | optional: true 1636 | "@rollup/rollup-linux-arm-gnueabihf": 1637 | optional: true 1638 | "@rollup/rollup-linux-arm-musleabihf": 1639 | optional: true 1640 | "@rollup/rollup-linux-arm64-gnu": 1641 | optional: true 1642 | "@rollup/rollup-linux-arm64-musl": 1643 | optional: true 1644 | "@rollup/rollup-linux-powerpc64le-gnu": 1645 | optional: true 1646 | "@rollup/rollup-linux-riscv64-gnu": 1647 | optional: true 1648 | "@rollup/rollup-linux-s390x-gnu": 1649 | optional: true 1650 | "@rollup/rollup-linux-x64-gnu": 1651 | optional: true 1652 | "@rollup/rollup-linux-x64-musl": 1653 | optional: true 1654 | "@rollup/rollup-win32-arm64-msvc": 1655 | optional: true 1656 | "@rollup/rollup-win32-ia32-msvc": 1657 | optional: true 1658 | "@rollup/rollup-win32-x64-msvc": 1659 | optional: true 1660 | fsevents: 1661 | optional: true 1662 | bin: 1663 | rollup: dist/bin/rollup 1664 | checksum: 741d9b6c7ac6503e38a24876c47f012f2109b1e1562dd84df355dce4a9637ba13289323559d32cfaa464c5f1fa9cbdc2a52b02ec4a4ce077f13399c21a799a4c 1665 | languageName: node 1666 | linkType: hard 1667 | 1668 | "safe-buffer@npm:~5.2.0": 1669 | version: 5.2.1 1670 | resolution: "safe-buffer@npm:5.2.1" 1671 | checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 1672 | languageName: node 1673 | linkType: hard 1674 | 1675 | "safer-buffer@npm:>= 2.1.2 < 3.0.0": 1676 | version: 2.1.2 1677 | resolution: "safer-buffer@npm:2.1.2" 1678 | checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 1679 | languageName: node 1680 | linkType: hard 1681 | 1682 | "semver@npm:^7.3.5": 1683 | version: 7.3.8 1684 | resolution: "semver@npm:7.3.8" 1685 | dependencies: 1686 | lru-cache: ^6.0.0 1687 | bin: 1688 | semver: bin/semver.js 1689 | checksum: ba9c7cbbf2b7884696523450a61fee1a09930d888b7a8d7579025ad93d459b2d1949ee5bbfeb188b2be5f4ac163544c5e98491ad6152df34154feebc2cc337c1 1690 | languageName: node 1691 | linkType: hard 1692 | 1693 | "set-blocking@npm:^2.0.0": 1694 | version: 2.0.0 1695 | resolution: "set-blocking@npm:2.0.0" 1696 | checksum: 6e65a05f7cf7ebdf8b7c75b101e18c0b7e3dff4940d480efed8aad3a36a4005140b660fa1d804cb8bce911cac290441dc728084a30504d3516ac2ff7ad607b02 1697 | languageName: node 1698 | linkType: hard 1699 | 1700 | "shebang-command@npm:^2.0.0": 1701 | version: 2.0.0 1702 | resolution: "shebang-command@npm:2.0.0" 1703 | dependencies: 1704 | shebang-regex: ^3.0.0 1705 | checksum: 6b52fe87271c12968f6a054e60f6bde5f0f3d2db483a1e5c3e12d657c488a15474121a1d55cd958f6df026a54374ec38a4a963988c213b7570e1d51575cea7fa 1706 | languageName: node 1707 | linkType: hard 1708 | 1709 | "shebang-regex@npm:^3.0.0": 1710 | version: 3.0.0 1711 | resolution: "shebang-regex@npm:3.0.0" 1712 | checksum: 1a2bcae50de99034fcd92ad4212d8e01eedf52c7ec7830eedcf886622804fe36884278f2be8be0ea5fde3fd1c23911643a4e0f726c8685b61871c8908af01222 1713 | languageName: node 1714 | linkType: hard 1715 | 1716 | "siginfo@npm:^2.0.0": 1717 | version: 2.0.0 1718 | resolution: "siginfo@npm:2.0.0" 1719 | checksum: 8aa5a98640ca09fe00d74416eca97551b3e42991614a3d1b824b115fc1401543650914f651ab1311518177e4d297e80b953f4cd4cd7ea1eabe824e8f2091de01 1720 | languageName: node 1721 | linkType: hard 1722 | 1723 | "signal-exit@npm:^3.0.7": 1724 | version: 3.0.7 1725 | resolution: "signal-exit@npm:3.0.7" 1726 | checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 1727 | languageName: node 1728 | linkType: hard 1729 | 1730 | "signal-exit@npm:^4.1.0": 1731 | version: 4.1.0 1732 | resolution: "signal-exit@npm:4.1.0" 1733 | checksum: 64c757b498cb8629ffa5f75485340594d2f8189e9b08700e69199069c8e3070fb3e255f7ab873c05dc0b3cec412aea7402e10a5990cb6a050bd33ba062a6c549 1734 | languageName: node 1735 | linkType: hard 1736 | 1737 | "smart-buffer@npm:^4.2.0": 1738 | version: 4.2.0 1739 | resolution: "smart-buffer@npm:4.2.0" 1740 | checksum: b5167a7142c1da704c0e3af85c402002b597081dd9575031a90b4f229ca5678e9a36e8a374f1814c8156a725d17008ae3bde63b92f9cfd132526379e580bec8b 1741 | languageName: node 1742 | linkType: hard 1743 | 1744 | "socks-proxy-agent@npm:^7.0.0": 1745 | version: 7.0.0 1746 | resolution: "socks-proxy-agent@npm:7.0.0" 1747 | dependencies: 1748 | agent-base: ^6.0.2 1749 | debug: ^4.3.3 1750 | socks: ^2.6.2 1751 | checksum: 720554370154cbc979e2e9ce6a6ec6ced205d02757d8f5d93fe95adae454fc187a5cbfc6b022afab850a5ce9b4c7d73e0f98e381879cf45f66317a4895953846 1752 | languageName: node 1753 | linkType: hard 1754 | 1755 | "socks@npm:^2.6.2": 1756 | version: 2.7.1 1757 | resolution: "socks@npm:2.7.1" 1758 | dependencies: 1759 | ip: ^2.0.0 1760 | smart-buffer: ^4.2.0 1761 | checksum: 259d9e3e8e1c9809a7f5c32238c3d4d2a36b39b83851d0f573bfde5f21c4b1288417ce1af06af1452569cd1eb0841169afd4998f0e04ba04656f6b7f0e46d748 1762 | languageName: node 1763 | linkType: hard 1764 | 1765 | "source-map-js@npm:^1.2.0": 1766 | version: 1.2.0 1767 | resolution: "source-map-js@npm:1.2.0" 1768 | checksum: 791a43306d9223792e84293b00458bf102a8946e7188f3db0e4e22d8d530b5f80a4ce468eb5ec0bf585443ad55ebbd630bf379c98db0b1f317fd902500217f97 1769 | languageName: node 1770 | linkType: hard 1771 | 1772 | "ssri@npm:^9.0.0": 1773 | version: 9.0.1 1774 | resolution: "ssri@npm:9.0.1" 1775 | dependencies: 1776 | minipass: ^3.1.1 1777 | checksum: fb58f5e46b6923ae67b87ad5ef1c5ab6d427a17db0bead84570c2df3cd50b4ceb880ebdba2d60726588272890bae842a744e1ecce5bd2a2a582fccd5068309eb 1778 | languageName: node 1779 | linkType: hard 1780 | 1781 | "stackback@npm:0.0.2": 1782 | version: 0.0.2 1783 | resolution: "stackback@npm:0.0.2" 1784 | checksum: 2d4dc4e64e2db796de4a3c856d5943daccdfa3dd092e452a1ce059c81e9a9c29e0b9badba91b43ef0d5ff5c04ee62feb3bcc559a804e16faf447bac2d883aa99 1785 | languageName: node 1786 | linkType: hard 1787 | 1788 | "std-env@npm:^3.7.0": 1789 | version: 3.7.0 1790 | resolution: "std-env@npm:3.7.0" 1791 | checksum: 4f489d13ff2ab838c9acd4ed6b786b51aa52ecacdfeaefe9275fcb220ff2ac80c6e95674723508fd29850a694569563a8caaaea738eb82ca16429b3a0b50e510 1792 | languageName: node 1793 | linkType: hard 1794 | 1795 | "string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.2.3": 1796 | version: 4.2.3 1797 | resolution: "string-width@npm:4.2.3" 1798 | dependencies: 1799 | emoji-regex: ^8.0.0 1800 | is-fullwidth-code-point: ^3.0.0 1801 | strip-ansi: ^6.0.1 1802 | checksum: e52c10dc3fbfcd6c3a15f159f54a90024241d0f149cf8aed2982a2d801d2e64df0bf1dc351cf8e95c3319323f9f220c16e740b06faecd53e2462df1d2b5443fb 1803 | languageName: node 1804 | linkType: hard 1805 | 1806 | "string_decoder@npm:^1.1.1": 1807 | version: 1.3.0 1808 | resolution: "string_decoder@npm:1.3.0" 1809 | dependencies: 1810 | safe-buffer: ~5.2.0 1811 | checksum: 8417646695a66e73aefc4420eb3b84cc9ffd89572861fe004e6aeb13c7bc00e2f616247505d2dbbef24247c372f70268f594af7126f43548565c68c117bdeb56 1812 | languageName: node 1813 | linkType: hard 1814 | 1815 | "strip-ansi@npm:^6.0.1": 1816 | version: 6.0.1 1817 | resolution: "strip-ansi@npm:6.0.1" 1818 | dependencies: 1819 | ansi-regex: ^5.0.1 1820 | checksum: f3cd25890aef3ba6e1a74e20896c21a46f482e93df4a06567cebf2b57edabb15133f1f94e57434e0a958d61186087b1008e89c94875d019910a213181a14fc8c 1821 | languageName: node 1822 | linkType: hard 1823 | 1824 | "strip-ansi@npm:^7.1.0": 1825 | version: 7.1.0 1826 | resolution: "strip-ansi@npm:7.1.0" 1827 | dependencies: 1828 | ansi-regex: ^6.0.1 1829 | checksum: 859c73fcf27869c22a4e4d8c6acfe690064659e84bef9458aa6d13719d09ca88dcfd40cbf31fd0be63518ea1a643fe070b4827d353e09533a5b0b9fd4553d64d 1830 | languageName: node 1831 | linkType: hard 1832 | 1833 | "strip-final-newline@npm:^3.0.0": 1834 | version: 3.0.0 1835 | resolution: "strip-final-newline@npm:3.0.0" 1836 | checksum: 23ee263adfa2070cd0f23d1ac14e2ed2f000c9b44229aec9c799f1367ec001478469560abefd00c5c99ee6f0b31c137d53ec6029c53e9f32a93804e18c201050 1837 | languageName: node 1838 | linkType: hard 1839 | 1840 | "strip-final-newline@npm:^4.0.0": 1841 | version: 4.0.0 1842 | resolution: "strip-final-newline@npm:4.0.0" 1843 | checksum: b5fe48f695d74863153a3b3155220e6e9bf51f4447832998c8edec38e6559b3af87a9fe5ac0df95570a78a26f5fa91701358842eab3c15480e27980b154a145f 1844 | languageName: node 1845 | linkType: hard 1846 | 1847 | "tar@npm:^6.1.11, tar@npm:^6.1.2": 1848 | version: 6.1.13 1849 | resolution: "tar@npm:6.1.13" 1850 | dependencies: 1851 | chownr: ^2.0.0 1852 | fs-minipass: ^2.0.0 1853 | minipass: ^4.0.0 1854 | minizlib: ^2.1.1 1855 | mkdirp: ^1.0.3 1856 | yallist: ^4.0.0 1857 | checksum: 8a278bed123aa9f53549b256a36b719e317c8b96fe86a63406f3c62887f78267cea9b22dc6f7007009738509800d4a4dccc444abd71d762287c90f35b002eb1c 1858 | languageName: node 1859 | linkType: hard 1860 | 1861 | "tinybench@npm:^2.8.0": 1862 | version: 2.8.0 1863 | resolution: "tinybench@npm:2.8.0" 1864 | checksum: 024a307c6a71f6e2903e110952457ee3dfa606093b45d7f49efcfd01d452650e099474080677ff650b0fd76b49074425ac68ff2a70561699a78515a278bf0862 1865 | languageName: node 1866 | linkType: hard 1867 | 1868 | "tinypool@npm:^1.0.0": 1869 | version: 1.0.0 1870 | resolution: "tinypool@npm:1.0.0" 1871 | checksum: 59dab87b0811da2dc1ecbac9a99cde93d45450744d4a9fca628d805c452bbb5e5f214fd191127f665d062cae9cc159225dea5508d766e40a0c6c33f573e5c3b6 1872 | languageName: node 1873 | linkType: hard 1874 | 1875 | "tinyrainbow@npm:^1.2.0": 1876 | version: 1.2.0 1877 | resolution: "tinyrainbow@npm:1.2.0" 1878 | checksum: d1e2cb5400032c0092be00e4a3da5450bea8b4fad58bfb5d3c58ca37ff5c5e252f7fcfb9af247914854af79c46014add9d1042fe044358c305a129ed55c8be35 1879 | languageName: node 1880 | linkType: hard 1881 | 1882 | "tinyspy@npm:^3.0.0": 1883 | version: 3.0.0 1884 | resolution: "tinyspy@npm:3.0.0" 1885 | checksum: b5b686acff2b88de60ff8ecf89a2042320406aaeee2fba1828a7ea8a925fad3ed9f5e4d7a068154a9134473c472aa03da8ca92ee994bc57a741c5ede5fa7de4d 1886 | languageName: node 1887 | linkType: hard 1888 | 1889 | "unique-filename@npm:^2.0.0": 1890 | version: 2.0.1 1891 | resolution: "unique-filename@npm:2.0.1" 1892 | dependencies: 1893 | unique-slug: ^3.0.0 1894 | checksum: 807acf3381aff319086b64dc7125a9a37c09c44af7620bd4f7f3247fcd5565660ac12d8b80534dcbfd067e6fe88a67e621386dd796a8af828d1337a8420a255f 1895 | languageName: node 1896 | linkType: hard 1897 | 1898 | "unique-slug@npm:^3.0.0": 1899 | version: 3.0.0 1900 | resolution: "unique-slug@npm:3.0.0" 1901 | dependencies: 1902 | imurmurhash: ^0.1.4 1903 | checksum: 49f8d915ba7f0101801b922062ee46b7953256c93ceca74303bd8e6413ae10aa7e8216556b54dc5382895e8221d04f1efaf75f945c2e4a515b4139f77aa6640c 1904 | languageName: node 1905 | linkType: hard 1906 | 1907 | "util-deprecate@npm:^1.0.1": 1908 | version: 1.0.2 1909 | resolution: "util-deprecate@npm:1.0.2" 1910 | checksum: 474acf1146cb2701fe3b074892217553dfcf9a031280919ba1b8d651a068c9b15d863b7303cb15bd00a862b498e6cf4ad7b4a08fb134edd5a6f7641681cb54a2 1911 | languageName: node 1912 | linkType: hard 1913 | 1914 | "vite-node@npm:2.0.2": 1915 | version: 2.0.2 1916 | resolution: "vite-node@npm:2.0.2" 1917 | dependencies: 1918 | cac: ^6.7.14 1919 | debug: ^4.3.5 1920 | pathe: ^1.1.2 1921 | tinyrainbow: ^1.2.0 1922 | vite: ^5.0.0 1923 | bin: 1924 | vite-node: vite-node.mjs 1925 | checksum: 05e478741a4b14ef38bdc9f68757ae48bc19e194755527cb7d8604abb420d02a57222ee1ec91e296a7bb1a08cfde7b12a5f9d983f264ff4b0e9a278cd3bfeb12 1926 | languageName: node 1927 | linkType: hard 1928 | 1929 | "vite@npm:^5.0.0": 1930 | version: 5.3.3 1931 | resolution: "vite@npm:5.3.3" 1932 | dependencies: 1933 | esbuild: ^0.21.3 1934 | fsevents: ~2.3.3 1935 | postcss: ^8.4.39 1936 | rollup: ^4.13.0 1937 | peerDependencies: 1938 | "@types/node": ^18.0.0 || >=20.0.0 1939 | less: "*" 1940 | lightningcss: ^1.21.0 1941 | sass: "*" 1942 | stylus: "*" 1943 | sugarss: "*" 1944 | terser: ^5.4.0 1945 | dependenciesMeta: 1946 | fsevents: 1947 | optional: true 1948 | peerDependenciesMeta: 1949 | "@types/node": 1950 | optional: true 1951 | less: 1952 | optional: true 1953 | lightningcss: 1954 | optional: true 1955 | sass: 1956 | optional: true 1957 | stylus: 1958 | optional: true 1959 | sugarss: 1960 | optional: true 1961 | terser: 1962 | optional: true 1963 | bin: 1964 | vite: bin/vite.js 1965 | checksum: 1a54b678c03b52be934b0db95295aa573819063fad9e13f148936cfc4006d081a6790fdd2dbe111b09b75b9a8d49f15e0788c58b86156d238ab3a0c1cc1a941f 1966 | languageName: node 1967 | linkType: hard 1968 | 1969 | "vitest@npm:^2.0.2": 1970 | version: 2.0.2 1971 | resolution: "vitest@npm:2.0.2" 1972 | dependencies: 1973 | "@ampproject/remapping": ^2.3.0 1974 | "@vitest/expect": 2.0.2 1975 | "@vitest/pretty-format": ^2.0.2 1976 | "@vitest/runner": 2.0.2 1977 | "@vitest/snapshot": 2.0.2 1978 | "@vitest/spy": 2.0.2 1979 | "@vitest/utils": 2.0.2 1980 | chai: ^5.1.1 1981 | debug: ^4.3.5 1982 | execa: ^8.0.1 1983 | magic-string: ^0.30.10 1984 | pathe: ^1.1.2 1985 | std-env: ^3.7.0 1986 | tinybench: ^2.8.0 1987 | tinypool: ^1.0.0 1988 | tinyrainbow: ^1.2.0 1989 | vite: ^5.0.0 1990 | vite-node: 2.0.2 1991 | why-is-node-running: ^2.2.2 1992 | peerDependencies: 1993 | "@edge-runtime/vm": "*" 1994 | "@types/node": ^18.0.0 || >=20.0.0 1995 | "@vitest/browser": 2.0.2 1996 | "@vitest/ui": 2.0.2 1997 | happy-dom: "*" 1998 | jsdom: "*" 1999 | peerDependenciesMeta: 2000 | "@edge-runtime/vm": 2001 | optional: true 2002 | "@types/node": 2003 | optional: true 2004 | "@vitest/browser": 2005 | optional: true 2006 | "@vitest/ui": 2007 | optional: true 2008 | happy-dom: 2009 | optional: true 2010 | jsdom: 2011 | optional: true 2012 | bin: 2013 | vitest: vitest.mjs 2014 | checksum: d79ab497cf5e6e4abcbb3bbd3ab2a44cf34dfc67efa305ef5d819bd18528811fb346b899c584a59a90336f321cef263d08b7ee30a4576701ba7cbad10f4b4c2a 2015 | languageName: node 2016 | linkType: hard 2017 | 2018 | "which@npm:^2.0.1, which@npm:^2.0.2": 2019 | version: 2.0.2 2020 | resolution: "which@npm:2.0.2" 2021 | dependencies: 2022 | isexe: ^2.0.0 2023 | bin: 2024 | node-which: ./bin/node-which 2025 | checksum: 1a5c563d3c1b52d5f893c8b61afe11abc3bab4afac492e8da5bde69d550de701cf9806235f20a47b5c8fa8a1d6a9135841de2596535e998027a54589000e66d1 2026 | languageName: node 2027 | linkType: hard 2028 | 2029 | "why-is-node-running@npm:^2.2.2": 2030 | version: 2.3.0 2031 | resolution: "why-is-node-running@npm:2.3.0" 2032 | dependencies: 2033 | siginfo: ^2.0.0 2034 | stackback: 0.0.2 2035 | bin: 2036 | why-is-node-running: cli.js 2037 | checksum: 58ebbf406e243ace97083027f0df7ff4c2108baf2595bb29317718ef207cc7a8104e41b711ff65d6fa354f25daa8756b67f2f04931a4fd6ba9d13ae8197496fb 2038 | languageName: node 2039 | linkType: hard 2040 | 2041 | "wide-align@npm:^1.1.5": 2042 | version: 1.1.5 2043 | resolution: "wide-align@npm:1.1.5" 2044 | dependencies: 2045 | string-width: ^1.0.2 || 2 || 3 || 4 2046 | checksum: d5fc37cd561f9daee3c80e03b92ed3e84d80dde3365a8767263d03dacfc8fa06b065ffe1df00d8c2a09f731482fcacae745abfbb478d4af36d0a891fad4834d3 2047 | languageName: node 2048 | linkType: hard 2049 | 2050 | "wrappy@npm:1": 2051 | version: 1.0.2 2052 | resolution: "wrappy@npm:1.0.2" 2053 | checksum: 159da4805f7e84a3d003d8841557196034155008f817172d4e986bd591f74aa82aa7db55929a54222309e01079a65a92a9e6414da5a6aa4b01ee44a511ac3ee5 2054 | languageName: node 2055 | linkType: hard 2056 | 2057 | "yallist@npm:^4.0.0": 2058 | version: 4.0.0 2059 | resolution: "yallist@npm:4.0.0" 2060 | checksum: 343617202af32df2a15a3be36a5a8c0c8545208f3d3dfbc6bb7c3e3b7e8c6f8e7485432e4f3b88da3031a6e20afa7c711eded32ddfb122896ac5d914e75848d5 2061 | languageName: node 2062 | linkType: hard 2063 | 2064 | "yoctocolors@npm:^2.0.0": 2065 | version: 2.1.1 2066 | resolution: "yoctocolors@npm:2.1.1" 2067 | checksum: 563fbec88bce9716d1044bc98c96c329e1d7a7c503e6f1af68f1ff914adc3ba55ce953c871395e2efecad329f85f1632f51a99c362032940321ff80c42a6f74d 2068 | languageName: node 2069 | linkType: hard 2070 | --------------------------------------------------------------------------------