A simple tool which lets you scrape twitter accounts and crosspost them to bluesky accounts! Comes with a CLI and a webapp for managing profiles! Works with images/videos/link embeds/threads.
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

Refactor: Switch to NPM version of twitter-scraper and remove local clone

jack bd03f37a 1242363a

+2 -17987
+2 -3
package.json
··· 12 12 "import": "tsx src/index.ts --import-history", 13 13 "lint": "biome check --write .", 14 14 "format": "biome format --write .", 15 - "typecheck": "tsc --noEmit", 16 - "postinstall": "cd twitter-scraper && npm install && npm run build" 15 + "typecheck": "tsc --noEmit" 17 16 }, 18 17 "keywords": [ 19 18 "bluesky", ··· 28 27 "dependencies": { 29 28 "@atproto/api": "^0.18.9", 30 29 "@google/generative-ai": "^0.24.1", 31 - "@the-convocation/twitter-scraper": "file:./twitter-scraper", 30 + "@the-convocation/twitter-scraper": "^0.21.1", 32 31 "axios": "^1.13.2", 33 32 "bcryptjs": "^3.0.3", 34 33 "better-sqlite3": "^12.5.0",
-5
twitter-scraper/.commitlintrc
··· 1 - { 2 - "extends": [ 3 - "@commitlint/config-conventional" 4 - ] 5 - }
-24
twitter-scraper/.eslintrc.js
··· 1 - module.exports = { 2 - parser: '@typescript-eslint/parser', 3 - parserOptions: { 4 - tsconfigRootDir: __dirname, 5 - sourceType: 'module', 6 - }, 7 - plugins: ['@typescript-eslint/eslint-plugin'], 8 - extends: [ 9 - 'plugin:@typescript-eslint/recommended', 10 - 'plugin:prettier/recommended', 11 - ], 12 - root: true, 13 - env: { 14 - node: true, 15 - jest: true, 16 - }, 17 - ignorePatterns: ['**/*.js'], 18 - rules: { 19 - '@typescript-eslint/interface-name-prefix': 'off', 20 - '@typescript-eslint/explicit-function-return-type': 'off', 21 - '@typescript-eslint/explicit-module-boundary-types': 'off', 22 - '@typescript-eslint/no-explicit-any': 'off', 23 - }, 24 - };
-78
twitter-scraper/.gitattributes
··· 1 - # Auto detect text files and perform LF normalization 2 - * text=auto 3 - 4 - # 5 - # The above will handle all files NOT found below 6 - # 7 - 8 - # Code 9 - *.js text eol=lf 10 - *.ts text eol=lf 11 - 12 - # Documents 13 - *.bibtex text diff=bibtex 14 - *.doc diff=astextplain 15 - *.DOC diff=astextplain 16 - *.docx diff=astextplain 17 - *.DOCX diff=astextplain 18 - *.dot diff=astextplain 19 - *.DOT diff=astextplain 20 - *.pdf diff=astextplain 21 - *.PDF diff=astextplain 22 - *.rtf diff=astextplain 23 - *.RTF diff=astextplain 24 - *.md text diff=markdown 25 - *.mdx text diff=markdown 26 - *.tex text diff=tex 27 - *.adoc text 28 - *.textile text 29 - *.mustache text 30 - *.csv text 31 - *.tab text 32 - *.tsv text 33 - *.txt text 34 - *.sql text 35 - 36 - # Graphics 37 - *.png binary 38 - *.jpg binary 39 - *.jpeg binary 40 - *.gif binary 41 - *.tif binary 42 - *.tiff binary 43 - *.ico binary 44 - *.svg text 45 - *.eps binary 46 - 47 - # Scripts 48 - *.bash text eol=lf 49 - *.fish text eol=lf 50 - *.sh text eol=lf 51 - *.zsh text eol=lf 52 - *.bat text eol=crlf 53 - *.cmd text eol=crlf 54 - *.ps1 text eol=crlf 55 - 56 - # Serialisation 57 - *.json text 58 - *.toml text 59 - *.xml text 60 - *.yaml text 61 - *.yml text 62 - 63 - # Archives 64 - *.7z binary 65 - *.gz binary 66 - *.tar binary 67 - *.tgz binary 68 - *.zip binary 69 - 70 - # Text files where line endings should be preserved 71 - *.patch -text 72 - 73 - # 74 - # Exclude files from exporting 75 - # 76 - 77 - .gitattributes export-ignore 78 - .gitignore export-ignore
-29
twitter-scraper/.github/workflows/build.yml
··· 1 - name: Node.js Build 2 - 3 - on: 4 - workflow_dispatch: 5 - push: 6 - branches: [main] 7 - pull_request: 8 - branches: [main] 9 - schedule: 10 - - cron: '22 18 * * 3' 11 - 12 - jobs: 13 - build: 14 - runs-on: ubuntu-latest 15 - strategy: 16 - matrix: 17 - node: [18.x, 20.x] 18 - steps: 19 - - uses: actions/checkout@v3 20 - - name: Install Node.js ${{ matrix.node }} 21 - uses: actions/setup-node@v3 22 - with: 23 - node-version: ${{ matrix.node }} 24 - - name: Yarn 25 - run: npm install -g yarn 26 - - name: Install 27 - run: yarn install 28 - - name: Build 29 - run: yarn build
-25
twitter-scraper/.github/workflows/docs.yml
··· 1 - name: Documentation 2 - 3 - on: 4 - push: 5 - branches: [main] 6 - 7 - jobs: 8 - docs: 9 - runs-on: ubuntu-latest 10 - steps: 11 - - uses: actions/checkout@v3 12 - - name: Install Node.js 13 - uses: actions/setup-node@v3 14 - with: 15 - node-version: 18.x 16 - - name: Yarn 17 - run: npm install -g yarn 18 - - name: Install 19 - run: yarn install 20 - - name: Deploy docs 21 - run: | 22 - git config --global user.name 'venatbot' 23 - git config --global user.email 'venatbot@protonmail.com' 24 - git remote set-url origin 'https://venatbot:${{ secrets.GH_TOKEN }}@github.com/the-convocation/twitter-scraper.git' 25 - yarn docs:deploy
-30
twitter-scraper/.github/workflows/publish.yml
··· 1 - name: Publish 2 - 3 - on: 4 - release: 5 - types: 6 - - created 7 - 8 - permissions: 9 - id-token: write # Required for OIDC 10 - contents: read 11 - 12 - jobs: 13 - publish: 14 - runs-on: ubuntu-latest 15 - steps: 16 - - uses: actions/checkout@v3 17 - - name: Install Node.js 18 - uses: actions/setup-node@v4 19 - with: 20 - node-version: 22.x 21 - - name: Update NPM 22 - run: npm install -g npm 23 - - name: Yarn 24 - run: npm install -g yarn 25 - - name: Install 26 - run: yarn install 27 - - name: Build 28 - run: yarn build 29 - - name: Publish 30 - run: npm publish --access public
-33
twitter-scraper/.github/workflows/test.yml
··· 1 - name: Node.js Test 2 - 3 - on: 4 - workflow_dispatch: 5 - push: 6 - branches: [main] 7 - pull_request: 8 - branches: [main] 9 - schedule: 10 - - cron: '37 22 * * 2' 11 - 12 - jobs: 13 - build: 14 - runs-on: ubuntu-latest 15 - strategy: 16 - matrix: 17 - node: [18.x, 20.x] 18 - steps: 19 - - uses: actions/checkout@v3 20 - - name: Install Node.js ${{ matrix.node }} 21 - uses: actions/setup-node@v3 22 - with: 23 - node-version: ${{ matrix.node }} 24 - - name: Yarn 25 - run: npm install -g yarn 26 - - name: Install 27 - run: yarn install 28 - - name: Test 29 - env: 30 - TWITTER_USERNAME: ${{ secrets.TWITTER_USERNAME }} 31 - TWITTER_PASSWORD: ${{ secrets.TWITTER_PASSWORD }} 32 - TWITTER_EMAIL: ${{ secrets.TWITTER_EMAIL }} 33 - run: yarn test
-122
twitter-scraper/.gitignore
··· 1 - # Logs 2 - logs 3 - *.log 4 - npm-debug.log* 5 - yarn-debug.log* 6 - yarn-error.log* 7 - lerna-debug.log* 8 - 9 - # Diagnostic reports (https://nodejs.org/api/report.html) 10 - report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 - 12 - # Runtime data 13 - pids 14 - *.pid 15 - *.seed 16 - *.pid.lock 17 - 18 - # Directory for instrumented libs generated by jscoverage/JSCover 19 - lib-cov 20 - 21 - # Coverage directory used by tools like istanbul 22 - coverage 23 - *.lcov 24 - 25 - # nyc test coverage 26 - .nyc_output 27 - 28 - # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 - .grunt 30 - 31 - # Bower dependency directory (https://bower.io/) 32 - bower_components 33 - 34 - # node-waf configuration 35 - .lock-wscript 36 - 37 - # Compiled binary addons (https://nodejs.org/api/addons.html) 38 - build/Release 39 - 40 - # Dependency directories 41 - node_modules/ 42 - jspm_packages/ 43 - 44 - # TypeScript v1 declaration files 45 - typings/ 46 - 47 - # TypeScript cache 48 - *.tsbuildinfo 49 - 50 - # Optional npm cache directory 51 - .npm 52 - 53 - # Optional eslint cache 54 - .eslintcache 55 - 56 - # Microbundle cache 57 - .rpt2_cache/ 58 - .rts2_cache_cjs/ 59 - .rts2_cache_es/ 60 - .rts2_cache_umd/ 61 - 62 - # Optional REPL history 63 - .node_repl_history 64 - 65 - # Output of 'npm pack' 66 - *.tgz 67 - 68 - # Yarn Integrity file 69 - .yarn-integrity 70 - 71 - # Yarn cache 72 - .yarn 73 - 74 - # dotenv environment variables file 75 - .env 76 - .env.test 77 - 78 - # parcel-bundler cache (https://parceljs.org/) 79 - .cache 80 - 81 - # Next.js build output 82 - .next 83 - 84 - # Nuxt.js build / generate output 85 - .nuxt 86 - dist 87 - 88 - # Gatsby files 89 - .cache/ 90 - # Comment in the public line in if your project uses Gatsby and *not* Next.js 91 - # https://nextjs.org/blog/next-9-1#public-directory-support 92 - # public 93 - 94 - # vuepress build output 95 - .vuepress/dist 96 - 97 - # Serverless directories 98 - .serverless/ 99 - 100 - # FuseBox cache 101 - .fusebox/ 102 - 103 - # DynamoDB Local files 104 - .dynamodb/ 105 - 106 - # TernJS port file 107 - .tern-port 108 - 109 - # VSCode 110 - .vscode/ 111 - 112 - # JetBrains 113 - .idea/ 114 - 115 - # Documentation 116 - docs/ 117 - 118 - # NPM lockfile 119 - package-lock.json 120 - 121 - .env*.local 122 - *.har
-1
twitter-scraper/.husky/.gitignore
··· 1 - _
-4
twitter-scraper/.husky/commit-msg
··· 1 - #!/usr/bin/env sh 2 - . "$(dirname -- "$0")/_/husky.sh" 3 - 4 - npx commitlint --edit
-4
twitter-scraper/.husky/pre-commit
··· 1 - #!/bin/sh 2 - . "$(dirname "$0")/_/husky.sh" 3 - 4 - npx lint-staged
-7
twitter-scraper/.npmignore
··· 1 - docs/ 2 - src/ 3 - .*/ 4 - jest.config.js 5 - tsconfig.json 6 - typedoc.json 7 - yarn.lock
-3
twitter-scraper/.prettierignore
··· 1 - node_modules/ 2 - dist/ 3 - *.json
-5
twitter-scraper/.prettierrc
··· 1 - { 2 - "singleQuote": true, 3 - "trailingComma": "all", 4 - "semi": true 5 - }
-1
twitter-scraper/.yarnrc.yml
··· 1 - nodeLinker: node-modules
-21
twitter-scraper/LICENSE
··· 1 - MIT License 2 - 3 - Copyright (c) 2022 karashiiro 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.
-295
twitter-scraper/README.md
··· 1 - # twitter-scraper 2 - 3 - [![Documentation badge](https://img.shields.io/badge/docs-here-informational)](https://the-convocation.github.io/twitter-scraper/) 4 - 5 - A port of the now-archived [n0madic/twitter-scraper](https://github.com/n0madic/twitter-scraper) to Node.js. 6 - 7 - > Twitter's API is annoying to work with, and has lots of limitations — luckily 8 - > their frontend (JavaScript) has it's own API, which I reverse-engineered. No 9 - > API rate limits. No tokens needed. No restrictions. Extremely fast. 10 - > 11 - > You can use this library to get the text of any user's Tweets trivially. 12 - 13 - Many things have changed since X (the company formerly known as Twitter) was acquired in 2022: 14 - 15 - - Several operations require logging in with a real user account via 16 - `scraper.login()`. **While we are not aware of confirmed cases caused 17 - by this library, any account you log into with this library is subject 18 - to being banned at any time. You have been warned.** 19 - - Twitter's frontend API does in fact have rate limits 20 - ([#11](https://github.com/the-convocation/twitter-scraper/issues/11)). 21 - The rate limits are dynamic and sometimes change, so we don't know 22 - exactly what they are at all times. Refer to [rate limiting](#rate-limiting) 23 - for more information. 24 - - Twitter's authentication requirements and frontend API endpoints 25 - change frequently, breaking this library. Fixes for these issues 26 - typically take at least a few days to go out. 27 - 28 - ## Installation 29 - 30 - This package requires Node.js v16.0.0 or greater. 31 - 32 - NPM: 33 - 34 - ```sh 35 - npm install @the-convocation/twitter-scraper 36 - ``` 37 - 38 - Yarn: 39 - 40 - ```sh 41 - yarn add @the-convocation/twitter-scraper 42 - ``` 43 - 44 - TypeScript types have been bundled with the distribution. 45 - 46 - ## Usage 47 - 48 - Most use cases are exactly the same as in 49 - [n0madic/twitter-scraper](https://github.com/n0madic/twitter-scraper). Channel 50 - iterators have been translated into 51 - [AsyncGenerator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncGenerator) 52 - instances, and can be consumed with the corresponding 53 - `for await (const x of y) { ... }` syntax. 54 - 55 - ### Browser usage 56 - 57 - This package directly invokes the Twitter API, which does not have permissive 58 - CORS headers. With the default settings, requests will fail unless you disable 59 - CORS checks, which is not advised. Instead, applications must provide a CORS 60 - proxy and configure it in the `Scraper` options. 61 - 62 - Proxies (and other request mutations) can be configured with the request 63 - interceptor transform: 64 - 65 - ```ts 66 - const scraper = new Scraper({ 67 - transform: { 68 - request(input: RequestInfo | URL, init?: RequestInit) { 69 - // The arguments here are the same as the parameters to fetch(), and 70 - // are kept as-is for flexibility of both the library and applications. 71 - if (input instanceof URL) { 72 - const proxy = 73 - 'https://corsproxy.io/?' + encodeURIComponent(input.toString()); 74 - return [proxy, init]; 75 - } else if (typeof input === 'string') { 76 - const proxy = 'https://corsproxy.io/?' + encodeURIComponent(input); 77 - return [proxy, init]; 78 - } else { 79 - // Omitting handling for example 80 - throw new Error('Unexpected request input type'); 81 - } 82 - }, 83 - }, 84 - }); 85 - ``` 86 - 87 - [corsproxy.io](https://corsproxy.io) is a public CORS proxy that works correctly 88 - with this package. 89 - 90 - The public CORS proxy [corsproxy.org](https://corsproxy.org) _does not work_ at 91 - the time of writing (at least not using their recommended integration on the 92 - front page). 93 - 94 - #### Next.js 13.x example: 95 - 96 - ```tsx 97 - 'use client'; 98 - 99 - import { Scraper, Tweet } from '@the-convocation/twitter-scraper'; 100 - import { useEffect, useMemo, useState } from 'react'; 101 - 102 - export default function Home() { 103 - const scraper = useMemo( 104 - () => 105 - new Scraper({ 106 - transform: { 107 - request(input: RequestInfo | URL, init?: RequestInit) { 108 - if (input instanceof URL) { 109 - const proxy = 110 - 'https://corsproxy.io/?' + encodeURIComponent(input.toString()); 111 - return [proxy, init]; 112 - } else if (typeof input === 'string') { 113 - const proxy = 114 - 'https://corsproxy.io/?' + encodeURIComponent(input); 115 - return [proxy, init]; 116 - } else { 117 - throw new Error('Unexpected request input type'); 118 - } 119 - }, 120 - }, 121 - }), 122 - [], 123 - ); 124 - const [tweet, setTweet] = useState<Tweet | null>(null); 125 - 126 - useEffect(() => { 127 - async function getTweet() { 128 - const latestTweet = await scraper.getLatestTweet('twitter'); 129 - if (latestTweet) { 130 - setTweet(latestTweet); 131 - } 132 - } 133 - 134 - getTweet(); 135 - }, [scraper]); 136 - 137 - return ( 138 - <main className="flex min-h-screen flex-col items-center justify-between p-24"> 139 - {tweet?.text} 140 - </main> 141 - ); 142 - } 143 - ``` 144 - 145 - ### Edge runtimes 146 - 147 - This package currently uses 148 - [`cross-fetch`](https://www.npmjs.com/package/cross-fetch) as a portable 149 - `fetch`. Edge runtimes such as CloudFlare Workers sometimes have `fetch` 150 - functions that behave differently from the web standard, so you may need to 151 - override the `fetch` function the scraper uses. If so, a custom `fetch` can be 152 - provided in the options: 153 - 154 - ```ts 155 - const scraper = new Scraper({ 156 - fetch: fetch, 157 - }); 158 - ``` 159 - 160 - Note that this does not change the arguments passed to the function, or the 161 - expected return type. If the custom `fetch` function produces runtime errors 162 - related to incorrect types, be sure to wrap it in a shim (not currently 163 - supported directly by interceptors): 164 - 165 - ```ts 166 - const scraper = new Scraper({ 167 - fetch: (input, init) => { 168 - // Transform input and init into your function's expected types... 169 - return fetch(input, init).then((res) => { 170 - // Transform res into a web-compliant response... 171 - return res; 172 - }); 173 - }, 174 - }); 175 - ``` 176 - 177 - ### Bypassing Cloudflare bot detection 178 - 179 - In some cases, Twitter's authentication endpoints may be protected by Cloudflare's advanced bot detection, resulting in `403 Forbidden` errors during login. This typically happens because standard Node.js TLS fingerprints are detected as non-browser clients. 180 - 181 - To bypass this protection, you can use the optional CycleTLS `fetch` integration to mimic Chrome browser TLS fingerprints: 182 - 183 - **Installation:** 184 - 185 - ```sh 186 - npm install cycletls 187 - # or 188 - yarn add cycletls 189 - ``` 190 - 191 - **Usage:** 192 - 193 - ```ts 194 - import { Scraper } from '@the-convocation/twitter-scraper'; 195 - import { 196 - cycleTLSFetch, 197 - cycleTLSExit, 198 - } from '@the-convocation/twitter-scraper/cycletls'; 199 - 200 - const scraper = new Scraper({ 201 - fetch: cycleTLSFetch, 202 - }); 203 - 204 - // Use the scraper normally 205 - await scraper.login(username, password, email); 206 - 207 - // Important: cleanup CycleTLS resources when done 208 - cycleTLSExit(); 209 - ``` 210 - 211 - **Note:** The `/cycletls` entrypoint is Node.js only and will not work in browser environments. It's provided as a separate optional entrypoint to avoid bundling binaries in environments where they cannot run. 212 - 213 - See the [cycletls example](./examples/cycletls/) for a complete working example. 214 - 215 - ### Rate limiting 216 - 217 - The Twitter API heavily rate-limits clients, requiring that the scraper has its own 218 - rate-limit handling to behave predictably when rate-limiting occurs. By default, the 219 - scraper uses a rate-limiting strategy that waits for the current rate-limiting period 220 - to expire before resuming requests. 221 - 222 - **This has been known to take a very long time, in some cases (up to 13 minutes).** 223 - 224 - You may want to change how rate-limiting events are handled, potentially by pooling 225 - scrapers logged-in to different accounts (refer to [#116](https://github.com/the-convocation/twitter-scraper/pull/116) for how to do this yourself). The rate-limit handling strategy can be configured by passing a custom 226 - implementation to the `rateLimitStrategy` option in the scraper constructor: 227 - 228 - ```ts 229 - import { Scraper, RateLimitStrategy } from '@the-convocation/twitter-scraper'; 230 - 231 - class CustomRateLimitStrategy implements RateLimitStrategy { 232 - async onRateLimit(event: RateLimitEvent): Promise<void> { 233 - // your own logic... 234 - } 235 - } 236 - 237 - const scraper = new Scraper({ 238 - rateLimitStrategy: new CustomRateLimitStrategy(), 239 - }); 240 - ``` 241 - 242 - More information on this interface can be found on the [`RateLimitStrategy`](https://the-convocation.github.io/twitter-scraper/interfaces/RateLimitStrategy.html) 243 - page in the documentation. The library provides two pre-written implementations to choose from: 244 - 245 - - `WaitingRateLimitStrategy`: The default, which waits for the limit to expire. 246 - - `ErrorRateLimitStrategy`: A strategy that throws if any rate-limit event occurs. 247 - 248 - ## Contributing 249 - 250 - ### Setup 251 - 252 - This project currently requires Node 18.x for development and uses Yarn for 253 - package management. 254 - [Corepack](https://nodejs.org/dist/latest-v18.x/docs/api/corepack.html) is 255 - configured for this project, so you don't need to install a particular package 256 - manager version manually. 257 - 258 - > The project supports Node 16.x at runtime, but requires Node 18.x to run its 259 - > build tools. 260 - 261 - Just run `corepack enable` to turn on the shims, then run `yarn` to install the 262 - dependencies. 263 - 264 - #### Basic scripts 265 - 266 - - `yarn build`: Builds the project into the `dist` folder 267 - - `yarn test`: Runs the package tests (see [Testing](#testing) first) 268 - 269 - Run `yarn help` for general `yarn` usage information. 270 - 271 - ### Testing 272 - 273 - This package includes unit tests for all major functionality. Given the speed at 274 - which Twitter's private API changes, failing tests are to be expected. 275 - 276 - ```sh 277 - yarn test 278 - ``` 279 - 280 - Before running tests, you should configure environment variables for 281 - authentication. 282 - 283 - ``` 284 - TWITTER_USERNAME= # Account username 285 - TWITTER_PASSWORD= # Account password 286 - TWITTER_EMAIL= # Account email 287 - TWITTER_COOKIES= # JSON-serialized array of cookies of an authenticated session 288 - PROXY_URL= # HTTP(s) proxy for requests (optional) 289 - ``` 290 - 291 - ### Commit message format 292 - 293 - We use [Conventional Commits](https://www.conventionalcommits.org), and enforce 294 - this with precommit checks. Please refer to the Git history for real examples of 295 - the commit message format.
-18
twitter-scraper/examples/cors-proxy/package.json
··· 1 - { 2 - "private": true, 3 - "packageManager": "yarn@1.22.19", 4 - "scripts": { 5 - "start": "tsx src/index.mts" 6 - }, 7 - "dependencies": { 8 - "@types/cookie": "^0.6.0", 9 - "@types/express": "^4.17.21", 10 - "@types/express-http-proxy": "^1.6.6", 11 - "@types/set-cookie-parser": "^2.4.9", 12 - "cookie": "^0.6.0", 13 - "express": "^4.19.2", 14 - "express-http-proxy": "^2.0.0", 15 - "set-cookie-parser": "^2.6.0", 16 - "tsx": "^4.15.5" 17 - } 18 - }
-79
twitter-scraper/examples/cors-proxy/src/index.mts
··· 1 - import proxy from 'express-http-proxy'; 2 - import express from 'express'; 3 - import setCookie from 'set-cookie-parser'; 4 - import libCookie from 'cookie'; 5 - 6 - const handlers: proxy.ProxyOptions = { 7 - proxyReqOptDecorator(proxyReqOpts) { 8 - const originalHeaders = structuredClone(proxyReqOpts.headers); 9 - for (const header in originalHeaders) { 10 - if (['origin', 'referer', 'host'].includes(header)) { 11 - delete proxyReqOpts.headers[header]; 12 - } 13 - } 14 - 15 - console.log(proxyReqOpts); 16 - 17 - return proxyReqOpts; 18 - }, 19 - userResHeaderDecorator(headers, userReq) { 20 - headers['access-control-allow-origin'] = 'http://localhost:5173'; 21 - headers['access-control-allow-credentials'] = 'true'; 22 - 23 - headers['access-control-allow-headers'] = Object.keys(headers) 24 - .concat([ 25 - 'authorization', 26 - 'content-type', 27 - 'x-twitter-client-language', 28 - 'x-twitter-auth-type', 29 - 'x-guest-token', 30 - 'x-twitter-active-user', 31 - 'x-rate-limit-remaining', 32 - 'x-rate-limit-reset', 33 - 'x-csrf-token', 34 - ]) 35 - .join(', '); 36 - 37 - if (headers['location']) { 38 - console.log(`Removing Location header: ${headers['location']}`); 39 - delete headers['location']; 40 - } 41 - 42 - if (headers['set-cookie']) { 43 - const origin = new URL(userReq.headers['origin']); 44 - headers['set-cookie'] = headers['set-cookie'].flatMap((header) => { 45 - const cookie = setCookie.parse(header); 46 - return cookie.map((c) => 47 - libCookie.serialize(c.name, c.value, { 48 - domain: `.${origin.hostname}`, 49 - path: '/', 50 - expires: c.expires, 51 - }), 52 - ); 53 - }); 54 - } 55 - 56 - console.log(headers); 57 - 58 - return headers; 59 - }, 60 - userResDecorator(_proxyRes, proxyResData, userReq, userRes) { 61 - if ( 62 - userReq.method === 'OPTIONS' || 63 - (userReq.statusCode >= 300 && userRes.statusCode < 400) 64 - ) { 65 - // Disable redirects, always return OK on OPTIONS 66 - userRes.statusCode = 200; 67 - } 68 - 69 - return proxyResData; 70 - }, 71 - }; 72 - 73 - const api = express(); 74 - api.use('/', proxy('https://api.x.com', handlers)); 75 - api.listen(5174); 76 - 77 - const web = express(); 78 - web.use('/', proxy('https://x.com', handlers)); 79 - web.listen(5175);
-7
twitter-scraper/examples/cors-proxy/tsconfig.json
··· 1 - { 2 - "compilerOptions": { 3 - "target": "ESNext", 4 - "module": "ESNext", 5 - "moduleResolution": "Bundler" 6 - } 7 - }
-763
twitter-scraper/examples/cors-proxy/yarn.lock
··· 1 - # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 - # yarn lockfile v1 3 - 4 - 5 - "@esbuild/aix-ppc64@0.21.5": 6 - version "0.21.5" 7 - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" 8 - integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== 9 - 10 - "@esbuild/android-arm64@0.21.5": 11 - version "0.21.5" 12 - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" 13 - integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== 14 - 15 - "@esbuild/android-arm@0.21.5": 16 - version "0.21.5" 17 - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" 18 - integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== 19 - 20 - "@esbuild/android-x64@0.21.5": 21 - version "0.21.5" 22 - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" 23 - integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== 24 - 25 - "@esbuild/darwin-arm64@0.21.5": 26 - version "0.21.5" 27 - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" 28 - integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== 29 - 30 - "@esbuild/darwin-x64@0.21.5": 31 - version "0.21.5" 32 - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" 33 - integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== 34 - 35 - "@esbuild/freebsd-arm64@0.21.5": 36 - version "0.21.5" 37 - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" 38 - integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== 39 - 40 - "@esbuild/freebsd-x64@0.21.5": 41 - version "0.21.5" 42 - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" 43 - integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== 44 - 45 - "@esbuild/linux-arm64@0.21.5": 46 - version "0.21.5" 47 - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" 48 - integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== 49 - 50 - "@esbuild/linux-arm@0.21.5": 51 - version "0.21.5" 52 - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" 53 - integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== 54 - 55 - "@esbuild/linux-ia32@0.21.5": 56 - version "0.21.5" 57 - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" 58 - integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== 59 - 60 - "@esbuild/linux-loong64@0.21.5": 61 - version "0.21.5" 62 - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" 63 - integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== 64 - 65 - "@esbuild/linux-mips64el@0.21.5": 66 - version "0.21.5" 67 - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" 68 - integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== 69 - 70 - "@esbuild/linux-ppc64@0.21.5": 71 - version "0.21.5" 72 - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" 73 - integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== 74 - 75 - "@esbuild/linux-riscv64@0.21.5": 76 - version "0.21.5" 77 - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" 78 - integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== 79 - 80 - "@esbuild/linux-s390x@0.21.5": 81 - version "0.21.5" 82 - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" 83 - integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== 84 - 85 - "@esbuild/linux-x64@0.21.5": 86 - version "0.21.5" 87 - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" 88 - integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== 89 - 90 - "@esbuild/netbsd-x64@0.21.5": 91 - version "0.21.5" 92 - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" 93 - integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== 94 - 95 - "@esbuild/openbsd-x64@0.21.5": 96 - version "0.21.5" 97 - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" 98 - integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== 99 - 100 - "@esbuild/sunos-x64@0.21.5": 101 - version "0.21.5" 102 - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" 103 - integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== 104 - 105 - "@esbuild/win32-arm64@0.21.5": 106 - version "0.21.5" 107 - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" 108 - integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== 109 - 110 - "@esbuild/win32-ia32@0.21.5": 111 - version "0.21.5" 112 - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" 113 - integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== 114 - 115 - "@esbuild/win32-x64@0.21.5": 116 - version "0.21.5" 117 - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" 118 - integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== 119 - 120 - "@types/body-parser@*": 121 - version "1.19.5" 122 - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" 123 - integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== 124 - dependencies: 125 - "@types/connect" "*" 126 - "@types/node" "*" 127 - 128 - "@types/connect@*": 129 - version "3.4.38" 130 - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" 131 - integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== 132 - dependencies: 133 - "@types/node" "*" 134 - 135 - "@types/cookie@^0.6.0": 136 - version "0.6.0" 137 - resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5" 138 - integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA== 139 - 140 - "@types/express-http-proxy@^1.6.6": 141 - version "1.6.6" 142 - resolved "https://registry.yarnpkg.com/@types/express-http-proxy/-/express-http-proxy-1.6.6.tgz#386c6f4c61a2d26ab8817ba1c2b2aac80e5638c9" 143 - integrity sha512-J8ZqHG76rq1UB716IZ3RCmUhg406pbWxsM3oFCFccl5xlWUPzoR4if6Og/cE4juK8emH0H9quZa5ltn6ZdmQJg== 144 - dependencies: 145 - "@types/express" "*" 146 - 147 - "@types/express-serve-static-core@^4.17.33": 148 - version "4.19.3" 149 - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.3.tgz#e469a13e4186c9e1c0418fb17be8bc8ff1b19a7a" 150 - integrity sha512-KOzM7MhcBFlmnlr/fzISFF5vGWVSvN6fTd4T+ExOt08bA/dA5kpSzY52nMsI1KDFmUREpJelPYyuslLRSjjgCg== 151 - dependencies: 152 - "@types/node" "*" 153 - "@types/qs" "*" 154 - "@types/range-parser" "*" 155 - "@types/send" "*" 156 - 157 - "@types/express@*", "@types/express@^4.17.21": 158 - version "4.17.21" 159 - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" 160 - integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== 161 - dependencies: 162 - "@types/body-parser" "*" 163 - "@types/express-serve-static-core" "^4.17.33" 164 - "@types/qs" "*" 165 - "@types/serve-static" "*" 166 - 167 - "@types/http-errors@*": 168 - version "2.0.4" 169 - resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" 170 - integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== 171 - 172 - "@types/mime@^1": 173 - version "1.3.5" 174 - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" 175 - integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== 176 - 177 - "@types/node@*": 178 - version "20.14.2" 179 - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.2.tgz#a5f4d2bcb4b6a87bffcaa717718c5a0f208f4a18" 180 - integrity sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q== 181 - dependencies: 182 - undici-types "~5.26.4" 183 - 184 - "@types/qs@*": 185 - version "6.9.15" 186 - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce" 187 - integrity sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg== 188 - 189 - "@types/range-parser@*": 190 - version "1.2.7" 191 - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" 192 - integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== 193 - 194 - "@types/send@*": 195 - version "0.17.4" 196 - resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" 197 - integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== 198 - dependencies: 199 - "@types/mime" "^1" 200 - "@types/node" "*" 201 - 202 - "@types/serve-static@*": 203 - version "1.15.7" 204 - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" 205 - integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== 206 - dependencies: 207 - "@types/http-errors" "*" 208 - "@types/node" "*" 209 - "@types/send" "*" 210 - 211 - "@types/set-cookie-parser@^2.4.9": 212 - version "2.4.9" 213 - resolved "https://registry.yarnpkg.com/@types/set-cookie-parser/-/set-cookie-parser-2.4.9.tgz#f8761e5aab0a855c3992e5d3a0016f5b1226b8ac" 214 - integrity sha512-bCorlULvl0xTdjj4BPUHX4cqs9I+go2TfW/7Do1nnFYWS0CPP429Qr1AY42kiFhCwLpvAkWFr1XIBHd8j6/MCQ== 215 - dependencies: 216 - "@types/node" "*" 217 - 218 - accepts@~1.3.8: 219 - version "1.3.8" 220 - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" 221 - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== 222 - dependencies: 223 - mime-types "~2.1.34" 224 - negotiator "0.6.3" 225 - 226 - array-flatten@1.1.1: 227 - version "1.1.1" 228 - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" 229 - integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== 230 - 231 - body-parser@1.20.2: 232 - version "1.20.2" 233 - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" 234 - integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== 235 - dependencies: 236 - bytes "3.1.2" 237 - content-type "~1.0.5" 238 - debug "2.6.9" 239 - depd "2.0.0" 240 - destroy "1.2.0" 241 - http-errors "2.0.0" 242 - iconv-lite "0.4.24" 243 - on-finished "2.4.1" 244 - qs "6.11.0" 245 - raw-body "2.5.2" 246 - type-is "~1.6.18" 247 - unpipe "1.0.0" 248 - 249 - bytes@3.1.2: 250 - version "3.1.2" 251 - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" 252 - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== 253 - 254 - call-bind@^1.0.7: 255 - version "1.0.7" 256 - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" 257 - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== 258 - dependencies: 259 - es-define-property "^1.0.0" 260 - es-errors "^1.3.0" 261 - function-bind "^1.1.2" 262 - get-intrinsic "^1.2.4" 263 - set-function-length "^1.2.1" 264 - 265 - content-disposition@0.5.4: 266 - version "0.5.4" 267 - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" 268 - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== 269 - dependencies: 270 - safe-buffer "5.2.1" 271 - 272 - content-type@~1.0.4, content-type@~1.0.5: 273 - version "1.0.5" 274 - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" 275 - integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== 276 - 277 - cookie-signature@1.0.6: 278 - version "1.0.6" 279 - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" 280 - integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== 281 - 282 - cookie@0.6.0, cookie@^0.6.0: 283 - version "0.6.0" 284 - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" 285 - integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== 286 - 287 - debug@2.6.9: 288 - version "2.6.9" 289 - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 290 - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 291 - dependencies: 292 - ms "2.0.0" 293 - 294 - debug@^3.0.1: 295 - version "3.2.7" 296 - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" 297 - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== 298 - dependencies: 299 - ms "^2.1.1" 300 - 301 - define-data-property@^1.1.4: 302 - version "1.1.4" 303 - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" 304 - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== 305 - dependencies: 306 - es-define-property "^1.0.0" 307 - es-errors "^1.3.0" 308 - gopd "^1.0.1" 309 - 310 - depd@2.0.0: 311 - version "2.0.0" 312 - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" 313 - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== 314 - 315 - destroy@1.2.0: 316 - version "1.2.0" 317 - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" 318 - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== 319 - 320 - ee-first@1.1.1: 321 - version "1.1.1" 322 - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 323 - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== 324 - 325 - encodeurl@~1.0.2: 326 - version "1.0.2" 327 - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 328 - integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== 329 - 330 - es-define-property@^1.0.0: 331 - version "1.0.0" 332 - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" 333 - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== 334 - dependencies: 335 - get-intrinsic "^1.2.4" 336 - 337 - es-errors@^1.3.0: 338 - version "1.3.0" 339 - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" 340 - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== 341 - 342 - es6-promise@^4.1.1: 343 - version "4.2.8" 344 - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" 345 - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== 346 - 347 - esbuild@~0.21.4: 348 - version "0.21.5" 349 - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" 350 - integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== 351 - optionalDependencies: 352 - "@esbuild/aix-ppc64" "0.21.5" 353 - "@esbuild/android-arm" "0.21.5" 354 - "@esbuild/android-arm64" "0.21.5" 355 - "@esbuild/android-x64" "0.21.5" 356 - "@esbuild/darwin-arm64" "0.21.5" 357 - "@esbuild/darwin-x64" "0.21.5" 358 - "@esbuild/freebsd-arm64" "0.21.5" 359 - "@esbuild/freebsd-x64" "0.21.5" 360 - "@esbuild/linux-arm" "0.21.5" 361 - "@esbuild/linux-arm64" "0.21.5" 362 - "@esbuild/linux-ia32" "0.21.5" 363 - "@esbuild/linux-loong64" "0.21.5" 364 - "@esbuild/linux-mips64el" "0.21.5" 365 - "@esbuild/linux-ppc64" "0.21.5" 366 - "@esbuild/linux-riscv64" "0.21.5" 367 - "@esbuild/linux-s390x" "0.21.5" 368 - "@esbuild/linux-x64" "0.21.5" 369 - "@esbuild/netbsd-x64" "0.21.5" 370 - "@esbuild/openbsd-x64" "0.21.5" 371 - "@esbuild/sunos-x64" "0.21.5" 372 - "@esbuild/win32-arm64" "0.21.5" 373 - "@esbuild/win32-ia32" "0.21.5" 374 - "@esbuild/win32-x64" "0.21.5" 375 - 376 - escape-html@~1.0.3: 377 - version "1.0.3" 378 - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 379 - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== 380 - 381 - etag@~1.8.1: 382 - version "1.8.1" 383 - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" 384 - integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== 385 - 386 - express-http-proxy@^2.0.0: 387 - version "2.0.0" 388 - resolved "https://registry.yarnpkg.com/express-http-proxy/-/express-http-proxy-2.0.0.tgz#c47f4d8b53e8d9c2b9a2f1d158eedf6eb84828a5" 389 - integrity sha512-TXxcPFTWVUMSEmyM6iX2sT/JtmqhqngTq29P+eXTVFdtxZrTmM8THUYK59rUXiln0FfPGvxEpGRnVrgvHksXDw== 390 - dependencies: 391 - debug "^3.0.1" 392 - es6-promise "^4.1.1" 393 - raw-body "^2.3.0" 394 - 395 - express@^4.19.2: 396 - version "4.19.2" 397 - resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" 398 - integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== 399 - dependencies: 400 - accepts "~1.3.8" 401 - array-flatten "1.1.1" 402 - body-parser "1.20.2" 403 - content-disposition "0.5.4" 404 - content-type "~1.0.4" 405 - cookie "0.6.0" 406 - cookie-signature "1.0.6" 407 - debug "2.6.9" 408 - depd "2.0.0" 409 - encodeurl "~1.0.2" 410 - escape-html "~1.0.3" 411 - etag "~1.8.1" 412 - finalhandler "1.2.0" 413 - fresh "0.5.2" 414 - http-errors "2.0.0" 415 - merge-descriptors "1.0.1" 416 - methods "~1.1.2" 417 - on-finished "2.4.1" 418 - parseurl "~1.3.3" 419 - path-to-regexp "0.1.7" 420 - proxy-addr "~2.0.7" 421 - qs "6.11.0" 422 - range-parser "~1.2.1" 423 - safe-buffer "5.2.1" 424 - send "0.18.0" 425 - serve-static "1.15.0" 426 - setprototypeof "1.2.0" 427 - statuses "2.0.1" 428 - type-is "~1.6.18" 429 - utils-merge "1.0.1" 430 - vary "~1.1.2" 431 - 432 - finalhandler@1.2.0: 433 - version "1.2.0" 434 - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" 435 - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== 436 - dependencies: 437 - debug "2.6.9" 438 - encodeurl "~1.0.2" 439 - escape-html "~1.0.3" 440 - on-finished "2.4.1" 441 - parseurl "~1.3.3" 442 - statuses "2.0.1" 443 - unpipe "~1.0.0" 444 - 445 - forwarded@0.2.0: 446 - version "0.2.0" 447 - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" 448 - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== 449 - 450 - fresh@0.5.2: 451 - version "0.5.2" 452 - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" 453 - integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== 454 - 455 - fsevents@~2.3.3: 456 - version "2.3.3" 457 - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" 458 - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== 459 - 460 - function-bind@^1.1.2: 461 - version "1.1.2" 462 - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" 463 - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== 464 - 465 - get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: 466 - version "1.2.4" 467 - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" 468 - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== 469 - dependencies: 470 - es-errors "^1.3.0" 471 - function-bind "^1.1.2" 472 - has-proto "^1.0.1" 473 - has-symbols "^1.0.3" 474 - hasown "^2.0.0" 475 - 476 - get-tsconfig@^4.7.5: 477 - version "4.7.5" 478 - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.5.tgz#5e012498579e9a6947511ed0cd403272c7acbbaf" 479 - integrity sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw== 480 - dependencies: 481 - resolve-pkg-maps "^1.0.0" 482 - 483 - gopd@^1.0.1: 484 - version "1.0.1" 485 - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" 486 - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== 487 - dependencies: 488 - get-intrinsic "^1.1.3" 489 - 490 - has-property-descriptors@^1.0.2: 491 - version "1.0.2" 492 - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" 493 - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== 494 - dependencies: 495 - es-define-property "^1.0.0" 496 - 497 - has-proto@^1.0.1: 498 - version "1.0.3" 499 - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" 500 - integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== 501 - 502 - has-symbols@^1.0.3: 503 - version "1.0.3" 504 - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" 505 - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== 506 - 507 - hasown@^2.0.0: 508 - version "2.0.2" 509 - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" 510 - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== 511 - dependencies: 512 - function-bind "^1.1.2" 513 - 514 - http-errors@2.0.0: 515 - version "2.0.0" 516 - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" 517 - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== 518 - dependencies: 519 - depd "2.0.0" 520 - inherits "2.0.4" 521 - setprototypeof "1.2.0" 522 - statuses "2.0.1" 523 - toidentifier "1.0.1" 524 - 525 - iconv-lite@0.4.24: 526 - version "0.4.24" 527 - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 528 - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 529 - dependencies: 530 - safer-buffer ">= 2.1.2 < 3" 531 - 532 - inherits@2.0.4: 533 - version "2.0.4" 534 - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 535 - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 536 - 537 - ipaddr.js@1.9.1: 538 - version "1.9.1" 539 - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" 540 - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== 541 - 542 - media-typer@0.3.0: 543 - version "0.3.0" 544 - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 545 - integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== 546 - 547 - merge-descriptors@1.0.1: 548 - version "1.0.1" 549 - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" 550 - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== 551 - 552 - methods@~1.1.2: 553 - version "1.1.2" 554 - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" 555 - integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== 556 - 557 - mime-db@1.52.0: 558 - version "1.52.0" 559 - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" 560 - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 561 - 562 - mime-types@~2.1.24, mime-types@~2.1.34: 563 - version "2.1.35" 564 - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" 565 - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 566 - dependencies: 567 - mime-db "1.52.0" 568 - 569 - mime@1.6.0: 570 - version "1.6.0" 571 - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" 572 - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== 573 - 574 - ms@2.0.0: 575 - version "2.0.0" 576 - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 577 - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== 578 - 579 - ms@2.1.3, ms@^2.1.1: 580 - version "2.1.3" 581 - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 582 - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 583 - 584 - negotiator@0.6.3: 585 - version "0.6.3" 586 - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" 587 - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== 588 - 589 - object-inspect@^1.13.1: 590 - version "1.13.1" 591 - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" 592 - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== 593 - 594 - on-finished@2.4.1: 595 - version "2.4.1" 596 - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" 597 - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== 598 - dependencies: 599 - ee-first "1.1.1" 600 - 601 - parseurl@~1.3.3: 602 - version "1.3.3" 603 - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" 604 - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== 605 - 606 - path-to-regexp@0.1.7: 607 - version "0.1.7" 608 - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" 609 - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== 610 - 611 - proxy-addr@~2.0.7: 612 - version "2.0.7" 613 - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" 614 - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== 615 - dependencies: 616 - forwarded "0.2.0" 617 - ipaddr.js "1.9.1" 618 - 619 - qs@6.11.0: 620 - version "6.11.0" 621 - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" 622 - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== 623 - dependencies: 624 - side-channel "^1.0.4" 625 - 626 - range-parser@~1.2.1: 627 - version "1.2.1" 628 - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" 629 - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== 630 - 631 - raw-body@2.5.2, raw-body@^2.3.0: 632 - version "2.5.2" 633 - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" 634 - integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== 635 - dependencies: 636 - bytes "3.1.2" 637 - http-errors "2.0.0" 638 - iconv-lite "0.4.24" 639 - unpipe "1.0.0" 640 - 641 - resolve-pkg-maps@^1.0.0: 642 - version "1.0.0" 643 - resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" 644 - integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== 645 - 646 - safe-buffer@5.2.1: 647 - version "5.2.1" 648 - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 649 - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 650 - 651 - "safer-buffer@>= 2.1.2 < 3": 652 - version "2.1.2" 653 - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 654 - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 655 - 656 - send@0.18.0: 657 - version "0.18.0" 658 - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" 659 - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== 660 - dependencies: 661 - debug "2.6.9" 662 - depd "2.0.0" 663 - destroy "1.2.0" 664 - encodeurl "~1.0.2" 665 - escape-html "~1.0.3" 666 - etag "~1.8.1" 667 - fresh "0.5.2" 668 - http-errors "2.0.0" 669 - mime "1.6.0" 670 - ms "2.1.3" 671 - on-finished "2.4.1" 672 - range-parser "~1.2.1" 673 - statuses "2.0.1" 674 - 675 - serve-static@1.15.0: 676 - version "1.15.0" 677 - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" 678 - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== 679 - dependencies: 680 - encodeurl "~1.0.2" 681 - escape-html "~1.0.3" 682 - parseurl "~1.3.3" 683 - send "0.18.0" 684 - 685 - set-cookie-parser@^2.6.0: 686 - version "2.6.0" 687 - resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz#131921e50f62ff1a66a461d7d62d7b21d5d15a51" 688 - integrity sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ== 689 - 690 - set-function-length@^1.2.1: 691 - version "1.2.2" 692 - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" 693 - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== 694 - dependencies: 695 - define-data-property "^1.1.4" 696 - es-errors "^1.3.0" 697 - function-bind "^1.1.2" 698 - get-intrinsic "^1.2.4" 699 - gopd "^1.0.1" 700 - has-property-descriptors "^1.0.2" 701 - 702 - setprototypeof@1.2.0: 703 - version "1.2.0" 704 - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" 705 - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== 706 - 707 - side-channel@^1.0.4: 708 - version "1.0.6" 709 - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" 710 - integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== 711 - dependencies: 712 - call-bind "^1.0.7" 713 - es-errors "^1.3.0" 714 - get-intrinsic "^1.2.4" 715 - object-inspect "^1.13.1" 716 - 717 - statuses@2.0.1: 718 - version "2.0.1" 719 - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" 720 - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== 721 - 722 - toidentifier@1.0.1: 723 - version "1.0.1" 724 - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" 725 - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== 726 - 727 - tsx@^4.15.5: 728 - version "4.15.5" 729 - resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.15.5.tgz#9c1ddb10ed0035c595c9b3e00ae40a3647a94c82" 730 - integrity sha512-iKi8jQ2VBmZ2kU/FkGkL2OSHBHsazsUzsdC/W/RwhKIEsIoZ1alCclZHP5jGfNHEaEWUJFM1GquzCf+4db3b0w== 731 - dependencies: 732 - esbuild "~0.21.4" 733 - get-tsconfig "^4.7.5" 734 - optionalDependencies: 735 - fsevents "~2.3.3" 736 - 737 - type-is@~1.6.18: 738 - version "1.6.18" 739 - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" 740 - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== 741 - dependencies: 742 - media-typer "0.3.0" 743 - mime-types "~2.1.24" 744 - 745 - undici-types@~5.26.4: 746 - version "5.26.5" 747 - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" 748 - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== 749 - 750 - unpipe@1.0.0, unpipe@~1.0.0: 751 - version "1.0.0" 752 - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 753 - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== 754 - 755 - utils-merge@1.0.1: 756 - version "1.0.1" 757 - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" 758 - integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== 759 - 760 - vary@~1.1.2: 761 - version "1.1.2" 762 - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 763 - integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
-48
twitter-scraper/examples/cycletls/README.md
··· 1 - # CycleTLS Cloudflare Bypass Example 2 - 3 - This example demonstrates how to use the `@the-convocation/twitter-scraper/cycletls` entrypoint to bypass Cloudflare bot detection when authenticating with Twitter. 4 - 5 - ## Problem 6 - 7 - Twitter's authentication endpoints may be protected by Cloudflare's bot detection, which analyzes TLS fingerprints to detect non-browser clients. Standard Node.js TLS handshakes can trigger `403 Forbidden` errors during login. 8 - 9 - ## Solution 10 - 11 - This example uses [CycleTLS](https://github.com/Danny-Dasilva/CycleTLS) to mimic Chrome browser TLS fingerprints, allowing requests to pass through Cloudflare's protection. 12 - 13 - ## Installation 14 - 15 - ```sh 16 - yarn install 17 - ``` 18 - 19 - ## Configuration 20 - 21 - Create a `.env` file in this directory with your Twitter credentials: 22 - 23 - ``` 24 - TWITTER_USERNAME=your_username 25 - TWITTER_PASSWORD=your_password 26 - TWITTER_EMAIL=your_email 27 - ``` 28 - 29 - ## Usage 30 - 31 - ```sh 32 - yarn start 33 - ``` 34 - 35 - ## How it works 36 - 37 - The example imports the `cycleTLSFetch` function from the `/cycletls` subpath: 38 - 39 - ```ts 40 - import { Scraper } from '@the-convocation/twitter-scraper'; 41 - import { cycleTLSFetch, cycleTLSExit } from '@the-convocation/twitter-scraper/cycletls'; 42 - 43 - const scraper = new Scraper({ 44 - fetch: cycleTLSFetch, 45 - }); 46 - ``` 47 - 48 - This replaces the default fetch implementation with one that uses Chrome-like TLS fingerprints, bypassing Cloudflare's detection.
-13
twitter-scraper/examples/cycletls/package.json
··· 1 - { 2 - "private": true, 3 - "packageManager": "yarn@1.22.19", 4 - "scripts": { 5 - "start": "tsx src/index.ts" 6 - }, 7 - "dependencies": { 8 - "@the-convocation/twitter-scraper": "file:../../", 9 - "cycletls": "^2.0.4", 10 - "dotenv": "^16.3.1", 11 - "tsx": "^4.15.5" 12 - } 13 - }
-56
twitter-scraper/examples/cycletls/src/index.ts
··· 1 - import assert from 'node:assert'; 2 - import { Scraper } from '@the-convocation/twitter-scraper'; 3 - import { 4 - cycleTLSFetch, 5 - cycleTLSExit, 6 - } from '@the-convocation/twitter-scraper/cycletls'; 7 - import dotenv from 'dotenv'; 8 - 9 - dotenv.config({ path: '.env.local' }); 10 - 11 - /** 12 - * Example: Using CycleTLS to bypass Cloudflare bot detection 13 - * 14 - * CycleTLS uses golang to mimic Chrome browser TLS fingerprints, which helps 15 - * bypass Cloudflare's advanced bot detection. This is particularly useful 16 - * when you encounter 403 errors during authentication. 17 - * 18 - * Usage: 19 - * 1. Install cycletls: yarn add cycletls 20 - * 2. Pass cycleTLSFetch as the fetch option when creating a Scraper 21 - * 3. Make sure to call cycleTLSExit() when done to cleanup resources 22 - */ 23 - 24 - // Load credentials from the environment 25 - const username = process.env['TWITTER_USERNAME']; 26 - const password = process.env['TWITTER_PASSWORD']; 27 - const email = process.env['TWITTER_EMAIL']; 28 - 29 - assert(username && password && email, 'Missing required environment variables'); 30 - 31 - // Create scraper with CycleTLS fetch 32 - const scraper = new Scraper({ 33 - fetch: cycleTLSFetch, 34 - }); 35 - 36 - const main = async () => { 37 - try { 38 - console.log('Logging in with CycleTLS-powered requests...'); 39 - await scraper.login(username, password, email); 40 - 41 - console.log('Login successful! Fetching a tweet...'); 42 - const tweet = await scraper.getTweet('1585338303800578049'); 43 - 44 - console.log('Tweet details:'); 45 - console.log(`- Text: ${tweet?.text}`); 46 - console.log(`- Likes: ${tweet?.likes}`); 47 - console.log(`- Retweets: ${tweet?.retweets}`); 48 - } catch (error) { 49 - console.error('Error:', error); 50 - } finally { 51 - // Important: cleanup CycleTLS resources 52 - cycleTLSExit(); 53 - } 54 - }; 55 - 56 - main();
-7
twitter-scraper/examples/cycletls/tsconfig.json
··· 1 - { 2 - "extends": "../../tsconfig.json", 3 - "compilerOptions": { 4 - "outDir": "./dist" 5 - }, 6 - "include": ["src"] 7 - }
-589
twitter-scraper/examples/cycletls/yarn.lock
··· 1 - # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 - # yarn lockfile v1 3 - 4 - 5 - "@esbuild/aix-ppc64@0.25.10": 6 - version "0.25.10" 7 - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz#ee6b7163a13528e099ecf562b972f2bcebe0aa97" 8 - integrity sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw== 9 - 10 - "@esbuild/android-arm64@0.25.10": 11 - version "0.25.10" 12 - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz#115fc76631e82dd06811bfaf2db0d4979c16e2cb" 13 - integrity sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg== 14 - 15 - "@esbuild/android-arm@0.25.10": 16 - version "0.25.10" 17 - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.10.tgz#8d5811912da77f615398611e5bbc1333fe321aa9" 18 - integrity sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w== 19 - 20 - "@esbuild/android-x64@0.25.10": 21 - version "0.25.10" 22 - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.10.tgz#e3e96516b2d50d74105bb92594c473e30ddc16b1" 23 - integrity sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg== 24 - 25 - "@esbuild/darwin-arm64@0.25.10": 26 - version "0.25.10" 27 - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz#6af6bb1d05887dac515de1b162b59dc71212ed76" 28 - integrity sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA== 29 - 30 - "@esbuild/darwin-x64@0.25.10": 31 - version "0.25.10" 32 - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz#99ae82347fbd336fc2d28ffd4f05694e6e5b723d" 33 - integrity sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg== 34 - 35 - "@esbuild/freebsd-arm64@0.25.10": 36 - version "0.25.10" 37 - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz#0c6d5558a6322b0bdb17f7025c19bd7d2359437d" 38 - integrity sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg== 39 - 40 - "@esbuild/freebsd-x64@0.25.10": 41 - version "0.25.10" 42 - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz#8c35873fab8c0857a75300a3dcce4324ca0b9844" 43 - integrity sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA== 44 - 45 - "@esbuild/linux-arm64@0.25.10": 46 - version "0.25.10" 47 - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz#3edc2f87b889a15b4cedaf65f498c2bed7b16b90" 48 - integrity sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ== 49 - 50 - "@esbuild/linux-arm@0.25.10": 51 - version "0.25.10" 52 - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz#86501cfdfb3d110176d80c41b27ed4611471cde7" 53 - integrity sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg== 54 - 55 - "@esbuild/linux-ia32@0.25.10": 56 - version "0.25.10" 57 - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz#e6589877876142537c6864680cd5d26a622b9d97" 58 - integrity sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ== 59 - 60 - "@esbuild/linux-loong64@0.25.10": 61 - version "0.25.10" 62 - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz#11119e18781f136d8083ea10eb6be73db7532de8" 63 - integrity sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg== 64 - 65 - "@esbuild/linux-mips64el@0.25.10": 66 - version "0.25.10" 67 - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz#3052f5436b0c0c67a25658d5fc87f045e7def9e6" 68 - integrity sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA== 69 - 70 - "@esbuild/linux-ppc64@0.25.10": 71 - version "0.25.10" 72 - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz#2f098920ee5be2ce799f35e367b28709925a8744" 73 - integrity sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA== 74 - 75 - "@esbuild/linux-riscv64@0.25.10": 76 - version "0.25.10" 77 - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz#fa51d7fd0a22a62b51b4b94b405a3198cf7405dd" 78 - integrity sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA== 79 - 80 - "@esbuild/linux-s390x@0.25.10": 81 - version "0.25.10" 82 - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz#a27642e36fc282748fdb38954bd3ef4f85791e8a" 83 - integrity sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew== 84 - 85 - "@esbuild/linux-x64@0.25.10": 86 - version "0.25.10" 87 - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz#9d9b09c0033d17529570ced6d813f98315dfe4e9" 88 - integrity sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA== 89 - 90 - "@esbuild/netbsd-arm64@0.25.10": 91 - version "0.25.10" 92 - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz#25c09a659c97e8af19e3f2afd1c9190435802151" 93 - integrity sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A== 94 - 95 - "@esbuild/netbsd-x64@0.25.10": 96 - version "0.25.10" 97 - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz#7fa5f6ffc19be3a0f6f5fd32c90df3dc2506937a" 98 - integrity sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig== 99 - 100 - "@esbuild/openbsd-arm64@0.25.10": 101 - version "0.25.10" 102 - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz#8faa6aa1afca0c6d024398321d6cb1c18e72a1c3" 103 - integrity sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw== 104 - 105 - "@esbuild/openbsd-x64@0.25.10": 106 - version "0.25.10" 107 - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz#a42979b016f29559a8453d32440d3c8cd420af5e" 108 - integrity sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw== 109 - 110 - "@esbuild/openharmony-arm64@0.25.10": 111 - version "0.25.10" 112 - resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz#fd87bfeadd7eeb3aa384bbba907459ffa3197cb1" 113 - integrity sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag== 114 - 115 - "@esbuild/sunos-x64@0.25.10": 116 - version "0.25.10" 117 - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz#3a18f590e36cb78ae7397976b760b2b8c74407f4" 118 - integrity sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ== 119 - 120 - "@esbuild/win32-arm64@0.25.10": 121 - version "0.25.10" 122 - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz#e71741a251e3fd971408827a529d2325551f530c" 123 - integrity sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw== 124 - 125 - "@esbuild/win32-ia32@0.25.10": 126 - version "0.25.10" 127 - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz#c6f010b5d3b943d8901a0c87ea55f93b8b54bf94" 128 - integrity sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw== 129 - 130 - "@esbuild/win32-x64@0.25.10": 131 - version "0.25.10" 132 - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz#e4b3e255a1b4aea84f6e1d2ae0b73f826c3785bd" 133 - integrity sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw== 134 - 135 - "@noble/hashes@1.8.0": 136 - version "1.8.0" 137 - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.8.0.tgz#cee43d801fcef9644b11b8194857695acd5f815a" 138 - integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== 139 - 140 - "@sinclair/typebox@^0.32.20": 141 - version "0.32.35" 142 - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.32.35.tgz#41c04473509478df9895800018a3d3ae7d40fb3c" 143 - integrity sha512-Ul3YyOTU++to8cgNkttakC0dWvpERr6RYoHO2W47DLbFvrwBDJUY31B1sImH6JZSYc4Kt4PyHtoPNu+vL2r2dA== 144 - 145 - "@the-convocation/twitter-scraper@file:../..": 146 - version "0.19.0" 147 - dependencies: 148 - "@sinclair/typebox" "^0.32.20" 149 - cross-fetch "^4.0.0-alpha.5" 150 - debug "^4.4.1" 151 - headers-polyfill "^3.1.2" 152 - json-stable-stringify "^1.0.2" 153 - otpauth "^9.2.2" 154 - set-cookie-parser "^2.6.0" 155 - tough-cookie "^4.1.2" 156 - tslib "^2.5.2" 157 - 158 - "@types/node@^20.14.0": 159 - version "20.19.18" 160 - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.18.tgz#e21af71b0234f59498888629bc5ce53ec9fd0b9d" 161 - integrity sha512-KeYVbfnbsBCyKG8e3gmUqAfyZNcoj/qpEbHRkQkfZdKOBrU7QQ+BsTdfqLSWX9/m1ytYreMhpKvp+EZi3UFYAg== 162 - dependencies: 163 - undici-types "~6.21.0" 164 - 165 - async-function@^1.0.0: 166 - version "1.0.0" 167 - resolved "https://registry.yarnpkg.com/async-function/-/async-function-1.0.0.tgz#509c9fca60eaf85034c6829838188e4e4c8ffb2b" 168 - integrity sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA== 169 - 170 - async-generator-function@^1.0.0: 171 - version "1.0.0" 172 - resolved "https://registry.yarnpkg.com/async-generator-function/-/async-generator-function-1.0.0.tgz#9bcc76d7fd147171e7ead5d2a2cfc3579c99f28e" 173 - integrity sha512-+NAXNqgCrB95ya4Sr66i1CL2hqLVckAk7xwRYWdcm39/ELQ6YNn1aw5r0bdQtqNZgQpEWzc5yc/igXc7aL5SLA== 174 - 175 - asynckit@^0.4.0: 176 - version "0.4.0" 177 - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 178 - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== 179 - 180 - call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: 181 - version "1.0.2" 182 - resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" 183 - integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== 184 - dependencies: 185 - es-errors "^1.3.0" 186 - function-bind "^1.1.2" 187 - 188 - call-bind@^1.0.8: 189 - version "1.0.8" 190 - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" 191 - integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== 192 - dependencies: 193 - call-bind-apply-helpers "^1.0.0" 194 - es-define-property "^1.0.0" 195 - get-intrinsic "^1.2.4" 196 - set-function-length "^1.2.2" 197 - 198 - call-bound@^1.0.4: 199 - version "1.0.4" 200 - resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" 201 - integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== 202 - dependencies: 203 - call-bind-apply-helpers "^1.0.2" 204 - get-intrinsic "^1.3.0" 205 - 206 - combined-stream@^1.0.8: 207 - version "1.0.8" 208 - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 209 - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 210 - dependencies: 211 - delayed-stream "~1.0.0" 212 - 213 - cross-fetch@^4.0.0-alpha.5: 214 - version "4.1.0" 215 - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.1.0.tgz#8f69355007ee182e47fa692ecbaa37a52e43c3d2" 216 - integrity sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw== 217 - dependencies: 218 - node-fetch "^2.7.0" 219 - 220 - cycletls@^2.0.4: 221 - version "2.0.4" 222 - resolved "https://registry.yarnpkg.com/cycletls/-/cycletls-2.0.4.tgz#8ae978f05a43ba9aba2d3c19d89630cc736868ab" 223 - integrity sha512-kyQewFdaKa+IiUd4sR0PmNP0+xXPTx+7eC8LPTmR0/F5Txv40Z7OSI46cQqWM8cgiCwOf6GsB3s9QK9TLizYog== 224 - dependencies: 225 - "@types/node" "^20.14.0" 226 - form-data "^4.0.0" 227 - ws "^8.17.0" 228 - 229 - debug@^4.4.1: 230 - version "4.4.3" 231 - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" 232 - integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== 233 - dependencies: 234 - ms "^2.1.3" 235 - 236 - define-data-property@^1.1.4: 237 - version "1.1.4" 238 - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" 239 - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== 240 - dependencies: 241 - es-define-property "^1.0.0" 242 - es-errors "^1.3.0" 243 - gopd "^1.0.1" 244 - 245 - delayed-stream@~1.0.0: 246 - version "1.0.0" 247 - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 248 - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== 249 - 250 - dotenv@^16.3.1: 251 - version "16.6.1" 252 - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.6.1.tgz#773f0e69527a8315c7285d5ee73c4459d20a8020" 253 - integrity sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow== 254 - 255 - dunder-proto@^1.0.1: 256 - version "1.0.1" 257 - resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" 258 - integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== 259 - dependencies: 260 - call-bind-apply-helpers "^1.0.1" 261 - es-errors "^1.3.0" 262 - gopd "^1.2.0" 263 - 264 - es-define-property@^1.0.0, es-define-property@^1.0.1: 265 - version "1.0.1" 266 - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" 267 - integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== 268 - 269 - es-errors@^1.3.0: 270 - version "1.3.0" 271 - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" 272 - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== 273 - 274 - es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: 275 - version "1.1.1" 276 - resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" 277 - integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== 278 - dependencies: 279 - es-errors "^1.3.0" 280 - 281 - es-set-tostringtag@^2.1.0: 282 - version "2.1.0" 283 - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" 284 - integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== 285 - dependencies: 286 - es-errors "^1.3.0" 287 - get-intrinsic "^1.2.6" 288 - has-tostringtag "^1.0.2" 289 - hasown "^2.0.2" 290 - 291 - esbuild@~0.25.0: 292 - version "0.25.10" 293 - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.10.tgz#37f5aa5cd14500f141be121c01b096ca83ac34a9" 294 - integrity sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ== 295 - optionalDependencies: 296 - "@esbuild/aix-ppc64" "0.25.10" 297 - "@esbuild/android-arm" "0.25.10" 298 - "@esbuild/android-arm64" "0.25.10" 299 - "@esbuild/android-x64" "0.25.10" 300 - "@esbuild/darwin-arm64" "0.25.10" 301 - "@esbuild/darwin-x64" "0.25.10" 302 - "@esbuild/freebsd-arm64" "0.25.10" 303 - "@esbuild/freebsd-x64" "0.25.10" 304 - "@esbuild/linux-arm" "0.25.10" 305 - "@esbuild/linux-arm64" "0.25.10" 306 - "@esbuild/linux-ia32" "0.25.10" 307 - "@esbuild/linux-loong64" "0.25.10" 308 - "@esbuild/linux-mips64el" "0.25.10" 309 - "@esbuild/linux-ppc64" "0.25.10" 310 - "@esbuild/linux-riscv64" "0.25.10" 311 - "@esbuild/linux-s390x" "0.25.10" 312 - "@esbuild/linux-x64" "0.25.10" 313 - "@esbuild/netbsd-arm64" "0.25.10" 314 - "@esbuild/netbsd-x64" "0.25.10" 315 - "@esbuild/openbsd-arm64" "0.25.10" 316 - "@esbuild/openbsd-x64" "0.25.10" 317 - "@esbuild/openharmony-arm64" "0.25.10" 318 - "@esbuild/sunos-x64" "0.25.10" 319 - "@esbuild/win32-arm64" "0.25.10" 320 - "@esbuild/win32-ia32" "0.25.10" 321 - "@esbuild/win32-x64" "0.25.10" 322 - 323 - form-data@^4.0.0: 324 - version "4.0.4" 325 - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.4.tgz#784cdcce0669a9d68e94d11ac4eea98088edd2c4" 326 - integrity sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow== 327 - dependencies: 328 - asynckit "^0.4.0" 329 - combined-stream "^1.0.8" 330 - es-set-tostringtag "^2.1.0" 331 - hasown "^2.0.2" 332 - mime-types "^2.1.12" 333 - 334 - fsevents@~2.3.3: 335 - version "2.3.3" 336 - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" 337 - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== 338 - 339 - function-bind@^1.1.2: 340 - version "1.1.2" 341 - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" 342 - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== 343 - 344 - generator-function@^2.0.0: 345 - version "2.0.0" 346 - resolved "https://registry.yarnpkg.com/generator-function/-/generator-function-2.0.0.tgz#f7d330dccf367a666195948580655946d1a3860a" 347 - integrity sha512-xPypGGincdfyl/AiSGa7GjXLkvld9V7GjZlowup9SHIJnQnHLFiLODCd/DqKOp0PBagbHJ68r1KJI9Mut7m4sA== 348 - 349 - get-intrinsic@^1.2.4, get-intrinsic@^1.2.6, get-intrinsic@^1.3.0: 350 - version "1.3.1" 351 - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.1.tgz#7f03d6cc8df96ae803c35cf23590510f28357173" 352 - integrity sha512-fk1ZVEeOX9hVZ6QzoBNEC55+Ucqg4sTVwrVuigZhuRPESVFpMyXnd3sbXvPOwp7Y9riVyANiqhEuRF0G1aVSeQ== 353 - dependencies: 354 - async-function "^1.0.0" 355 - async-generator-function "^1.0.0" 356 - call-bind-apply-helpers "^1.0.2" 357 - es-define-property "^1.0.1" 358 - es-errors "^1.3.0" 359 - es-object-atoms "^1.1.1" 360 - function-bind "^1.1.2" 361 - generator-function "^2.0.0" 362 - get-proto "^1.0.1" 363 - gopd "^1.2.0" 364 - has-symbols "^1.1.0" 365 - hasown "^2.0.2" 366 - math-intrinsics "^1.1.0" 367 - 368 - get-proto@^1.0.1: 369 - version "1.0.1" 370 - resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" 371 - integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== 372 - dependencies: 373 - dunder-proto "^1.0.1" 374 - es-object-atoms "^1.0.0" 375 - 376 - get-tsconfig@^4.7.5: 377 - version "4.10.1" 378 - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.10.1.tgz#d34c1c01f47d65a606c37aa7a177bc3e56ab4b2e" 379 - integrity sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ== 380 - dependencies: 381 - resolve-pkg-maps "^1.0.0" 382 - 383 - gopd@^1.0.1, gopd@^1.2.0: 384 - version "1.2.0" 385 - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" 386 - integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== 387 - 388 - has-property-descriptors@^1.0.2: 389 - version "1.0.2" 390 - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" 391 - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== 392 - dependencies: 393 - es-define-property "^1.0.0" 394 - 395 - has-symbols@^1.0.3, has-symbols@^1.1.0: 396 - version "1.1.0" 397 - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" 398 - integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== 399 - 400 - has-tostringtag@^1.0.2: 401 - version "1.0.2" 402 - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" 403 - integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== 404 - dependencies: 405 - has-symbols "^1.0.3" 406 - 407 - hasown@^2.0.2: 408 - version "2.0.2" 409 - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" 410 - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== 411 - dependencies: 412 - function-bind "^1.1.2" 413 - 414 - headers-polyfill@^3.1.2: 415 - version "3.3.0" 416 - resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-3.3.0.tgz#67c6ef7b72d4c8cac832ad5936f5b3a56e7b705a" 417 - integrity sha512-5e57etwBpNcDc0b6KCVWEh/Ro063OxPvzVimUdM0/tsYM/T7Hfy3kknIGj78SFTOhNd8AZY41U8mOHoO4LzmIQ== 418 - 419 - isarray@^2.0.5: 420 - version "2.0.5" 421 - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" 422 - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== 423 - 424 - json-stable-stringify@^1.0.2: 425 - version "1.3.0" 426 - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz#8903cfac42ea1a0f97f35d63a4ce0518f0cc6a70" 427 - integrity sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg== 428 - dependencies: 429 - call-bind "^1.0.8" 430 - call-bound "^1.0.4" 431 - isarray "^2.0.5" 432 - jsonify "^0.0.1" 433 - object-keys "^1.1.1" 434 - 435 - jsonify@^0.0.1: 436 - version "0.0.1" 437 - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" 438 - integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== 439 - 440 - math-intrinsics@^1.1.0: 441 - version "1.1.0" 442 - resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" 443 - integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== 444 - 445 - mime-db@1.52.0: 446 - version "1.52.0" 447 - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" 448 - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 449 - 450 - mime-types@^2.1.12: 451 - version "2.1.35" 452 - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" 453 - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 454 - dependencies: 455 - mime-db "1.52.0" 456 - 457 - ms@^2.1.3: 458 - version "2.1.3" 459 - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 460 - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 461 - 462 - node-fetch@^2.7.0: 463 - version "2.7.0" 464 - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" 465 - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== 466 - dependencies: 467 - whatwg-url "^5.0.0" 468 - 469 - object-keys@^1.1.1: 470 - version "1.1.1" 471 - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" 472 - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== 473 - 474 - otpauth@^9.2.2: 475 - version "9.4.1" 476 - resolved "https://registry.yarnpkg.com/otpauth/-/otpauth-9.4.1.tgz#6c5d8cf82b441b2f9f2a2a64ba5e00b992f5f31f" 477 - integrity sha512-+iVvys36CFsyXEqfNftQm1II7SW23W1wx9RwNk0Cd97lbvorqAhBDksb/0bYry087QMxjiuBS0wokdoZ0iUeAw== 478 - dependencies: 479 - "@noble/hashes" "1.8.0" 480 - 481 - psl@^1.1.33: 482 - version "1.15.0" 483 - resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" 484 - integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w== 485 - dependencies: 486 - punycode "^2.3.1" 487 - 488 - punycode@^2.1.1, punycode@^2.3.1: 489 - version "2.3.1" 490 - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" 491 - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== 492 - 493 - querystringify@^2.1.1: 494 - version "2.2.0" 495 - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" 496 - integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== 497 - 498 - requires-port@^1.0.0: 499 - version "1.0.0" 500 - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" 501 - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== 502 - 503 - resolve-pkg-maps@^1.0.0: 504 - version "1.0.0" 505 - resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" 506 - integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== 507 - 508 - set-cookie-parser@^2.6.0: 509 - version "2.7.1" 510 - resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz#3016f150072202dfbe90fadee053573cc89d2943" 511 - integrity sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ== 512 - 513 - set-function-length@^1.2.2: 514 - version "1.2.2" 515 - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" 516 - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== 517 - dependencies: 518 - define-data-property "^1.1.4" 519 - es-errors "^1.3.0" 520 - function-bind "^1.1.2" 521 - get-intrinsic "^1.2.4" 522 - gopd "^1.0.1" 523 - has-property-descriptors "^1.0.2" 524 - 525 - tough-cookie@^4.1.2: 526 - version "4.1.4" 527 - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" 528 - integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== 529 - dependencies: 530 - psl "^1.1.33" 531 - punycode "^2.1.1" 532 - universalify "^0.2.0" 533 - url-parse "^1.5.3" 534 - 535 - tr46@~0.0.3: 536 - version "0.0.3" 537 - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" 538 - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== 539 - 540 - tslib@^2.5.2: 541 - version "2.8.1" 542 - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" 543 - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== 544 - 545 - tsx@^4.15.5: 546 - version "4.20.6" 547 - resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.20.6.tgz#8fb803fd9c1f70e8ccc93b5d7c5e03c3979ccb2e" 548 - integrity sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg== 549 - dependencies: 550 - esbuild "~0.25.0" 551 - get-tsconfig "^4.7.5" 552 - optionalDependencies: 553 - fsevents "~2.3.3" 554 - 555 - undici-types@~6.21.0: 556 - version "6.21.0" 557 - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" 558 - integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== 559 - 560 - universalify@^0.2.0: 561 - version "0.2.0" 562 - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" 563 - integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== 564 - 565 - url-parse@^1.5.3: 566 - version "1.5.10" 567 - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" 568 - integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== 569 - dependencies: 570 - querystringify "^2.1.1" 571 - requires-port "^1.0.0" 572 - 573 - webidl-conversions@^3.0.0: 574 - version "3.0.1" 575 - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" 576 - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== 577 - 578 - whatwg-url@^5.0.0: 579 - version "5.0.0" 580 - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" 581 - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== 582 - dependencies: 583 - tr46 "~0.0.3" 584 - webidl-conversions "^3.0.0" 585 - 586 - ws@^8.17.0: 587 - version "8.18.3" 588 - resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472" 589 - integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==
-11
twitter-scraper/examples/etc-compat/package.json
··· 1 - { 2 - "private": true, 3 - "packageManager": "yarn@1.22.19", 4 - "scripts": { 5 - "start": "tsx src/index.mts" 6 - }, 7 - "dependencies": { 8 - "@the-convocation/twitter-scraper": "file:../../", 9 - "tsx": "^4.15.5" 10 - } 11 - }
-16
twitter-scraper/examples/etc-compat/src/index.mts
··· 1 - /* eslint-disable @typescript-eslint/no-unused-vars */ 2 - import { 3 - Profile, 4 - Tweet, 5 - Mention, 6 - Photo, 7 - PlaceRaw, 8 - Video, 9 - } from '@the-convocation/twitter-scraper'; 10 - 11 - const a: Profile = null as unknown as Profile; 12 - const b: Tweet = null as unknown as Tweet; 13 - const c: Mention = null as unknown as Mention; 14 - const d: Photo = null as unknown as Photo; 15 - const e: PlaceRaw = null as unknown as PlaceRaw; 16 - const f: Video = null as unknown as Video;
-8
twitter-scraper/examples/etc-compat/tsconfig.json
··· 1 - { 2 - "compilerOptions": { 3 - "target": "ESNext", 4 - "module": "ESNext", 5 - "moduleResolution": "Bundler" 6 - } 7 - } 8 -
-409
twitter-scraper/examples/etc-compat/yarn.lock
··· 1 - # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 - # yarn lockfile v1 3 - 4 - 5 - "@esbuild/aix-ppc64@0.21.5": 6 - version "0.21.5" 7 - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" 8 - integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== 9 - 10 - "@esbuild/android-arm64@0.21.5": 11 - version "0.21.5" 12 - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" 13 - integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== 14 - 15 - "@esbuild/android-arm@0.21.5": 16 - version "0.21.5" 17 - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" 18 - integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== 19 - 20 - "@esbuild/android-x64@0.21.5": 21 - version "0.21.5" 22 - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" 23 - integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== 24 - 25 - "@esbuild/darwin-arm64@0.21.5": 26 - version "0.21.5" 27 - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" 28 - integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== 29 - 30 - "@esbuild/darwin-x64@0.21.5": 31 - version "0.21.5" 32 - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" 33 - integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== 34 - 35 - "@esbuild/freebsd-arm64@0.21.5": 36 - version "0.21.5" 37 - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" 38 - integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== 39 - 40 - "@esbuild/freebsd-x64@0.21.5": 41 - version "0.21.5" 42 - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" 43 - integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== 44 - 45 - "@esbuild/linux-arm64@0.21.5": 46 - version "0.21.5" 47 - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" 48 - integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== 49 - 50 - "@esbuild/linux-arm@0.21.5": 51 - version "0.21.5" 52 - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" 53 - integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== 54 - 55 - "@esbuild/linux-ia32@0.21.5": 56 - version "0.21.5" 57 - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" 58 - integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== 59 - 60 - "@esbuild/linux-loong64@0.21.5": 61 - version "0.21.5" 62 - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" 63 - integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== 64 - 65 - "@esbuild/linux-mips64el@0.21.5": 66 - version "0.21.5" 67 - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" 68 - integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== 69 - 70 - "@esbuild/linux-ppc64@0.21.5": 71 - version "0.21.5" 72 - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" 73 - integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== 74 - 75 - "@esbuild/linux-riscv64@0.21.5": 76 - version "0.21.5" 77 - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" 78 - integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== 79 - 80 - "@esbuild/linux-s390x@0.21.5": 81 - version "0.21.5" 82 - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" 83 - integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== 84 - 85 - "@esbuild/linux-x64@0.21.5": 86 - version "0.21.5" 87 - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" 88 - integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== 89 - 90 - "@esbuild/netbsd-x64@0.21.5": 91 - version "0.21.5" 92 - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" 93 - integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== 94 - 95 - "@esbuild/openbsd-x64@0.21.5": 96 - version "0.21.5" 97 - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" 98 - integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== 99 - 100 - "@esbuild/sunos-x64@0.21.5": 101 - version "0.21.5" 102 - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" 103 - integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== 104 - 105 - "@esbuild/win32-arm64@0.21.5": 106 - version "0.21.5" 107 - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" 108 - integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== 109 - 110 - "@esbuild/win32-ia32@0.21.5": 111 - version "0.21.5" 112 - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" 113 - integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== 114 - 115 - "@esbuild/win32-x64@0.21.5": 116 - version "0.21.5" 117 - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" 118 - integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== 119 - 120 - "@noble/hashes@1.4.0": 121 - version "1.4.0" 122 - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" 123 - integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== 124 - 125 - "@sinclair/typebox@^0.32.20": 126 - version "0.32.35" 127 - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.32.35.tgz#41c04473509478df9895800018a3d3ae7d40fb3c" 128 - integrity sha512-Ul3YyOTU++to8cgNkttakC0dWvpERr6RYoHO2W47DLbFvrwBDJUY31B1sImH6JZSYc4Kt4PyHtoPNu+vL2r2dA== 129 - 130 - "@the-convocation/twitter-scraper@file:../..": 131 - version "0.14.1" 132 - dependencies: 133 - "@sinclair/typebox" "^0.32.20" 134 - cross-fetch "^4.0.0-alpha.5" 135 - headers-polyfill "^3.1.2" 136 - json-stable-stringify "^1.0.2" 137 - otpauth "^9.2.2" 138 - set-cookie-parser "^2.6.0" 139 - tough-cookie "^4.1.2" 140 - tslib "^2.5.2" 141 - 142 - call-bind@^1.0.5: 143 - version "1.0.7" 144 - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" 145 - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== 146 - dependencies: 147 - es-define-property "^1.0.0" 148 - es-errors "^1.3.0" 149 - function-bind "^1.1.2" 150 - get-intrinsic "^1.2.4" 151 - set-function-length "^1.2.1" 152 - 153 - cross-fetch@^4.0.0-alpha.5: 154 - version "4.0.0" 155 - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.0.0.tgz#f037aef1580bb3a1a35164ea2a848ba81b445983" 156 - integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g== 157 - dependencies: 158 - node-fetch "^2.6.12" 159 - 160 - define-data-property@^1.1.4: 161 - version "1.1.4" 162 - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" 163 - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== 164 - dependencies: 165 - es-define-property "^1.0.0" 166 - es-errors "^1.3.0" 167 - gopd "^1.0.1" 168 - 169 - es-define-property@^1.0.0: 170 - version "1.0.0" 171 - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" 172 - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== 173 - dependencies: 174 - get-intrinsic "^1.2.4" 175 - 176 - es-errors@^1.3.0: 177 - version "1.3.0" 178 - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" 179 - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== 180 - 181 - esbuild@~0.21.5: 182 - version "0.21.5" 183 - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" 184 - integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== 185 - optionalDependencies: 186 - "@esbuild/aix-ppc64" "0.21.5" 187 - "@esbuild/android-arm" "0.21.5" 188 - "@esbuild/android-arm64" "0.21.5" 189 - "@esbuild/android-x64" "0.21.5" 190 - "@esbuild/darwin-arm64" "0.21.5" 191 - "@esbuild/darwin-x64" "0.21.5" 192 - "@esbuild/freebsd-arm64" "0.21.5" 193 - "@esbuild/freebsd-x64" "0.21.5" 194 - "@esbuild/linux-arm" "0.21.5" 195 - "@esbuild/linux-arm64" "0.21.5" 196 - "@esbuild/linux-ia32" "0.21.5" 197 - "@esbuild/linux-loong64" "0.21.5" 198 - "@esbuild/linux-mips64el" "0.21.5" 199 - "@esbuild/linux-ppc64" "0.21.5" 200 - "@esbuild/linux-riscv64" "0.21.5" 201 - "@esbuild/linux-s390x" "0.21.5" 202 - "@esbuild/linux-x64" "0.21.5" 203 - "@esbuild/netbsd-x64" "0.21.5" 204 - "@esbuild/openbsd-x64" "0.21.5" 205 - "@esbuild/sunos-x64" "0.21.5" 206 - "@esbuild/win32-arm64" "0.21.5" 207 - "@esbuild/win32-ia32" "0.21.5" 208 - "@esbuild/win32-x64" "0.21.5" 209 - 210 - fsevents@~2.3.3: 211 - version "2.3.3" 212 - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" 213 - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== 214 - 215 - function-bind@^1.1.2: 216 - version "1.1.2" 217 - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" 218 - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== 219 - 220 - get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: 221 - version "1.2.4" 222 - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" 223 - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== 224 - dependencies: 225 - es-errors "^1.3.0" 226 - function-bind "^1.1.2" 227 - has-proto "^1.0.1" 228 - has-symbols "^1.0.3" 229 - hasown "^2.0.0" 230 - 231 - get-tsconfig@^4.7.5: 232 - version "4.7.6" 233 - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.6.tgz#118fd5b7b9bae234cc7705a00cd771d7eb65d62a" 234 - integrity sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA== 235 - dependencies: 236 - resolve-pkg-maps "^1.0.0" 237 - 238 - gopd@^1.0.1: 239 - version "1.0.1" 240 - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" 241 - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== 242 - dependencies: 243 - get-intrinsic "^1.1.3" 244 - 245 - has-property-descriptors@^1.0.2: 246 - version "1.0.2" 247 - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" 248 - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== 249 - dependencies: 250 - es-define-property "^1.0.0" 251 - 252 - has-proto@^1.0.1: 253 - version "1.0.3" 254 - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" 255 - integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== 256 - 257 - has-symbols@^1.0.3: 258 - version "1.0.3" 259 - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" 260 - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== 261 - 262 - hasown@^2.0.0: 263 - version "2.0.2" 264 - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" 265 - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== 266 - dependencies: 267 - function-bind "^1.1.2" 268 - 269 - headers-polyfill@^3.1.2: 270 - version "3.3.0" 271 - resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-3.3.0.tgz#67c6ef7b72d4c8cac832ad5936f5b3a56e7b705a" 272 - integrity sha512-5e57etwBpNcDc0b6KCVWEh/Ro063OxPvzVimUdM0/tsYM/T7Hfy3kknIGj78SFTOhNd8AZY41U8mOHoO4LzmIQ== 273 - 274 - isarray@^2.0.5: 275 - version "2.0.5" 276 - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" 277 - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== 278 - 279 - json-stable-stringify@^1.0.2: 280 - version "1.1.1" 281 - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz#52d4361b47d49168bcc4e564189a42e5a7439454" 282 - integrity sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg== 283 - dependencies: 284 - call-bind "^1.0.5" 285 - isarray "^2.0.5" 286 - jsonify "^0.0.1" 287 - object-keys "^1.1.1" 288 - 289 - jsonify@^0.0.1: 290 - version "0.0.1" 291 - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" 292 - integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== 293 - 294 - node-fetch@^2.6.12: 295 - version "2.7.0" 296 - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" 297 - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== 298 - dependencies: 299 - whatwg-url "^5.0.0" 300 - 301 - object-keys@^1.1.1: 302 - version "1.1.1" 303 - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" 304 - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== 305 - 306 - otpauth@^9.2.2: 307 - version "9.3.1" 308 - resolved "https://registry.yarnpkg.com/otpauth/-/otpauth-9.3.1.tgz#4756aff0f0b6e04966fa2b14d865e8f6f4cf4279" 309 - integrity sha512-E6d2tMxPofHNk4sRFp+kqW7vQ+WJGO9VLI2N/W00DnI+ThskU12Qa10kyNSGklrzhN5c+wRUsN4GijVgCU2N9w== 310 - dependencies: 311 - "@noble/hashes" "1.4.0" 312 - 313 - psl@^1.1.33: 314 - version "1.9.0" 315 - resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" 316 - integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== 317 - 318 - punycode@^2.1.1: 319 - version "2.3.1" 320 - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" 321 - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== 322 - 323 - querystringify@^2.1.1: 324 - version "2.2.0" 325 - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" 326 - integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== 327 - 328 - requires-port@^1.0.0: 329 - version "1.0.0" 330 - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" 331 - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== 332 - 333 - resolve-pkg-maps@^1.0.0: 334 - version "1.0.0" 335 - resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" 336 - integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== 337 - 338 - set-cookie-parser@^2.6.0: 339 - version "2.6.0" 340 - resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz#131921e50f62ff1a66a461d7d62d7b21d5d15a51" 341 - integrity sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ== 342 - 343 - set-function-length@^1.2.1: 344 - version "1.2.2" 345 - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" 346 - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== 347 - dependencies: 348 - define-data-property "^1.1.4" 349 - es-errors "^1.3.0" 350 - function-bind "^1.1.2" 351 - get-intrinsic "^1.2.4" 352 - gopd "^1.0.1" 353 - has-property-descriptors "^1.0.2" 354 - 355 - tough-cookie@^4.1.2: 356 - version "4.1.4" 357 - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" 358 - integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== 359 - dependencies: 360 - psl "^1.1.33" 361 - punycode "^2.1.1" 362 - universalify "^0.2.0" 363 - url-parse "^1.5.3" 364 - 365 - tr46@~0.0.3: 366 - version "0.0.3" 367 - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" 368 - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== 369 - 370 - tslib@^2.5.2: 371 - version "2.6.3" 372 - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" 373 - integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== 374 - 375 - tsx@^4.15.5: 376 - version "4.16.2" 377 - resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.16.2.tgz#8722be119ae226ef0b4c6210d5ee90f3ba823f19" 378 - integrity sha512-C1uWweJDgdtX2x600HjaFaucXTilT7tgUZHbOE4+ypskZ1OP8CRCSDkCxG6Vya9EwaFIVagWwpaVAn5wzypaqQ== 379 - dependencies: 380 - esbuild "~0.21.5" 381 - get-tsconfig "^4.7.5" 382 - optionalDependencies: 383 - fsevents "~2.3.3" 384 - 385 - universalify@^0.2.0: 386 - version "0.2.0" 387 - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" 388 - integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== 389 - 390 - url-parse@^1.5.3: 391 - version "1.5.10" 392 - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" 393 - integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== 394 - dependencies: 395 - querystringify "^2.1.1" 396 - requires-port "^1.0.0" 397 - 398 - webidl-conversions@^3.0.0: 399 - version "3.0.1" 400 - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" 401 - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== 402 - 403 - whatwg-url@^5.0.0: 404 - version "5.0.0" 405 - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" 406 - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== 407 - dependencies: 408 - tr46 "~0.0.3" 409 - webidl-conversions "^3.0.0"
-13
twitter-scraper/examples/node-integration/package.json
··· 1 - { 2 - "private": true, 3 - "packageManager": "yarn@1.22.19", 4 - "scripts": { 5 - "start:esm": "node src/index.mjs", 6 - "start:cjs": "node src/index.cjs" 7 - }, 8 - "dependencies": { 9 - "@the-convocation/twitter-scraper": "file:../../", 10 - "dotenv": "^17.2.3" 11 - }, 12 - "devDependencies": {} 13 - }
-42
twitter-scraper/examples/node-integration/src/index.cjs
··· 1 - /* eslint-disable @typescript-eslint/no-var-requires */ 2 - const assert = require('node:assert'); 3 - const dotenv = require('dotenv'); 4 - const { Scraper } = require('@the-convocation/twitter-scraper'); 5 - 6 - dotenv.config({ path: '../../.env.local' }); 7 - 8 - // Debug logging to show that the Node.js build is being loaded 9 - console.log( 10 - `Loaded @the-convocation/twitter-scraper from ${require.resolve( 11 - '@the-convocation/twitter-scraper', 12 - )}`, 13 - ); 14 - 15 - /* 16 - * Simplest scraper initialization. Refer to the README or `src/test-utils.ts` for more 17 - * comprehensive examples. 18 - */ 19 - 20 - // Load credentials from the environment 21 - const username = process.env['TWITTER_USERNAME']; 22 - const password = process.env['TWITTER_PASSWORD']; 23 - const email = process.env['TWITTER_EMAIL']; 24 - 25 - assert(username && password && email); 26 - 27 - const scraper = new Scraper({ 28 - experimental: { 29 - xClientTransactionId: true, 30 - xpff: true, 31 - }, 32 - }); 33 - 34 - const main = async () => { 35 - await scraper.login(username, password, email); 36 - 37 - const tweet = await scraper.getTweet('1585338303800578049'); 38 - 39 - console.log(tweet); 40 - }; 41 - 42 - main();
-36
twitter-scraper/examples/node-integration/src/index.mjs
··· 1 - import assert from 'node:assert'; 2 - import dotenv from 'dotenv'; 3 - import { Scraper } from '@the-convocation/twitter-scraper'; 4 - 5 - dotenv.config({ path: '../../.env.local' }); 6 - 7 - // Debug logging to show that the Node.js build is being loaded 8 - console.log( 9 - `Loaded @the-convocation/twitter-scraper from ${import.meta.resolve( 10 - '@the-convocation/twitter-scraper', 11 - )}`, 12 - ); 13 - 14 - /* 15 - * Simplest scraper initialization. Refer to the README or `src/test-utils.ts` for more 16 - * comprehensive examples. 17 - */ 18 - 19 - // Load credentials from the environment 20 - const username = process.env['TWITTER_USERNAME']; 21 - const password = process.env['TWITTER_PASSWORD']; 22 - const email = process.env['TWITTER_EMAIL']; 23 - 24 - assert(username && password && email); 25 - 26 - const scraper = new Scraper({ 27 - experimental: { 28 - xClientTransactionId: true, 29 - xpff: true, 30 - }, 31 - }); 32 - await scraper.login(username, password, email); 33 - 34 - const tweet = await scraper.getTweet('1585338303800578049'); 35 - 36 - console.log(tweet);
-369
twitter-scraper/examples/node-integration/yarn.lock
··· 1 - # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 - # yarn lockfile v1 3 - 4 - 5 - "@noble/hashes@1.4.0": 6 - version "1.4.0" 7 - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" 8 - integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== 9 - 10 - "@sinclair/typebox@^0.32.20": 11 - version "0.32.32" 12 - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.32.32.tgz#e12172fe394e7adc868c62354f4f677e3196630e" 13 - integrity sha512-m+A3zFSI87TCtoz6vQCSnd+t/kDKL78JmzhKYkON+7SnHSa+794qraIVpm6ozFGK+5svnVOt1LJ7BUEhGkIvgg== 14 - 15 - "@the-convocation/twitter-scraper@file:../..": 16 - version "0.20.0" 17 - dependencies: 18 - "@sinclair/typebox" "^0.32.20" 19 - cross-fetch "^4.0.0-alpha.5" 20 - debug "^4.4.1" 21 - headers-polyfill "^3.1.2" 22 - json-stable-stringify "^1.0.2" 23 - linkedom "^0.18.12" 24 - otpauth "^9.2.2" 25 - set-cookie-parser "^2.6.0" 26 - tough-cookie "^4.1.2" 27 - tslib "^2.5.2" 28 - x-client-transaction-id "^0.1.9" 29 - 30 - boolbase@^1.0.0: 31 - version "1.0.0" 32 - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" 33 - integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== 34 - 35 - call-bind@^1.0.5: 36 - version "1.0.7" 37 - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" 38 - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== 39 - dependencies: 40 - es-define-property "^1.0.0" 41 - es-errors "^1.3.0" 42 - function-bind "^1.1.2" 43 - get-intrinsic "^1.2.4" 44 - set-function-length "^1.2.1" 45 - 46 - cross-fetch@^4.0.0-alpha.5: 47 - version "4.0.0" 48 - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.0.0.tgz#f037aef1580bb3a1a35164ea2a848ba81b445983" 49 - integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g== 50 - dependencies: 51 - node-fetch "^2.6.12" 52 - 53 - css-select@^5.1.0: 54 - version "5.2.2" 55 - resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.2.2.tgz#01b6e8d163637bb2dd6c982ca4ed65863682786e" 56 - integrity sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw== 57 - dependencies: 58 - boolbase "^1.0.0" 59 - css-what "^6.1.0" 60 - domhandler "^5.0.2" 61 - domutils "^3.0.1" 62 - nth-check "^2.0.1" 63 - 64 - css-what@^6.1.0: 65 - version "6.2.2" 66 - resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.2.2.tgz#cdcc8f9b6977719fdfbd1de7aec24abf756b9dea" 67 - integrity sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA== 68 - 69 - cssom@^0.5.0: 70 - version "0.5.0" 71 - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36" 72 - integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw== 73 - 74 - debug@^4.4.1: 75 - version "4.4.3" 76 - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" 77 - integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== 78 - dependencies: 79 - ms "^2.1.3" 80 - 81 - define-data-property@^1.1.4: 82 - version "1.1.4" 83 - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" 84 - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== 85 - dependencies: 86 - es-define-property "^1.0.0" 87 - es-errors "^1.3.0" 88 - gopd "^1.0.1" 89 - 90 - dom-serializer@^2.0.0: 91 - version "2.0.0" 92 - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" 93 - integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== 94 - dependencies: 95 - domelementtype "^2.3.0" 96 - domhandler "^5.0.2" 97 - entities "^4.2.0" 98 - 99 - domelementtype@^2.3.0: 100 - version "2.3.0" 101 - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" 102 - integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== 103 - 104 - domhandler@^5.0.2, domhandler@^5.0.3: 105 - version "5.0.3" 106 - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" 107 - integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== 108 - dependencies: 109 - domelementtype "^2.3.0" 110 - 111 - domutils@^3.0.1, domutils@^3.2.1: 112 - version "3.2.2" 113 - resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.2.2.tgz#edbfe2b668b0c1d97c24baf0f1062b132221bc78" 114 - integrity sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw== 115 - dependencies: 116 - dom-serializer "^2.0.0" 117 - domelementtype "^2.3.0" 118 - domhandler "^5.0.3" 119 - 120 - dotenv@^17.2.3: 121 - version "17.2.3" 122 - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-17.2.3.tgz#ad995d6997f639b11065f419a22fabf567cdb9a2" 123 - integrity sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w== 124 - 125 - entities@^4.2.0: 126 - version "4.5.0" 127 - resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" 128 - integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== 129 - 130 - entities@^6.0.0: 131 - version "6.0.1" 132 - resolved "https://registry.yarnpkg.com/entities/-/entities-6.0.1.tgz#c28c34a43379ca7f61d074130b2f5f7020a30694" 133 - integrity sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g== 134 - 135 - es-define-property@^1.0.0: 136 - version "1.0.0" 137 - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" 138 - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== 139 - dependencies: 140 - get-intrinsic "^1.2.4" 141 - 142 - es-errors@^1.3.0: 143 - version "1.3.0" 144 - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" 145 - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== 146 - 147 - function-bind@^1.1.2: 148 - version "1.1.2" 149 - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" 150 - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== 151 - 152 - get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: 153 - version "1.2.4" 154 - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" 155 - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== 156 - dependencies: 157 - es-errors "^1.3.0" 158 - function-bind "^1.1.2" 159 - has-proto "^1.0.1" 160 - has-symbols "^1.0.3" 161 - hasown "^2.0.0" 162 - 163 - gopd@^1.0.1: 164 - version "1.0.1" 165 - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" 166 - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== 167 - dependencies: 168 - get-intrinsic "^1.1.3" 169 - 170 - has-property-descriptors@^1.0.2: 171 - version "1.0.2" 172 - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" 173 - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== 174 - dependencies: 175 - es-define-property "^1.0.0" 176 - 177 - has-proto@^1.0.1: 178 - version "1.0.3" 179 - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" 180 - integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== 181 - 182 - has-symbols@^1.0.3: 183 - version "1.0.3" 184 - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" 185 - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== 186 - 187 - hasown@^2.0.0: 188 - version "2.0.2" 189 - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" 190 - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== 191 - dependencies: 192 - function-bind "^1.1.2" 193 - 194 - headers-polyfill@^3.1.2: 195 - version "3.3.0" 196 - resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-3.3.0.tgz#67c6ef7b72d4c8cac832ad5936f5b3a56e7b705a" 197 - integrity sha512-5e57etwBpNcDc0b6KCVWEh/Ro063OxPvzVimUdM0/tsYM/T7Hfy3kknIGj78SFTOhNd8AZY41U8mOHoO4LzmIQ== 198 - 199 - html-escaper@^3.0.3: 200 - version "3.0.3" 201 - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-3.0.3.tgz#4d336674652beb1dcbc29ef6b6ba7f6be6fdfed6" 202 - integrity sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ== 203 - 204 - htmlparser2@^10.0.0: 205 - version "10.0.0" 206 - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-10.0.0.tgz#77ad249037b66bf8cc99c6e286ef73b83aeb621d" 207 - integrity sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g== 208 - dependencies: 209 - domelementtype "^2.3.0" 210 - domhandler "^5.0.3" 211 - domutils "^3.2.1" 212 - entities "^6.0.0" 213 - 214 - isarray@^2.0.5: 215 - version "2.0.5" 216 - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" 217 - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== 218 - 219 - json-stable-stringify@^1.0.2: 220 - version "1.1.1" 221 - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz#52d4361b47d49168bcc4e564189a42e5a7439454" 222 - integrity sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg== 223 - dependencies: 224 - call-bind "^1.0.5" 225 - isarray "^2.0.5" 226 - jsonify "^0.0.1" 227 - object-keys "^1.1.1" 228 - 229 - jsonify@^0.0.1: 230 - version "0.0.1" 231 - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" 232 - integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== 233 - 234 - linkedom@^0.18.12, linkedom@^0.18.9: 235 - version "0.18.12" 236 - resolved "https://registry.yarnpkg.com/linkedom/-/linkedom-0.18.12.tgz#a8b1a1942b567dcb1888093df311055da1349a14" 237 - integrity sha512-jalJsOwIKuQJSeTvsgzPe9iJzyfVaEJiEXl+25EkKevsULHvMJzpNqwvj1jOESWdmgKDiXObyjOYwlUqG7wo1Q== 238 - dependencies: 239 - css-select "^5.1.0" 240 - cssom "^0.5.0" 241 - html-escaper "^3.0.3" 242 - htmlparser2 "^10.0.0" 243 - uhyphen "^0.2.0" 244 - 245 - ms@^2.1.3: 246 - version "2.1.3" 247 - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 248 - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 249 - 250 - node-fetch@^2.6.12: 251 - version "2.7.0" 252 - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" 253 - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== 254 - dependencies: 255 - whatwg-url "^5.0.0" 256 - 257 - nth-check@^2.0.1: 258 - version "2.1.1" 259 - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" 260 - integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== 261 - dependencies: 262 - boolbase "^1.0.0" 263 - 264 - object-keys@^1.1.1: 265 - version "1.1.1" 266 - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" 267 - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== 268 - 269 - otpauth@^9.2.2: 270 - version "9.3.1" 271 - resolved "https://registry.yarnpkg.com/otpauth/-/otpauth-9.3.1.tgz#4756aff0f0b6e04966fa2b14d865e8f6f4cf4279" 272 - integrity sha512-E6d2tMxPofHNk4sRFp+kqW7vQ+WJGO9VLI2N/W00DnI+ThskU12Qa10kyNSGklrzhN5c+wRUsN4GijVgCU2N9w== 273 - dependencies: 274 - "@noble/hashes" "1.4.0" 275 - 276 - psl@^1.1.33: 277 - version "1.9.0" 278 - resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" 279 - integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== 280 - 281 - punycode@^2.1.1: 282 - version "2.3.1" 283 - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" 284 - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== 285 - 286 - querystringify@^2.1.1: 287 - version "2.2.0" 288 - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" 289 - integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== 290 - 291 - requires-port@^1.0.0: 292 - version "1.0.0" 293 - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" 294 - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== 295 - 296 - set-cookie-parser@^2.6.0: 297 - version "2.6.0" 298 - resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz#131921e50f62ff1a66a461d7d62d7b21d5d15a51" 299 - integrity sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ== 300 - 301 - set-function-length@^1.2.1: 302 - version "1.2.2" 303 - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" 304 - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== 305 - dependencies: 306 - define-data-property "^1.1.4" 307 - es-errors "^1.3.0" 308 - function-bind "^1.1.2" 309 - get-intrinsic "^1.2.4" 310 - gopd "^1.0.1" 311 - has-property-descriptors "^1.0.2" 312 - 313 - tough-cookie@^4.1.2: 314 - version "4.1.4" 315 - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" 316 - integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== 317 - dependencies: 318 - psl "^1.1.33" 319 - punycode "^2.1.1" 320 - universalify "^0.2.0" 321 - url-parse "^1.5.3" 322 - 323 - tr46@~0.0.3: 324 - version "0.0.3" 325 - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" 326 - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== 327 - 328 - tslib@^2.5.2: 329 - version "2.6.3" 330 - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" 331 - integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== 332 - 333 - uhyphen@^0.2.0: 334 - version "0.2.0" 335 - resolved "https://registry.yarnpkg.com/uhyphen/-/uhyphen-0.2.0.tgz#8fdf0623314486e020a3c00ee5cc7a12fe722b81" 336 - integrity sha512-qz3o9CHXmJJPGBdqzab7qAYuW8kQGKNEuoHFYrBwV6hWIMcpAmxDLXojcHfFr9US1Pe6zUswEIJIbLI610fuqA== 337 - 338 - universalify@^0.2.0: 339 - version "0.2.0" 340 - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" 341 - integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== 342 - 343 - url-parse@^1.5.3: 344 - version "1.5.10" 345 - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" 346 - integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== 347 - dependencies: 348 - querystringify "^2.1.1" 349 - requires-port "^1.0.0" 350 - 351 - webidl-conversions@^3.0.0: 352 - version "3.0.1" 353 - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" 354 - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== 355 - 356 - whatwg-url@^5.0.0: 357 - version "5.0.0" 358 - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" 359 - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== 360 - dependencies: 361 - tr46 "~0.0.3" 362 - webidl-conversions "^3.0.0" 363 - 364 - x-client-transaction-id@^0.1.9: 365 - version "0.1.9" 366 - resolved "https://registry.yarnpkg.com/x-client-transaction-id/-/x-client-transaction-id-0.1.9.tgz#3bb0359268a481f66edf39c0aaa195d73195e849" 367 - integrity sha512-CES4zgkJ0wbfFWm0qgdKphthyb+L7lVHymgOY15v6ivcWSx5p9lp5kzAed+BuqJSP7bS0GbQyJ16ONkRthgsUw== 368 - dependencies: 369 - linkedom "^0.18.9"
-4
twitter-scraper/examples/react-integration/.env.example
··· 1 - # Copy this file to .env.local and update these values if needed. 2 - VITE_TWITTER_USERNAME=$TWITTER_USERNAME 3 - VITE_TWITTER_PASSWORD=$TWITTER_PASSWORD 4 - VITE_TWITTER_EMAIL=$TWITTER_EMAIL
-18
twitter-scraper/examples/react-integration/.eslintrc.cjs
··· 1 - module.exports = { 2 - root: true, 3 - env: { browser: true, es2020: true }, 4 - extends: [ 5 - 'eslint:recommended', 6 - 'plugin:@typescript-eslint/recommended', 7 - 'plugin:react-hooks/recommended', 8 - ], 9 - ignorePatterns: ['dist', '.eslintrc.cjs'], 10 - parser: '@typescript-eslint/parser', 11 - plugins: ['react-refresh'], 12 - rules: { 13 - 'react-refresh/only-export-components': [ 14 - 'warn', 15 - { allowConstantExport: true }, 16 - ], 17 - }, 18 - }
-24
twitter-scraper/examples/react-integration/.gitignore
··· 1 - # Logs 2 - logs 3 - *.log 4 - npm-debug.log* 5 - yarn-debug.log* 6 - yarn-error.log* 7 - pnpm-debug.log* 8 - lerna-debug.log* 9 - 10 - node_modules 11 - dist 12 - dist-ssr 13 - *.local 14 - 15 - # Editor directories and files 16 - .vscode/* 17 - !.vscode/extensions.json 18 - .idea 19 - .DS_Store 20 - *.suo 21 - *.ntvs* 22 - *.njsproj 23 - *.sln 24 - *.sw?
-21
twitter-scraper/examples/react-integration/README.md
··· 1 - # React Example 2 - 3 - Browser usage example in React. Due to Twitter's CORS headers not allowing external websites from calling their APIs, 4 - this requires using a CORS proxy of some kind. 5 - 6 - ## Running 7 - 8 - First, copy `.env.example` to a new `.env.local` file, and update the environment variables to point to your 9 - own account credentials if needed. 10 - 11 - In the `cors-proxy` example folder, run the following command: 12 - 13 - ```bash 14 - yarn start 15 - ``` 16 - 17 - Then, in this folder, run the following command to start the Vite development server: 18 - 19 - ```bash 20 - yarn dev 21 - ```
-13
twitter-scraper/examples/react-integration/index.html
··· 1 - <!doctype html> 2 - <html lang="en"> 3 - <head> 4 - <meta charset="UTF-8" /> 5 - <link rel="icon" type="image/svg+xml" href="/vite.svg" /> 6 - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 7 - <title>Vite + React + TS</title> 8 - </head> 9 - <body> 10 - <div id="root"></div> 11 - <script type="module" src="/src/main.tsx"></script> 12 - </body> 13 - </html>
-29
twitter-scraper/examples/react-integration/package.json
··· 1 - { 2 - "name": "react-integration", 3 - "private": true, 4 - "version": "0.0.0", 5 - "type": "module", 6 - "scripts": { 7 - "dev": "vite", 8 - "build": "tsc && vite build", 9 - "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", 10 - "preview": "vite preview" 11 - }, 12 - "dependencies": { 13 - "@the-convocation/twitter-scraper": "^0.16.6", 14 - "react": "^18.2.0", 15 - "react-dom": "^18.2.0" 16 - }, 17 - "devDependencies": { 18 - "@types/react": "^18.2.66", 19 - "@types/react-dom": "^18.2.22", 20 - "@typescript-eslint/eslint-plugin": "^7.2.0", 21 - "@typescript-eslint/parser": "^7.2.0", 22 - "@vitejs/plugin-react-swc": "^3.5.0", 23 - "eslint": "^8.57.0", 24 - "eslint-plugin-react-hooks": "^4.6.0", 25 - "eslint-plugin-react-refresh": "^0.4.6", 26 - "typescript": "^5.2.2", 27 - "vite": "^5.2.0" 28 - } 29 - }
-1
twitter-scraper/examples/react-integration/public/vite.svg
··· 1 - <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
-42
twitter-scraper/examples/react-integration/src/App.css
··· 1 - #root { 2 - max-width: 1280px; 3 - margin: 0 auto; 4 - padding: 2rem; 5 - text-align: center; 6 - } 7 - 8 - .logo { 9 - height: 6em; 10 - padding: 1.5em; 11 - will-change: filter; 12 - transition: filter 300ms; 13 - } 14 - .logo:hover { 15 - filter: drop-shadow(0 0 2em #646cffaa); 16 - } 17 - .logo.react:hover { 18 - filter: drop-shadow(0 0 2em #61dafbaa); 19 - } 20 - 21 - @keyframes logo-spin { 22 - from { 23 - transform: rotate(0deg); 24 - } 25 - to { 26 - transform: rotate(360deg); 27 - } 28 - } 29 - 30 - @media (prefers-reduced-motion: no-preference) { 31 - a:nth-of-type(2) .logo { 32 - animation: logo-spin infinite 20s linear; 33 - } 34 - } 35 - 36 - .card { 37 - padding: 2em; 38 - } 39 - 40 - .read-the-docs { 41 - color: #888; 42 - }
-85
twitter-scraper/examples/react-integration/src/App.tsx
··· 1 - import { useEffect, useRef, useState } from 'react'; 2 - import { Scraper, Tweet } from '@the-convocation/twitter-scraper'; 3 - import './App.css'; 4 - 5 - function getProxyHost(host: string): string { 6 - if (host.startsWith('api')) { 7 - return 'localhost:5174'; 8 - } else { 9 - return 'localhost:5175'; 10 - } 11 - } 12 - 13 - function FetchTweet() { 14 - const [tweet, setTweet] = useState<Tweet | null>(null); 15 - 16 - const scraper = useRef( 17 - new Scraper({ 18 - transform: { 19 - request(input: RequestInfo | URL, init?: RequestInit) { 20 - console.log(input, init); 21 - if (input instanceof URL) { 22 - input.protocol = 'http'; 23 - input.host = getProxyHost(input.host); 24 - return [input, init]; 25 - } else if (typeof input === 'string') { 26 - const proxy = new URL(input); 27 - proxy.protocol = 'http'; 28 - proxy.host = getProxyHost(proxy.host); 29 - return [proxy, init]; 30 - } else { 31 - throw new Error('Unexpected request input type'); 32 - } 33 - }, 34 - }, 35 - }), 36 - ); 37 - const loggedIn = useRef(false); 38 - const loggingIn = useRef(false); 39 - 40 - useEffect(() => { 41 - async function getTweet() { 42 - if (loggedIn.current || loggingIn.current) { 43 - return; 44 - } 45 - 46 - loggingIn.current = true; 47 - 48 - try { 49 - if (!loggedIn.current) { 50 - await scraper.current.login( 51 - import.meta.env.VITE_TWITTER_USERNAME, 52 - import.meta.env.VITE_TWITTER_PASSWORD, 53 - import.meta.env.VITE_TWITTER_EMAIL, 54 - ); 55 - loggedIn.current = true; 56 - } 57 - 58 - const latestTweet = await scraper.current.getTweet( 59 - '1585338303800578049', 60 - ); 61 - if (latestTweet) { 62 - setTweet(latestTweet); 63 - } 64 - } finally { 65 - loggingIn.current = false; 66 - } 67 - } 68 - 69 - getTweet(); 70 - }, []); 71 - 72 - return <p>{tweet?.text}</p>; 73 - } 74 - 75 - function App() { 76 - return ( 77 - <> 78 - <div className="card"> 79 - <FetchTweet /> 80 - </div> 81 - </> 82 - ); 83 - } 84 - 85 - export default App;
-68
twitter-scraper/examples/react-integration/src/index.css
··· 1 - :root { 2 - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; 3 - line-height: 1.5; 4 - font-weight: 400; 5 - 6 - color-scheme: light dark; 7 - color: rgba(255, 255, 255, 0.87); 8 - background-color: #242424; 9 - 10 - font-synthesis: none; 11 - text-rendering: optimizeLegibility; 12 - -webkit-font-smoothing: antialiased; 13 - -moz-osx-font-smoothing: grayscale; 14 - } 15 - 16 - a { 17 - font-weight: 500; 18 - color: #646cff; 19 - text-decoration: inherit; 20 - } 21 - a:hover { 22 - color: #535bf2; 23 - } 24 - 25 - body { 26 - margin: 0; 27 - display: flex; 28 - place-items: center; 29 - min-width: 320px; 30 - min-height: 100vh; 31 - } 32 - 33 - h1 { 34 - font-size: 3.2em; 35 - line-height: 1.1; 36 - } 37 - 38 - button { 39 - border-radius: 8px; 40 - border: 1px solid transparent; 41 - padding: 0.6em 1.2em; 42 - font-size: 1em; 43 - font-weight: 500; 44 - font-family: inherit; 45 - background-color: #1a1a1a; 46 - cursor: pointer; 47 - transition: border-color 0.25s; 48 - } 49 - button:hover { 50 - border-color: #646cff; 51 - } 52 - button:focus, 53 - button:focus-visible { 54 - outline: 4px auto -webkit-focus-ring-color; 55 - } 56 - 57 - @media (prefers-color-scheme: light) { 58 - :root { 59 - color: #213547; 60 - background-color: #ffffff; 61 - } 62 - a:hover { 63 - color: #747bff; 64 - } 65 - button { 66 - background-color: #f9f9f9; 67 - } 68 - }
-10
twitter-scraper/examples/react-integration/src/main.tsx
··· 1 - import React from 'react'; 2 - import ReactDOM from 'react-dom/client'; 3 - import App from './App.tsx'; 4 - import './index.css'; 5 - 6 - ReactDOM.createRoot(document.getElementById('root')!).render( 7 - <React.StrictMode> 8 - <App /> 9 - </React.StrictMode>, 10 - );
-11
twitter-scraper/examples/react-integration/src/vite-env.d.ts
··· 1 - /// <reference types="vite/client" /> 2 - 3 - interface ImportMetaEnv { 4 - readonly VITE_TWITTER_USERNAME: string; 5 - readonly VITE_TWITTER_PASSWORD: string; 6 - readonly VITE_TWITTER_EMAIL: string; 7 - } 8 - 9 - interface ImportMeta { 10 - readonly env: ImportMetaEnv; 11 - }
-25
twitter-scraper/examples/react-integration/tsconfig.json
··· 1 - { 2 - "compilerOptions": { 3 - "target": "ES2020", 4 - "useDefineForClassFields": true, 5 - "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 - "module": "ESNext", 7 - "skipLibCheck": true, 8 - 9 - /* Bundler mode */ 10 - "moduleResolution": "bundler", 11 - "allowImportingTsExtensions": true, 12 - "resolveJsonModule": true, 13 - "isolatedModules": true, 14 - "noEmit": true, 15 - "jsx": "react-jsx", 16 - 17 - /* Linting */ 18 - "strict": true, 19 - "noUnusedLocals": true, 20 - "noUnusedParameters": true, 21 - "noFallthroughCasesInSwitch": true 22 - }, 23 - "include": ["src"], 24 - "references": [{ "path": "./tsconfig.node.json" }] 25 - }
-11
twitter-scraper/examples/react-integration/tsconfig.node.json
··· 1 - { 2 - "compilerOptions": { 3 - "composite": true, 4 - "skipLibCheck": true, 5 - "module": "ESNext", 6 - "moduleResolution": "bundler", 7 - "allowSyntheticDefaultImports": true, 8 - "strict": true 9 - }, 10 - "include": ["vite.config.ts"] 11 - }
-7
twitter-scraper/examples/react-integration/vite.config.ts
··· 1 - import { defineConfig } from 'vite'; 2 - import react from '@vitejs/plugin-react-swc'; 3 - 4 - // https://vitejs.dev/config/ 5 - export default defineConfig({ 6 - plugins: [react()], 7 - });
-1610
twitter-scraper/examples/react-integration/yarn.lock
··· 1 - # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 - # yarn lockfile v1 3 - 4 - 5 - "@esbuild/aix-ppc64@0.21.5": 6 - version "0.21.5" 7 - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" 8 - integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== 9 - 10 - "@esbuild/android-arm64@0.21.5": 11 - version "0.21.5" 12 - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" 13 - integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== 14 - 15 - "@esbuild/android-arm@0.21.5": 16 - version "0.21.5" 17 - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" 18 - integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== 19 - 20 - "@esbuild/android-x64@0.21.5": 21 - version "0.21.5" 22 - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" 23 - integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== 24 - 25 - "@esbuild/darwin-arm64@0.21.5": 26 - version "0.21.5" 27 - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" 28 - integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== 29 - 30 - "@esbuild/darwin-x64@0.21.5": 31 - version "0.21.5" 32 - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" 33 - integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== 34 - 35 - "@esbuild/freebsd-arm64@0.21.5": 36 - version "0.21.5" 37 - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" 38 - integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== 39 - 40 - "@esbuild/freebsd-x64@0.21.5": 41 - version "0.21.5" 42 - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" 43 - integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== 44 - 45 - "@esbuild/linux-arm64@0.21.5": 46 - version "0.21.5" 47 - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" 48 - integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== 49 - 50 - "@esbuild/linux-arm@0.21.5": 51 - version "0.21.5" 52 - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" 53 - integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== 54 - 55 - "@esbuild/linux-ia32@0.21.5": 56 - version "0.21.5" 57 - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" 58 - integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== 59 - 60 - "@esbuild/linux-loong64@0.21.5": 61 - version "0.21.5" 62 - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" 63 - integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== 64 - 65 - "@esbuild/linux-mips64el@0.21.5": 66 - version "0.21.5" 67 - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" 68 - integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== 69 - 70 - "@esbuild/linux-ppc64@0.21.5": 71 - version "0.21.5" 72 - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" 73 - integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== 74 - 75 - "@esbuild/linux-riscv64@0.21.5": 76 - version "0.21.5" 77 - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" 78 - integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== 79 - 80 - "@esbuild/linux-s390x@0.21.5": 81 - version "0.21.5" 82 - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" 83 - integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== 84 - 85 - "@esbuild/linux-x64@0.21.5": 86 - version "0.21.5" 87 - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" 88 - integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== 89 - 90 - "@esbuild/netbsd-x64@0.21.5": 91 - version "0.21.5" 92 - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" 93 - integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== 94 - 95 - "@esbuild/openbsd-x64@0.21.5": 96 - version "0.21.5" 97 - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" 98 - integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== 99 - 100 - "@esbuild/sunos-x64@0.21.5": 101 - version "0.21.5" 102 - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" 103 - integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== 104 - 105 - "@esbuild/win32-arm64@0.21.5": 106 - version "0.21.5" 107 - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" 108 - integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== 109 - 110 - "@esbuild/win32-ia32@0.21.5": 111 - version "0.21.5" 112 - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" 113 - integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== 114 - 115 - "@esbuild/win32-x64@0.21.5": 116 - version "0.21.5" 117 - resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz" 118 - integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== 119 - 120 - "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": 121 - version "4.4.0" 122 - resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz" 123 - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== 124 - dependencies: 125 - eslint-visitor-keys "^3.3.0" 126 - 127 - "@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1": 128 - version "4.10.1" 129 - resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz" 130 - integrity sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA== 131 - 132 - "@eslint/eslintrc@^2.1.4": 133 - version "2.1.4" 134 - resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz" 135 - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== 136 - dependencies: 137 - ajv "^6.12.4" 138 - debug "^4.3.2" 139 - espree "^9.6.0" 140 - globals "^13.19.0" 141 - ignore "^5.2.0" 142 - import-fresh "^3.2.1" 143 - js-yaml "^4.1.0" 144 - minimatch "^3.1.2" 145 - strip-json-comments "^3.1.1" 146 - 147 - "@eslint/js@8.57.0": 148 - version "8.57.0" 149 - resolved "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz" 150 - integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== 151 - 152 - "@humanwhocodes/config-array@^0.11.14": 153 - version "0.11.14" 154 - resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz" 155 - integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== 156 - dependencies: 157 - "@humanwhocodes/object-schema" "^2.0.2" 158 - debug "^4.3.1" 159 - minimatch "^3.0.5" 160 - 161 - "@humanwhocodes/module-importer@^1.0.1": 162 - version "1.0.1" 163 - resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz" 164 - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== 165 - 166 - "@humanwhocodes/object-schema@^2.0.2": 167 - version "2.0.3" 168 - resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz" 169 - integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== 170 - 171 - "@noble/hashes@1.7.1": 172 - version "1.7.1" 173 - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.1.tgz#5738f6d765710921e7a751e00c20ae091ed8db0f" 174 - integrity sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ== 175 - 176 - "@nodelib/fs.scandir@2.1.5": 177 - version "2.1.5" 178 - resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" 179 - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== 180 - dependencies: 181 - "@nodelib/fs.stat" "2.0.5" 182 - run-parallel "^1.1.9" 183 - 184 - "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": 185 - version "2.0.5" 186 - resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" 187 - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== 188 - 189 - "@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": 190 - version "1.2.8" 191 - resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" 192 - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== 193 - dependencies: 194 - "@nodelib/fs.scandir" "2.1.5" 195 - fastq "^1.6.0" 196 - 197 - "@rollup/rollup-android-arm-eabi@4.18.0": 198 - version "4.18.0" 199 - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz#bbd0e616b2078cd2d68afc9824d1fadb2f2ffd27" 200 - integrity sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ== 201 - 202 - "@rollup/rollup-android-arm64@4.18.0": 203 - version "4.18.0" 204 - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz#97255ef6384c5f73f4800c0de91f5f6518e21203" 205 - integrity sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA== 206 - 207 - "@rollup/rollup-darwin-arm64@4.18.0": 208 - version "4.18.0" 209 - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz#b6dd74e117510dfe94541646067b0545b42ff096" 210 - integrity sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w== 211 - 212 - "@rollup/rollup-darwin-x64@4.18.0": 213 - version "4.18.0" 214 - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz#e07d76de1cec987673e7f3d48ccb8e106d42c05c" 215 - integrity sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA== 216 - 217 - "@rollup/rollup-linux-arm-gnueabihf@4.18.0": 218 - version "4.18.0" 219 - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz#9f1a6d218b560c9d75185af4b8bb42f9f24736b8" 220 - integrity sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA== 221 - 222 - "@rollup/rollup-linux-arm-musleabihf@4.18.0": 223 - version "4.18.0" 224 - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz#53618b92e6ffb642c7b620e6e528446511330549" 225 - integrity sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A== 226 - 227 - "@rollup/rollup-linux-arm64-gnu@4.18.0": 228 - version "4.18.0" 229 - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz#99a7ba5e719d4f053761a698f7b52291cefba577" 230 - integrity sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw== 231 - 232 - "@rollup/rollup-linux-arm64-musl@4.18.0": 233 - version "4.18.0" 234 - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz#f53db99a45d9bc00ce94db8a35efa7c3c144a58c" 235 - integrity sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ== 236 - 237 - "@rollup/rollup-linux-powerpc64le-gnu@4.18.0": 238 - version "4.18.0" 239 - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz#cbb0837408fe081ce3435cf3730e090febafc9bf" 240 - integrity sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA== 241 - 242 - "@rollup/rollup-linux-riscv64-gnu@4.18.0": 243 - version "4.18.0" 244 - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz#8ed09c1d1262ada4c38d791a28ae0fea28b80cc9" 245 - integrity sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg== 246 - 247 - "@rollup/rollup-linux-s390x-gnu@4.18.0": 248 - version "4.18.0" 249 - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz#938138d3c8e0c96f022252a28441dcfb17afd7ec" 250 - integrity sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg== 251 - 252 - "@rollup/rollup-linux-x64-gnu@4.18.0": 253 - version "4.18.0" 254 - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz#1a7481137a54740bee1ded4ae5752450f155d942" 255 - integrity sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w== 256 - 257 - "@rollup/rollup-linux-x64-musl@4.18.0": 258 - version "4.18.0" 259 - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz#f1186afc601ac4f4fc25fac4ca15ecbee3a1874d" 260 - integrity sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg== 261 - 262 - "@rollup/rollup-win32-arm64-msvc@4.18.0": 263 - version "4.18.0" 264 - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz#ed6603e93636a96203c6915be4117245c1bd2daf" 265 - integrity sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA== 266 - 267 - "@rollup/rollup-win32-ia32-msvc@4.18.0": 268 - version "4.18.0" 269 - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz#14e0b404b1c25ebe6157a15edb9c46959ba74c54" 270 - integrity sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg== 271 - 272 - "@rollup/rollup-win32-x64-msvc@4.18.0": 273 - version "4.18.0" 274 - resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz" 275 - integrity sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g== 276 - 277 - "@sinclair/typebox@^0.32.20": 278 - version "0.32.35" 279 - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.32.35.tgz#41c04473509478df9895800018a3d3ae7d40fb3c" 280 - integrity sha512-Ul3YyOTU++to8cgNkttakC0dWvpERr6RYoHO2W47DLbFvrwBDJUY31B1sImH6JZSYc4Kt4PyHtoPNu+vL2r2dA== 281 - 282 - "@swc/core-darwin-arm64@1.6.1": 283 - version "1.6.1" 284 - resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.6.1.tgz#72d861fb7094b7a0004f4f300e2c5d4ea1549d9e" 285 - integrity sha512-u6GdwOXsOEdNAdSI6nWq6G2BQw5HiSNIZVcBaH1iSvBnxZvWbnIKyDiZKaYnDwTLHLzig2GuUjjE2NaCJPy4jg== 286 - 287 - "@swc/core-darwin-x64@1.6.1": 288 - version "1.6.1" 289 - resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.6.1.tgz#8b7070fcee4a4570d0af245c4614ca4e492dfd5b" 290 - integrity sha512-/tXwQibkDNLVbAtr7PUQI0iQjoB708fjhDDDfJ6WILSBVZ3+qs/LHjJ7jHwumEYxVq1XA7Fv2Q7SE/ZSQoWHcQ== 291 - 292 - "@swc/core-linux-arm-gnueabihf@1.6.1": 293 - version "1.6.1" 294 - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.6.1.tgz#bea6d2e75127bbc65a664284f012ffa90c8325d5" 295 - integrity sha512-aDgipxhJTms8iH78emHVutFR2c16LNhO+NTRCdYi+X4PyIn58/DyYTH6VDZ0AeEcS5f132ZFldU5AEgExwihXA== 296 - 297 - "@swc/core-linux-arm64-gnu@1.6.1": 298 - version "1.6.1" 299 - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.6.1.tgz#5c84d804ec23cf54b31c0bc0b4bdd30ec5d43ce8" 300 - integrity sha512-XkJ+eO4zUKG5g458RyhmKPyBGxI0FwfWFgpfIj5eDybxYJ6s4HBT5MoxyBLorB5kMlZ0XoY/usUMobPVY3nL0g== 301 - 302 - "@swc/core-linux-arm64-musl@1.6.1": 303 - version "1.6.1" 304 - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.6.1.tgz#e167a350bec12caebc97304068c3ffbad6c398ce" 305 - integrity sha512-dr6YbLBg/SsNxs1hDqJhxdcrS8dGMlOXJwXIrUvACiA8jAd6S5BxYCaqsCefLYXtaOmu0bbx1FB/evfodqB70Q== 306 - 307 - "@swc/core-linux-x64-gnu@1.6.1": 308 - version "1.6.1" 309 - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.6.1.tgz#fdd4e1d63b3e53d195e2ddcb9cb5ad9f31995796" 310 - integrity sha512-A0b/3V+yFy4LXh3O9umIE7LXPC7NBWdjl6AQYqymSMcMu0EOb1/iygA6s6uWhz9y3e172Hpb9b/CGsuD8Px/bg== 311 - 312 - "@swc/core-linux-x64-musl@1.6.1": 313 - version "1.6.1" 314 - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.6.1.tgz#81a312dd9e62da5f4c48e3cd23b6c6d28a31ac42" 315 - integrity sha512-5dJjlzZXhC87nZZZWbpiDP8kBIO0ibis893F/rtPIQBI5poH+iJuA32EU3wN4/WFHeK4et8z6SGSVghPtWyk4g== 316 - 317 - "@swc/core-win32-arm64-msvc@1.6.1": 318 - version "1.6.1" 319 - resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.6.1.tgz#e131f579a69c5d807013e54ccb311e10caa27bcb" 320 - integrity sha512-HBi1ZlwvfcUibLtT3g/lP57FaDPC799AD6InolB2KSgkqyBbZJ9wAXM8/CcH67GLIP0tZ7FqblrJTzGXxetTJQ== 321 - 322 - "@swc/core-win32-ia32-msvc@1.6.1": 323 - version "1.6.1" 324 - resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.6.1.tgz#9f3d88cf0e826aa8222a695177a065ed2899eb21" 325 - integrity sha512-AKqHohlWERclexar5y6ux4sQ8yaMejEXNxeKXm7xPhXrp13/1p4/I3E5bPVX/jMnvpm4HpcKSP0ee2WsqmhhPw== 326 - 327 - "@swc/core-win32-x64-msvc@1.6.1": 328 - version "1.6.1" 329 - resolved "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.6.1.tgz" 330 - integrity sha512-0dLdTLd+ONve8kgC5T6VQ2Y5G+OZ7y0ujjapnK66wpvCBM6BKYGdT/OKhZKZydrC5gUKaxFN6Y5oOt9JOFUrOQ== 331 - 332 - "@swc/core@^1.5.7": 333 - version "1.6.1" 334 - resolved "https://registry.npmjs.org/@swc/core/-/core-1.6.1.tgz" 335 - integrity sha512-Yz5uj5hNZpS5brLtBvKY0L4s2tBAbQ4TjmW8xF1EC3YLFxQRrUjMP49Zm1kp/KYyYvTkSaG48Ffj2YWLu9nChw== 336 - dependencies: 337 - "@swc/counter" "^0.1.3" 338 - "@swc/types" "^0.1.8" 339 - optionalDependencies: 340 - "@swc/core-darwin-arm64" "1.6.1" 341 - "@swc/core-darwin-x64" "1.6.1" 342 - "@swc/core-linux-arm-gnueabihf" "1.6.1" 343 - "@swc/core-linux-arm64-gnu" "1.6.1" 344 - "@swc/core-linux-arm64-musl" "1.6.1" 345 - "@swc/core-linux-x64-gnu" "1.6.1" 346 - "@swc/core-linux-x64-musl" "1.6.1" 347 - "@swc/core-win32-arm64-msvc" "1.6.1" 348 - "@swc/core-win32-ia32-msvc" "1.6.1" 349 - "@swc/core-win32-x64-msvc" "1.6.1" 350 - 351 - "@swc/counter@^0.1.3": 352 - version "0.1.3" 353 - resolved "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz" 354 - integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== 355 - 356 - "@swc/types@^0.1.8": 357 - version "0.1.8" 358 - resolved "https://registry.npmjs.org/@swc/types/-/types-0.1.8.tgz" 359 - integrity sha512-RNFA3+7OJFNYY78x0FYwi1Ow+iF1eF5WvmfY1nXPOEH4R2p/D4Cr1vzje7dNAI2aLFqpv8Wyz4oKSWqIZArpQA== 360 - dependencies: 361 - "@swc/counter" "^0.1.3" 362 - 363 - "@the-convocation/twitter-scraper@^0.16.6": 364 - version "0.16.6" 365 - resolved "https://registry.yarnpkg.com/@the-convocation/twitter-scraper/-/twitter-scraper-0.16.6.tgz#41484ba294eaf43cc8f442234a5f80d5feb83a23" 366 - integrity sha512-+75F/1MVFDJ9UfDwmhEjUbFqbVyLMnBwWNgKCKsshhU+X9Faom0C78RirPLRB088+Gc4aTLcbBS0vyEqz5bqwA== 367 - dependencies: 368 - "@sinclair/typebox" "^0.32.20" 369 - cross-fetch "^4.0.0-alpha.5" 370 - debug "^4.4.1" 371 - headers-polyfill "^3.1.2" 372 - json-stable-stringify "^1.0.2" 373 - otpauth "^9.2.2" 374 - set-cookie-parser "^2.6.0" 375 - tough-cookie "^4.1.2" 376 - tslib "^2.5.2" 377 - 378 - "@types/estree@1.0.5": 379 - version "1.0.5" 380 - resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz" 381 - integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== 382 - 383 - "@types/prop-types@*": 384 - version "15.7.12" 385 - resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz" 386 - integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== 387 - 388 - "@types/react-dom@^18.2.22": 389 - version "18.3.0" 390 - resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz" 391 - integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg== 392 - dependencies: 393 - "@types/react" "*" 394 - 395 - "@types/react@*", "@types/react@^18.2.66": 396 - version "18.3.3" 397 - resolved "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz" 398 - integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw== 399 - dependencies: 400 - "@types/prop-types" "*" 401 - csstype "^3.0.2" 402 - 403 - "@typescript-eslint/eslint-plugin@^7.2.0": 404 - version "7.13.0" 405 - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.0.tgz" 406 - integrity sha512-FX1X6AF0w8MdVFLSdqwqN/me2hyhuQg4ykN6ZpVhh1ij/80pTvDKclX1sZB9iqex8SjQfVhwMKs3JtnnMLzG9w== 407 - dependencies: 408 - "@eslint-community/regexpp" "^4.10.0" 409 - "@typescript-eslint/scope-manager" "7.13.0" 410 - "@typescript-eslint/type-utils" "7.13.0" 411 - "@typescript-eslint/utils" "7.13.0" 412 - "@typescript-eslint/visitor-keys" "7.13.0" 413 - graphemer "^1.4.0" 414 - ignore "^5.3.1" 415 - natural-compare "^1.4.0" 416 - ts-api-utils "^1.3.0" 417 - 418 - "@typescript-eslint/parser@^7.2.0": 419 - version "7.13.0" 420 - resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.0.tgz" 421 - integrity sha512-EjMfl69KOS9awXXe83iRN7oIEXy9yYdqWfqdrFAYAAr6syP8eLEFI7ZE4939antx2mNgPRW/o1ybm2SFYkbTVA== 422 - dependencies: 423 - "@typescript-eslint/scope-manager" "7.13.0" 424 - "@typescript-eslint/types" "7.13.0" 425 - "@typescript-eslint/typescript-estree" "7.13.0" 426 - "@typescript-eslint/visitor-keys" "7.13.0" 427 - debug "^4.3.4" 428 - 429 - "@typescript-eslint/scope-manager@7.13.0": 430 - version "7.13.0" 431 - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.0.tgz" 432 - integrity sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng== 433 - dependencies: 434 - "@typescript-eslint/types" "7.13.0" 435 - "@typescript-eslint/visitor-keys" "7.13.0" 436 - 437 - "@typescript-eslint/type-utils@7.13.0": 438 - version "7.13.0" 439 - resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.0.tgz" 440 - integrity sha512-xMEtMzxq9eRkZy48XuxlBFzpVMDurUAfDu5Rz16GouAtXm0TaAoTFzqWUFPPuQYXI/CDaH/Bgx/fk/84t/Bc9A== 441 - dependencies: 442 - "@typescript-eslint/typescript-estree" "7.13.0" 443 - "@typescript-eslint/utils" "7.13.0" 444 - debug "^4.3.4" 445 - ts-api-utils "^1.3.0" 446 - 447 - "@typescript-eslint/types@7.13.0": 448 - version "7.13.0" 449 - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.0.tgz" 450 - integrity sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA== 451 - 452 - "@typescript-eslint/typescript-estree@7.13.0": 453 - version "7.13.0" 454 - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.0.tgz" 455 - integrity sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw== 456 - dependencies: 457 - "@typescript-eslint/types" "7.13.0" 458 - "@typescript-eslint/visitor-keys" "7.13.0" 459 - debug "^4.3.4" 460 - globby "^11.1.0" 461 - is-glob "^4.0.3" 462 - minimatch "^9.0.4" 463 - semver "^7.6.0" 464 - ts-api-utils "^1.3.0" 465 - 466 - "@typescript-eslint/utils@7.13.0": 467 - version "7.13.0" 468 - resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.0.tgz" 469 - integrity sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ== 470 - dependencies: 471 - "@eslint-community/eslint-utils" "^4.4.0" 472 - "@typescript-eslint/scope-manager" "7.13.0" 473 - "@typescript-eslint/types" "7.13.0" 474 - "@typescript-eslint/typescript-estree" "7.13.0" 475 - 476 - "@typescript-eslint/visitor-keys@7.13.0": 477 - version "7.13.0" 478 - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.0.tgz" 479 - integrity sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw== 480 - dependencies: 481 - "@typescript-eslint/types" "7.13.0" 482 - eslint-visitor-keys "^3.4.3" 483 - 484 - "@ungap/structured-clone@^1.2.0": 485 - version "1.2.0" 486 - resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz" 487 - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== 488 - 489 - "@vitejs/plugin-react-swc@^3.5.0": 490 - version "3.7.0" 491 - resolved "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.7.0.tgz" 492 - integrity sha512-yrknSb3Dci6svCd/qhHqhFPDSw0QtjumcqdKMoNNzmOl5lMXTTiqzjWtG4Qask2HdvvzaNgSunbQGet8/GrKdA== 493 - dependencies: 494 - "@swc/core" "^1.5.7" 495 - 496 - acorn-jsx@^5.3.2: 497 - version "5.3.2" 498 - resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" 499 - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== 500 - 501 - acorn@^8.9.0: 502 - version "8.12.0" 503 - resolved "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz" 504 - integrity sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw== 505 - 506 - ajv@^6.12.4: 507 - version "6.12.6" 508 - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" 509 - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 510 - dependencies: 511 - fast-deep-equal "^3.1.1" 512 - fast-json-stable-stringify "^2.0.0" 513 - json-schema-traverse "^0.4.1" 514 - uri-js "^4.2.2" 515 - 516 - ansi-regex@^5.0.1: 517 - version "5.0.1" 518 - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" 519 - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 520 - 521 - ansi-styles@^4.1.0: 522 - version "4.3.0" 523 - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" 524 - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 525 - dependencies: 526 - color-convert "^2.0.1" 527 - 528 - argparse@^2.0.1: 529 - version "2.0.1" 530 - resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" 531 - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 532 - 533 - array-union@^2.1.0: 534 - version "2.1.0" 535 - resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" 536 - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== 537 - 538 - balanced-match@^1.0.0: 539 - version "1.0.2" 540 - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" 541 - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 542 - 543 - brace-expansion@^1.1.7: 544 - version "1.1.11" 545 - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" 546 - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 547 - dependencies: 548 - balanced-match "^1.0.0" 549 - concat-map "0.0.1" 550 - 551 - brace-expansion@^2.0.1: 552 - version "2.0.1" 553 - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" 554 - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== 555 - dependencies: 556 - balanced-match "^1.0.0" 557 - 558 - braces@^3.0.3: 559 - version "3.0.3" 560 - resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" 561 - integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== 562 - dependencies: 563 - fill-range "^7.1.1" 564 - 565 - call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: 566 - version "1.0.2" 567 - resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" 568 - integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== 569 - dependencies: 570 - es-errors "^1.3.0" 571 - function-bind "^1.1.2" 572 - 573 - call-bind@^1.0.8: 574 - version "1.0.8" 575 - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" 576 - integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== 577 - dependencies: 578 - call-bind-apply-helpers "^1.0.0" 579 - es-define-property "^1.0.0" 580 - get-intrinsic "^1.2.4" 581 - set-function-length "^1.2.2" 582 - 583 - call-bound@^1.0.4: 584 - version "1.0.4" 585 - resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" 586 - integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== 587 - dependencies: 588 - call-bind-apply-helpers "^1.0.2" 589 - get-intrinsic "^1.3.0" 590 - 591 - callsites@^3.0.0: 592 - version "3.1.0" 593 - resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" 594 - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 595 - 596 - chalk@^4.0.0: 597 - version "4.1.2" 598 - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" 599 - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 600 - dependencies: 601 - ansi-styles "^4.1.0" 602 - supports-color "^7.1.0" 603 - 604 - color-convert@^2.0.1: 605 - version "2.0.1" 606 - resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" 607 - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 608 - dependencies: 609 - color-name "~1.1.4" 610 - 611 - color-name@~1.1.4: 612 - version "1.1.4" 613 - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" 614 - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 615 - 616 - concat-map@0.0.1: 617 - version "0.0.1" 618 - resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" 619 - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== 620 - 621 - cross-fetch@^4.0.0-alpha.5: 622 - version "4.1.0" 623 - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.1.0.tgz#8f69355007ee182e47fa692ecbaa37a52e43c3d2" 624 - integrity sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw== 625 - dependencies: 626 - node-fetch "^2.7.0" 627 - 628 - cross-spawn@^7.0.2: 629 - version "7.0.3" 630 - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" 631 - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== 632 - dependencies: 633 - path-key "^3.1.0" 634 - shebang-command "^2.0.0" 635 - which "^2.0.1" 636 - 637 - csstype@^3.0.2: 638 - version "3.1.3" 639 - resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz" 640 - integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== 641 - 642 - debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: 643 - version "4.3.5" 644 - resolved "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz" 645 - integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== 646 - dependencies: 647 - ms "2.1.2" 648 - 649 - debug@^4.4.1: 650 - version "4.4.1" 651 - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" 652 - integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== 653 - dependencies: 654 - ms "^2.1.3" 655 - 656 - deep-is@^0.1.3: 657 - version "0.1.4" 658 - resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" 659 - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== 660 - 661 - define-data-property@^1.1.4: 662 - version "1.1.4" 663 - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" 664 - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== 665 - dependencies: 666 - es-define-property "^1.0.0" 667 - es-errors "^1.3.0" 668 - gopd "^1.0.1" 669 - 670 - dir-glob@^3.0.1: 671 - version "3.0.1" 672 - resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" 673 - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== 674 - dependencies: 675 - path-type "^4.0.0" 676 - 677 - doctrine@^3.0.0: 678 - version "3.0.0" 679 - resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" 680 - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== 681 - dependencies: 682 - esutils "^2.0.2" 683 - 684 - dunder-proto@^1.0.1: 685 - version "1.0.1" 686 - resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" 687 - integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== 688 - dependencies: 689 - call-bind-apply-helpers "^1.0.1" 690 - es-errors "^1.3.0" 691 - gopd "^1.2.0" 692 - 693 - es-define-property@^1.0.0, es-define-property@^1.0.1: 694 - version "1.0.1" 695 - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" 696 - integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== 697 - 698 - es-errors@^1.3.0: 699 - version "1.3.0" 700 - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" 701 - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== 702 - 703 - es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: 704 - version "1.1.1" 705 - resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" 706 - integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== 707 - dependencies: 708 - es-errors "^1.3.0" 709 - 710 - esbuild@^0.21.3: 711 - version "0.21.5" 712 - resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz" 713 - integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== 714 - optionalDependencies: 715 - "@esbuild/aix-ppc64" "0.21.5" 716 - "@esbuild/android-arm" "0.21.5" 717 - "@esbuild/android-arm64" "0.21.5" 718 - "@esbuild/android-x64" "0.21.5" 719 - "@esbuild/darwin-arm64" "0.21.5" 720 - "@esbuild/darwin-x64" "0.21.5" 721 - "@esbuild/freebsd-arm64" "0.21.5" 722 - "@esbuild/freebsd-x64" "0.21.5" 723 - "@esbuild/linux-arm" "0.21.5" 724 - "@esbuild/linux-arm64" "0.21.5" 725 - "@esbuild/linux-ia32" "0.21.5" 726 - "@esbuild/linux-loong64" "0.21.5" 727 - "@esbuild/linux-mips64el" "0.21.5" 728 - "@esbuild/linux-ppc64" "0.21.5" 729 - "@esbuild/linux-riscv64" "0.21.5" 730 - "@esbuild/linux-s390x" "0.21.5" 731 - "@esbuild/linux-x64" "0.21.5" 732 - "@esbuild/netbsd-x64" "0.21.5" 733 - "@esbuild/openbsd-x64" "0.21.5" 734 - "@esbuild/sunos-x64" "0.21.5" 735 - "@esbuild/win32-arm64" "0.21.5" 736 - "@esbuild/win32-ia32" "0.21.5" 737 - "@esbuild/win32-x64" "0.21.5" 738 - 739 - escape-string-regexp@^4.0.0: 740 - version "4.0.0" 741 - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" 742 - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 743 - 744 - eslint-plugin-react-hooks@^4.6.0: 745 - version "4.6.2" 746 - resolved "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz" 747 - integrity sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ== 748 - 749 - eslint-plugin-react-refresh@^0.4.6: 750 - version "0.4.7" 751 - resolved "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.7.tgz" 752 - integrity sha512-yrj+KInFmwuQS2UQcg1SF83ha1tuHC1jMQbRNyuWtlEzzKRDgAl7L4Yp4NlDUZTZNlWvHEzOtJhMi40R7JxcSw== 753 - 754 - eslint-scope@^7.2.2: 755 - version "7.2.2" 756 - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz" 757 - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== 758 - dependencies: 759 - esrecurse "^4.3.0" 760 - estraverse "^5.2.0" 761 - 762 - eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: 763 - version "3.4.3" 764 - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" 765 - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== 766 - 767 - eslint@^8.57.0: 768 - version "8.57.0" 769 - resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz" 770 - integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== 771 - dependencies: 772 - "@eslint-community/eslint-utils" "^4.2.0" 773 - "@eslint-community/regexpp" "^4.6.1" 774 - "@eslint/eslintrc" "^2.1.4" 775 - "@eslint/js" "8.57.0" 776 - "@humanwhocodes/config-array" "^0.11.14" 777 - "@humanwhocodes/module-importer" "^1.0.1" 778 - "@nodelib/fs.walk" "^1.2.8" 779 - "@ungap/structured-clone" "^1.2.0" 780 - ajv "^6.12.4" 781 - chalk "^4.0.0" 782 - cross-spawn "^7.0.2" 783 - debug "^4.3.2" 784 - doctrine "^3.0.0" 785 - escape-string-regexp "^4.0.0" 786 - eslint-scope "^7.2.2" 787 - eslint-visitor-keys "^3.4.3" 788 - espree "^9.6.1" 789 - esquery "^1.4.2" 790 - esutils "^2.0.2" 791 - fast-deep-equal "^3.1.3" 792 - file-entry-cache "^6.0.1" 793 - find-up "^5.0.0" 794 - glob-parent "^6.0.2" 795 - globals "^13.19.0" 796 - graphemer "^1.4.0" 797 - ignore "^5.2.0" 798 - imurmurhash "^0.1.4" 799 - is-glob "^4.0.0" 800 - is-path-inside "^3.0.3" 801 - js-yaml "^4.1.0" 802 - json-stable-stringify-without-jsonify "^1.0.1" 803 - levn "^0.4.1" 804 - lodash.merge "^4.6.2" 805 - minimatch "^3.1.2" 806 - natural-compare "^1.4.0" 807 - optionator "^0.9.3" 808 - strip-ansi "^6.0.1" 809 - text-table "^0.2.0" 810 - 811 - espree@^9.6.0, espree@^9.6.1: 812 - version "9.6.1" 813 - resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz" 814 - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== 815 - dependencies: 816 - acorn "^8.9.0" 817 - acorn-jsx "^5.3.2" 818 - eslint-visitor-keys "^3.4.1" 819 - 820 - esquery@^1.4.2: 821 - version "1.5.0" 822 - resolved "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz" 823 - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== 824 - dependencies: 825 - estraverse "^5.1.0" 826 - 827 - esrecurse@^4.3.0: 828 - version "4.3.0" 829 - resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" 830 - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== 831 - dependencies: 832 - estraverse "^5.2.0" 833 - 834 - estraverse@^5.1.0, estraverse@^5.2.0: 835 - version "5.3.0" 836 - resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" 837 - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== 838 - 839 - esutils@^2.0.2: 840 - version "2.0.3" 841 - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" 842 - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 843 - 844 - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: 845 - version "3.1.3" 846 - resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" 847 - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 848 - 849 - fast-glob@^3.2.9: 850 - version "3.3.2" 851 - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz" 852 - integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== 853 - dependencies: 854 - "@nodelib/fs.stat" "^2.0.2" 855 - "@nodelib/fs.walk" "^1.2.3" 856 - glob-parent "^5.1.2" 857 - merge2 "^1.3.0" 858 - micromatch "^4.0.4" 859 - 860 - fast-json-stable-stringify@^2.0.0: 861 - version "2.1.0" 862 - resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" 863 - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 864 - 865 - fast-levenshtein@^2.0.6: 866 - version "2.0.6" 867 - resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" 868 - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== 869 - 870 - fastq@^1.6.0: 871 - version "1.17.1" 872 - resolved "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz" 873 - integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== 874 - dependencies: 875 - reusify "^1.0.4" 876 - 877 - file-entry-cache@^6.0.1: 878 - version "6.0.1" 879 - resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" 880 - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== 881 - dependencies: 882 - flat-cache "^3.0.4" 883 - 884 - fill-range@^7.1.1: 885 - version "7.1.1" 886 - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz" 887 - integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== 888 - dependencies: 889 - to-regex-range "^5.0.1" 890 - 891 - find-up@^5.0.0: 892 - version "5.0.0" 893 - resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" 894 - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 895 - dependencies: 896 - locate-path "^6.0.0" 897 - path-exists "^4.0.0" 898 - 899 - flat-cache@^3.0.4: 900 - version "3.2.0" 901 - resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz" 902 - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== 903 - dependencies: 904 - flatted "^3.2.9" 905 - keyv "^4.5.3" 906 - rimraf "^3.0.2" 907 - 908 - flatted@^3.2.9: 909 - version "3.3.1" 910 - resolved "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz" 911 - integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== 912 - 913 - fs.realpath@^1.0.0: 914 - version "1.0.0" 915 - resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" 916 - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== 917 - 918 - fsevents@~2.3.2, fsevents@~2.3.3: 919 - version "2.3.3" 920 - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" 921 - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== 922 - 923 - function-bind@^1.1.2: 924 - version "1.1.2" 925 - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" 926 - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== 927 - 928 - get-intrinsic@^1.2.4, get-intrinsic@^1.3.0: 929 - version "1.3.0" 930 - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" 931 - integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== 932 - dependencies: 933 - call-bind-apply-helpers "^1.0.2" 934 - es-define-property "^1.0.1" 935 - es-errors "^1.3.0" 936 - es-object-atoms "^1.1.1" 937 - function-bind "^1.1.2" 938 - get-proto "^1.0.1" 939 - gopd "^1.2.0" 940 - has-symbols "^1.1.0" 941 - hasown "^2.0.2" 942 - math-intrinsics "^1.1.0" 943 - 944 - get-proto@^1.0.1: 945 - version "1.0.1" 946 - resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" 947 - integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== 948 - dependencies: 949 - dunder-proto "^1.0.1" 950 - es-object-atoms "^1.0.0" 951 - 952 - glob-parent@^5.1.2: 953 - version "5.1.2" 954 - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" 955 - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 956 - dependencies: 957 - is-glob "^4.0.1" 958 - 959 - glob-parent@^6.0.2: 960 - version "6.0.2" 961 - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" 962 - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== 963 - dependencies: 964 - is-glob "^4.0.3" 965 - 966 - glob@^7.1.3: 967 - version "7.2.3" 968 - resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" 969 - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== 970 - dependencies: 971 - fs.realpath "^1.0.0" 972 - inflight "^1.0.4" 973 - inherits "2" 974 - minimatch "^3.1.1" 975 - once "^1.3.0" 976 - path-is-absolute "^1.0.0" 977 - 978 - globals@^13.19.0: 979 - version "13.24.0" 980 - resolved "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz" 981 - integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== 982 - dependencies: 983 - type-fest "^0.20.2" 984 - 985 - globby@^11.1.0: 986 - version "11.1.0" 987 - resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" 988 - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== 989 - dependencies: 990 - array-union "^2.1.0" 991 - dir-glob "^3.0.1" 992 - fast-glob "^3.2.9" 993 - ignore "^5.2.0" 994 - merge2 "^1.4.1" 995 - slash "^3.0.0" 996 - 997 - gopd@^1.0.1, gopd@^1.2.0: 998 - version "1.2.0" 999 - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" 1000 - integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== 1001 - 1002 - graphemer@^1.4.0: 1003 - version "1.4.0" 1004 - resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz" 1005 - integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== 1006 - 1007 - has-flag@^4.0.0: 1008 - version "4.0.0" 1009 - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" 1010 - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 1011 - 1012 - has-property-descriptors@^1.0.2: 1013 - version "1.0.2" 1014 - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" 1015 - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== 1016 - dependencies: 1017 - es-define-property "^1.0.0" 1018 - 1019 - has-symbols@^1.1.0: 1020 - version "1.1.0" 1021 - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" 1022 - integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== 1023 - 1024 - hasown@^2.0.2: 1025 - version "2.0.2" 1026 - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" 1027 - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== 1028 - dependencies: 1029 - function-bind "^1.1.2" 1030 - 1031 - headers-polyfill@^3.1.2: 1032 - version "3.3.0" 1033 - resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-3.3.0.tgz#67c6ef7b72d4c8cac832ad5936f5b3a56e7b705a" 1034 - integrity sha512-5e57etwBpNcDc0b6KCVWEh/Ro063OxPvzVimUdM0/tsYM/T7Hfy3kknIGj78SFTOhNd8AZY41U8mOHoO4LzmIQ== 1035 - 1036 - ignore@^5.2.0, ignore@^5.3.1: 1037 - version "5.3.1" 1038 - resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz" 1039 - integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== 1040 - 1041 - import-fresh@^3.2.1: 1042 - version "3.3.0" 1043 - resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" 1044 - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== 1045 - dependencies: 1046 - parent-module "^1.0.0" 1047 - resolve-from "^4.0.0" 1048 - 1049 - imurmurhash@^0.1.4: 1050 - version "0.1.4" 1051 - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" 1052 - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== 1053 - 1054 - inflight@^1.0.4: 1055 - version "1.0.6" 1056 - resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" 1057 - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== 1058 - dependencies: 1059 - once "^1.3.0" 1060 - wrappy "1" 1061 - 1062 - inherits@2: 1063 - version "2.0.4" 1064 - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" 1065 - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 1066 - 1067 - is-extglob@^2.1.1: 1068 - version "2.1.1" 1069 - resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" 1070 - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 1071 - 1072 - is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: 1073 - version "4.0.3" 1074 - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" 1075 - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 1076 - dependencies: 1077 - is-extglob "^2.1.1" 1078 - 1079 - is-number@^7.0.0: 1080 - version "7.0.0" 1081 - resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" 1082 - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 1083 - 1084 - is-path-inside@^3.0.3: 1085 - version "3.0.3" 1086 - resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" 1087 - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== 1088 - 1089 - isarray@^2.0.5: 1090 - version "2.0.5" 1091 - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" 1092 - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== 1093 - 1094 - isexe@^2.0.0: 1095 - version "2.0.0" 1096 - resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" 1097 - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== 1098 - 1099 - "js-tokens@^3.0.0 || ^4.0.0": 1100 - version "4.0.0" 1101 - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" 1102 - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 1103 - 1104 - js-yaml@^4.1.0: 1105 - version "4.1.0" 1106 - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" 1107 - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 1108 - dependencies: 1109 - argparse "^2.0.1" 1110 - 1111 - json-buffer@3.0.1: 1112 - version "3.0.1" 1113 - resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz" 1114 - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== 1115 - 1116 - json-schema-traverse@^0.4.1: 1117 - version "0.4.1" 1118 - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" 1119 - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 1120 - 1121 - json-stable-stringify-without-jsonify@^1.0.1: 1122 - version "1.0.1" 1123 - resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" 1124 - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== 1125 - 1126 - json-stable-stringify@^1.0.2: 1127 - version "1.3.0" 1128 - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz#8903cfac42ea1a0f97f35d63a4ce0518f0cc6a70" 1129 - integrity sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg== 1130 - dependencies: 1131 - call-bind "^1.0.8" 1132 - call-bound "^1.0.4" 1133 - isarray "^2.0.5" 1134 - jsonify "^0.0.1" 1135 - object-keys "^1.1.1" 1136 - 1137 - jsonify@^0.0.1: 1138 - version "0.0.1" 1139 - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" 1140 - integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== 1141 - 1142 - keyv@^4.5.3: 1143 - version "4.5.4" 1144 - resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz" 1145 - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== 1146 - dependencies: 1147 - json-buffer "3.0.1" 1148 - 1149 - levn@^0.4.1: 1150 - version "0.4.1" 1151 - resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" 1152 - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== 1153 - dependencies: 1154 - prelude-ls "^1.2.1" 1155 - type-check "~0.4.0" 1156 - 1157 - locate-path@^6.0.0: 1158 - version "6.0.0" 1159 - resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" 1160 - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 1161 - dependencies: 1162 - p-locate "^5.0.0" 1163 - 1164 - lodash.merge@^4.6.2: 1165 - version "4.6.2" 1166 - resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" 1167 - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== 1168 - 1169 - loose-envify@^1.1.0: 1170 - version "1.4.0" 1171 - resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" 1172 - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== 1173 - dependencies: 1174 - js-tokens "^3.0.0 || ^4.0.0" 1175 - 1176 - math-intrinsics@^1.1.0: 1177 - version "1.1.0" 1178 - resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" 1179 - integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== 1180 - 1181 - merge2@^1.3.0, merge2@^1.4.1: 1182 - version "1.4.1" 1183 - resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" 1184 - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== 1185 - 1186 - micromatch@^4.0.4: 1187 - version "4.0.7" 1188 - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz" 1189 - integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== 1190 - dependencies: 1191 - braces "^3.0.3" 1192 - picomatch "^2.3.1" 1193 - 1194 - minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: 1195 - version "3.1.2" 1196 - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" 1197 - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 1198 - dependencies: 1199 - brace-expansion "^1.1.7" 1200 - 1201 - minimatch@^9.0.4: 1202 - version "9.0.4" 1203 - resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz" 1204 - integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== 1205 - dependencies: 1206 - brace-expansion "^2.0.1" 1207 - 1208 - ms@2.1.2: 1209 - version "2.1.2" 1210 - resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" 1211 - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 1212 - 1213 - ms@^2.1.3: 1214 - version "2.1.3" 1215 - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 1216 - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 1217 - 1218 - nanoid@^3.3.7: 1219 - version "3.3.7" 1220 - resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz" 1221 - integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== 1222 - 1223 - natural-compare@^1.4.0: 1224 - version "1.4.0" 1225 - resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" 1226 - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== 1227 - 1228 - node-fetch@^2.7.0: 1229 - version "2.7.0" 1230 - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" 1231 - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== 1232 - dependencies: 1233 - whatwg-url "^5.0.0" 1234 - 1235 - object-keys@^1.1.1: 1236 - version "1.1.1" 1237 - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" 1238 - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== 1239 - 1240 - once@^1.3.0: 1241 - version "1.4.0" 1242 - resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" 1243 - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== 1244 - dependencies: 1245 - wrappy "1" 1246 - 1247 - optionator@^0.9.3: 1248 - version "0.9.4" 1249 - resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz" 1250 - integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== 1251 - dependencies: 1252 - deep-is "^0.1.3" 1253 - fast-levenshtein "^2.0.6" 1254 - levn "^0.4.1" 1255 - prelude-ls "^1.2.1" 1256 - type-check "^0.4.0" 1257 - word-wrap "^1.2.5" 1258 - 1259 - otpauth@^9.2.2: 1260 - version "9.4.0" 1261 - resolved "https://registry.yarnpkg.com/otpauth/-/otpauth-9.4.0.tgz#ed52538848cc52138e4dcd75cef45412b6175ea1" 1262 - integrity sha512-fHIfzIG5RqCkK9cmV8WU+dPQr9/ebR5QOwGZn2JAr1RQF+lmAuLL2YdtdqvmBjNmgJlYk3KZ4a0XokaEhg1Jsw== 1263 - dependencies: 1264 - "@noble/hashes" "1.7.1" 1265 - 1266 - p-limit@^3.0.2: 1267 - version "3.1.0" 1268 - resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" 1269 - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 1270 - dependencies: 1271 - yocto-queue "^0.1.0" 1272 - 1273 - p-locate@^5.0.0: 1274 - version "5.0.0" 1275 - resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" 1276 - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 1277 - dependencies: 1278 - p-limit "^3.0.2" 1279 - 1280 - parent-module@^1.0.0: 1281 - version "1.0.1" 1282 - resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" 1283 - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== 1284 - dependencies: 1285 - callsites "^3.0.0" 1286 - 1287 - path-exists@^4.0.0: 1288 - version "4.0.0" 1289 - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" 1290 - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 1291 - 1292 - path-is-absolute@^1.0.0: 1293 - version "1.0.1" 1294 - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" 1295 - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== 1296 - 1297 - path-key@^3.1.0: 1298 - version "3.1.1" 1299 - resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" 1300 - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 1301 - 1302 - path-type@^4.0.0: 1303 - version "4.0.0" 1304 - resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" 1305 - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== 1306 - 1307 - picocolors@^1.0.0: 1308 - version "1.0.1" 1309 - resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz" 1310 - integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== 1311 - 1312 - picomatch@^2.3.1: 1313 - version "2.3.1" 1314 - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" 1315 - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 1316 - 1317 - postcss@^8.4.38: 1318 - version "8.4.38" 1319 - resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz" 1320 - integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== 1321 - dependencies: 1322 - nanoid "^3.3.7" 1323 - picocolors "^1.0.0" 1324 - source-map-js "^1.2.0" 1325 - 1326 - prelude-ls@^1.2.1: 1327 - version "1.2.1" 1328 - resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" 1329 - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== 1330 - 1331 - psl@^1.1.33: 1332 - version "1.15.0" 1333 - resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" 1334 - integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w== 1335 - dependencies: 1336 - punycode "^2.3.1" 1337 - 1338 - punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: 1339 - version "2.3.1" 1340 - resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz" 1341 - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== 1342 - 1343 - querystringify@^2.1.1: 1344 - version "2.2.0" 1345 - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" 1346 - integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== 1347 - 1348 - queue-microtask@^1.2.2: 1349 - version "1.2.3" 1350 - resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" 1351 - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== 1352 - 1353 - react-dom@^18.2.0: 1354 - version "18.3.1" 1355 - resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz" 1356 - integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== 1357 - dependencies: 1358 - loose-envify "^1.1.0" 1359 - scheduler "^0.23.2" 1360 - 1361 - react@^18.2.0: 1362 - version "18.3.1" 1363 - resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz" 1364 - integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== 1365 - dependencies: 1366 - loose-envify "^1.1.0" 1367 - 1368 - requires-port@^1.0.0: 1369 - version "1.0.0" 1370 - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" 1371 - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== 1372 - 1373 - resolve-from@^4.0.0: 1374 - version "4.0.0" 1375 - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" 1376 - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 1377 - 1378 - reusify@^1.0.4: 1379 - version "1.0.4" 1380 - resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" 1381 - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== 1382 - 1383 - rimraf@^3.0.2: 1384 - version "3.0.2" 1385 - resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" 1386 - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== 1387 - dependencies: 1388 - glob "^7.1.3" 1389 - 1390 - rollup@^4.13.0: 1391 - version "4.18.0" 1392 - resolved "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz" 1393 - integrity sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg== 1394 - dependencies: 1395 - "@types/estree" "1.0.5" 1396 - optionalDependencies: 1397 - "@rollup/rollup-android-arm-eabi" "4.18.0" 1398 - "@rollup/rollup-android-arm64" "4.18.0" 1399 - "@rollup/rollup-darwin-arm64" "4.18.0" 1400 - "@rollup/rollup-darwin-x64" "4.18.0" 1401 - "@rollup/rollup-linux-arm-gnueabihf" "4.18.0" 1402 - "@rollup/rollup-linux-arm-musleabihf" "4.18.0" 1403 - "@rollup/rollup-linux-arm64-gnu" "4.18.0" 1404 - "@rollup/rollup-linux-arm64-musl" "4.18.0" 1405 - "@rollup/rollup-linux-powerpc64le-gnu" "4.18.0" 1406 - "@rollup/rollup-linux-riscv64-gnu" "4.18.0" 1407 - "@rollup/rollup-linux-s390x-gnu" "4.18.0" 1408 - "@rollup/rollup-linux-x64-gnu" "4.18.0" 1409 - "@rollup/rollup-linux-x64-musl" "4.18.0" 1410 - "@rollup/rollup-win32-arm64-msvc" "4.18.0" 1411 - "@rollup/rollup-win32-ia32-msvc" "4.18.0" 1412 - "@rollup/rollup-win32-x64-msvc" "4.18.0" 1413 - fsevents "~2.3.2" 1414 - 1415 - run-parallel@^1.1.9: 1416 - version "1.2.0" 1417 - resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" 1418 - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== 1419 - dependencies: 1420 - queue-microtask "^1.2.2" 1421 - 1422 - scheduler@^0.23.2: 1423 - version "0.23.2" 1424 - resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz" 1425 - integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== 1426 - dependencies: 1427 - loose-envify "^1.1.0" 1428 - 1429 - semver@^7.6.0: 1430 - version "7.6.2" 1431 - resolved "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz" 1432 - integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== 1433 - 1434 - set-cookie-parser@^2.6.0: 1435 - version "2.7.1" 1436 - resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz#3016f150072202dfbe90fadee053573cc89d2943" 1437 - integrity sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ== 1438 - 1439 - set-function-length@^1.2.2: 1440 - version "1.2.2" 1441 - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" 1442 - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== 1443 - dependencies: 1444 - define-data-property "^1.1.4" 1445 - es-errors "^1.3.0" 1446 - function-bind "^1.1.2" 1447 - get-intrinsic "^1.2.4" 1448 - gopd "^1.0.1" 1449 - has-property-descriptors "^1.0.2" 1450 - 1451 - shebang-command@^2.0.0: 1452 - version "2.0.0" 1453 - resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" 1454 - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 1455 - dependencies: 1456 - shebang-regex "^3.0.0" 1457 - 1458 - shebang-regex@^3.0.0: 1459 - version "3.0.0" 1460 - resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" 1461 - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 1462 - 1463 - slash@^3.0.0: 1464 - version "3.0.0" 1465 - resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" 1466 - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== 1467 - 1468 - source-map-js@^1.2.0: 1469 - version "1.2.0" 1470 - resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz" 1471 - integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== 1472 - 1473 - strip-ansi@^6.0.1: 1474 - version "6.0.1" 1475 - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" 1476 - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 1477 - dependencies: 1478 - ansi-regex "^5.0.1" 1479 - 1480 - strip-json-comments@^3.1.1: 1481 - version "3.1.1" 1482 - resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" 1483 - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 1484 - 1485 - supports-color@^7.1.0: 1486 - version "7.2.0" 1487 - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" 1488 - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 1489 - dependencies: 1490 - has-flag "^4.0.0" 1491 - 1492 - text-table@^0.2.0: 1493 - version "0.2.0" 1494 - resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" 1495 - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== 1496 - 1497 - to-regex-range@^5.0.1: 1498 - version "5.0.1" 1499 - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" 1500 - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1501 - dependencies: 1502 - is-number "^7.0.0" 1503 - 1504 - tough-cookie@^4.1.2: 1505 - version "4.1.4" 1506 - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" 1507 - integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== 1508 - dependencies: 1509 - psl "^1.1.33" 1510 - punycode "^2.1.1" 1511 - universalify "^0.2.0" 1512 - url-parse "^1.5.3" 1513 - 1514 - tr46@~0.0.3: 1515 - version "0.0.3" 1516 - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" 1517 - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== 1518 - 1519 - ts-api-utils@^1.3.0: 1520 - version "1.3.0" 1521 - resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz" 1522 - integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== 1523 - 1524 - tslib@^2.5.2: 1525 - version "2.8.1" 1526 - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" 1527 - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== 1528 - 1529 - type-check@^0.4.0, type-check@~0.4.0: 1530 - version "0.4.0" 1531 - resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" 1532 - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== 1533 - dependencies: 1534 - prelude-ls "^1.2.1" 1535 - 1536 - type-fest@^0.20.2: 1537 - version "0.20.2" 1538 - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" 1539 - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== 1540 - 1541 - typescript@^5.2.2: 1542 - version "5.4.5" 1543 - resolved "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz" 1544 - integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== 1545 - 1546 - universalify@^0.2.0: 1547 - version "0.2.0" 1548 - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" 1549 - integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== 1550 - 1551 - uri-js@^4.2.2: 1552 - version "4.4.1" 1553 - resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" 1554 - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 1555 - dependencies: 1556 - punycode "^2.1.0" 1557 - 1558 - url-parse@^1.5.3: 1559 - version "1.5.10" 1560 - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" 1561 - integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== 1562 - dependencies: 1563 - querystringify "^2.1.1" 1564 - requires-port "^1.0.0" 1565 - 1566 - vite@^5.2.0: 1567 - version "5.3.1" 1568 - resolved "https://registry.npmjs.org/vite/-/vite-5.3.1.tgz" 1569 - integrity sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ== 1570 - dependencies: 1571 - esbuild "^0.21.3" 1572 - postcss "^8.4.38" 1573 - rollup "^4.13.0" 1574 - optionalDependencies: 1575 - fsevents "~2.3.3" 1576 - 1577 - webidl-conversions@^3.0.0: 1578 - version "3.0.1" 1579 - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" 1580 - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== 1581 - 1582 - whatwg-url@^5.0.0: 1583 - version "5.0.0" 1584 - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" 1585 - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== 1586 - dependencies: 1587 - tr46 "~0.0.3" 1588 - webidl-conversions "^3.0.0" 1589 - 1590 - which@^2.0.1: 1591 - version "2.0.2" 1592 - resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" 1593 - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1594 - dependencies: 1595 - isexe "^2.0.0" 1596 - 1597 - word-wrap@^1.2.5: 1598 - version "1.2.5" 1599 - resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz" 1600 - integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== 1601 - 1602 - wrappy@1: 1603 - version "1.0.2" 1604 - resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" 1605 - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== 1606 - 1607 - yocto-queue@^0.1.0: 1608 - version "0.1.0" 1609 - resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" 1610 - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
-27
twitter-scraper/jest.config.js
··· 1 - /** @type {import('ts-jest').JestConfigWithTsJest} */ 2 - module.exports = { 3 - preset: 'ts-jest/presets/default-esm', 4 - testEnvironment: 'node', 5 - extensionsToTreatAsEsm: ['.ts'], 6 - setupFiles: ['dotenv/config', './test-setup.js'], 7 - collectCoverage: true, 8 - collectCoverageFrom: [ 9 - 'src/**/*.{js,ts}', 10 - '!src/index.ts', 11 - '!src/**/*.d.ts', 12 - '!src/**/*.test.{js,ts}', 13 - '!src/**/*.spec.{js,ts}', 14 - ], 15 - coverageDirectory: 'coverage', 16 - moduleNameMapper: { 17 - '^(\\.{1,2}/.*)\\.js$': '$1', 18 - }, 19 - transform: { 20 - '^.+\\.tsx?$': [ 21 - 'ts-jest', 22 - { 23 - useESM: true, 24 - }, 25 - ], 26 - }, 27 - };
-110
twitter-scraper/package.json
··· 1 - { 2 - "name": "@the-convocation/twitter-scraper", 3 - "description": "A port of n0madic/twitter-scraper to Node.js.", 4 - "keywords": [ 5 - "x", 6 - "twitter", 7 - "scraper", 8 - "crawler" 9 - ], 10 - "version": "0.21.1", 11 - "main": "dist/default/cjs/index.js", 12 - "types": "./dist/types/index.d.ts", 13 - "exports": { 14 - ".": { 15 - "types": "./dist/types/index.d.ts", 16 - "node": { 17 - "import": "./dist/node/esm/index.mjs", 18 - "require": "./dist/node/cjs/index.cjs" 19 - }, 20 - "default": { 21 - "import": "./dist/default/esm/index.mjs", 22 - "require": "./dist/default/cjs/index.js" 23 - } 24 - }, 25 - "./cycletls": { 26 - "types": "./dist/cycletls/index.d.ts", 27 - "import": "./dist/cycletls/esm/index.mjs", 28 - "require": "./dist/cycletls/cjs/index.cjs" 29 - } 30 - }, 31 - "repository": "https://github.com/the-convocation/twitter-scraper.git", 32 - "author": "karashiiro <49822414+karashiiro@users.noreply.github.com>", 33 - "license": "MIT", 34 - "engines": { 35 - "node": ">=16" 36 - }, 37 - "packageManager": "yarn@1.22.19", 38 - "scripts": { 39 - "build": "rimraf dist && rollup -c", 40 - "commit": "cz", 41 - "docs:generate": "typedoc --options typedoc.json", 42 - "docs:deploy": "yarn docs:generate && gh-pages -d docs", 43 - "format": "prettier --write src/**/*.ts examples/**/*.{ts,js,tsx}", 44 - "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --runInBand --forceExit" 45 - }, 46 - "dependencies": { 47 - "@sinclair/typebox": "^0.32.20", 48 - "cross-fetch": "^4.0.0-alpha.5", 49 - "debug": "^4.4.1", 50 - "headers-polyfill": "^3.1.2", 51 - "json-stable-stringify": "^1.0.2", 52 - "linkedom": "^0.18.12", 53 - "otpauth": "^9.2.2", 54 - "set-cookie-parser": "^2.6.0", 55 - "tough-cookie": "^4.1.2", 56 - "tslib": "^2.5.2", 57 - "x-client-transaction-id": "^0.1.9" 58 - }, 59 - "peerDependencies": { 60 - "cycletls": "^2.0.5" 61 - }, 62 - "peerDependenciesMeta": { 63 - "cycletls": { 64 - "optional": true 65 - } 66 - }, 67 - "devDependencies": { 68 - "@commitlint/cli": "^17.6.3", 69 - "@commitlint/config-conventional": "^17.6.3", 70 - "@tsconfig/node16": "^16.1.0", 71 - "@types/debug": "^4.1.12", 72 - "@types/jest": "^29.5.1", 73 - "@types/json-stable-stringify": "^1.0.34", 74 - "@types/set-cookie-parser": "^2.4.2", 75 - "@types/tough-cookie": "^4.0.2", 76 - "@typescript-eslint/eslint-plugin": "^5.59.7", 77 - "@typescript-eslint/parser": "^5.59.7", 78 - "cycletls": "^2.0.4", 79 - "cz-conventional-changelog": "^3.3.0", 80 - "dotenv": "^16.3.1", 81 - "esbuild": "^0.21.5", 82 - "eslint": "^8.41.0", 83 - "eslint-config-prettier": "^8.8.0", 84 - "eslint-plugin-prettier": "^4.2.1", 85 - "gh-pages": "^5.0.0", 86 - "https-proxy-agent": "^7.0.2", 87 - "husky": "^8.0.3", 88 - "jest": "^29.5.0", 89 - "lint-staged": "^13.2.2", 90 - "prettier": "^2.8.8", 91 - "rimraf": "^5.0.7", 92 - "rollup": "^4.18.0", 93 - "rollup-plugin-dts": "^6.1.1", 94 - "rollup-plugin-esbuild": "^6.1.1", 95 - "ts-jest": "^29.1.0", 96 - "typedoc": "^0.27.6", 97 - "typescript": "^5.0.4" 98 - }, 99 - "config": { 100 - "commitizen": { 101 - "path": "./node_modules/cz-conventional-changelog" 102 - } 103 - }, 104 - "lint-staged": { 105 - "*.{js,ts}": [ 106 - "eslint --cache --fix", 107 - "prettier --write" 108 - ] 109 - } 110 - }
-92
twitter-scraper/rollup.config.mjs
··· 1 - import dts from 'rollup-plugin-dts'; 2 - import esbuild from 'rollup-plugin-esbuild'; 3 - 4 - export default [ 5 - { 6 - input: 'src/_module.ts', 7 - plugins: [ 8 - esbuild({ 9 - define: { 10 - PLATFORM_NODE: 'false', 11 - }, 12 - }), 13 - ], 14 - output: [ 15 - { 16 - file: 'dist/default/cjs/index.js', 17 - format: 'cjs', 18 - sourcemap: true, 19 - }, 20 - { 21 - file: 'dist/default/esm/index.mjs', 22 - format: 'es', 23 - sourcemap: true, 24 - }, 25 - ], 26 - }, 27 - { 28 - input: 'src/_module.ts', 29 - plugins: [ 30 - esbuild({ 31 - define: { 32 - PLATFORM_NODE: 'true', 33 - }, 34 - }), 35 - ], 36 - output: [ 37 - { 38 - file: 'dist/node/cjs/index.cjs', 39 - format: 'cjs', 40 - sourcemap: true, 41 - inlineDynamicImports: true, 42 - }, 43 - { 44 - file: 'dist/node/esm/index.mjs', 45 - format: 'es', 46 - sourcemap: true, 47 - inlineDynamicImports: true, 48 - }, 49 - ], 50 - }, 51 - { 52 - input: 'src/_module.ts', 53 - plugins: [dts()], 54 - output: { 55 - file: 'dist/types/index.d.ts', 56 - format: 'es', 57 - }, 58 - }, 59 - // CycleTLS build (Node-only) 60 - { 61 - input: 'src/_cycletls.ts', 62 - external: ['cycletls'], 63 - plugins: [ 64 - esbuild({ 65 - define: { 66 - PLATFORM_NODE: 'true', 67 - }, 68 - }), 69 - ], 70 - output: [ 71 - { 72 - file: 'dist/cycletls/cjs/index.cjs', 73 - format: 'cjs', 74 - sourcemap: true, 75 - }, 76 - { 77 - file: 'dist/cycletls/esm/index.mjs', 78 - format: 'es', 79 - sourcemap: true, 80 - }, 81 - ], 82 - }, 83 - { 84 - input: 'src/_cycletls.ts', 85 - external: ['cycletls'], 86 - plugins: [dts()], 87 - output: { 88 - file: 'dist/cycletls/index.d.ts', 89 - format: 'es', 90 - }, 91 - }, 92 - ];
-7
twitter-scraper/src/_cycletls.ts
··· 1 - /** 2 - * CycleTLS fetch wrapper for bypassing Cloudflare bot detection 3 - * 4 - * This is a separate entrypoint to avoid bundling cycletls in environments 5 - * where it cannot run (like browsers). Import from '@the-convocation/twitter-scraper/cycletls' 6 - */ 7 - export { cycleTLSFetch, cycleTLSExit } from './cycletls-fetch';
-58
twitter-scraper/src/_module.ts
··· 1 - export type { FetchTransformOptions } from './api'; 2 - export type { FetchParameters } from './api-types'; 3 - export type { 4 - TwitterUserAuthCredentials, 5 - TwitterUserAuthFlowInitRequest, 6 - TwitterUserAuthFlowSubtaskRequest, 7 - TwitterUserAuthFlowRequest, 8 - TwitterUserAuthFlowResponse, 9 - FlowSubtaskHandler, 10 - FlowSubtaskHandlerApi, 11 - FlowTokenResult, 12 - FlowTokenResultError, 13 - FlowTokenResultSuccess, 14 - } from './auth-user'; 15 - export type { 16 - DmInboxResponse, 17 - DmInbox, 18 - DmConversationResponse, 19 - DmConversationTimeline, 20 - DmConversation, 21 - DmStatus, 22 - DmParticipant, 23 - DmMessageEntry, 24 - DmMessage, 25 - DmMessageData, 26 - DmReaction, 27 - DmMessageEntities, 28 - DmMessageUrl, 29 - DmWelcomeMessage, 30 - DmInboxTimelines, 31 - DmTimelineState, 32 - } from './direct-messages'; 33 - export { 34 - ApiError, 35 - AuthenticationError, 36 - type TwitterApiErrorRaw, 37 - type TwitterApiErrorExtensions, 38 - type TwitterApiErrorPosition, 39 - type TwitterApiErrorTraceInfo, 40 - } from './errors'; 41 - export type { Profile } from './profile'; 42 - export { 43 - type RateLimitEvent, 44 - type RateLimitStrategy, 45 - WaitingRateLimitStrategy, 46 - ErrorRateLimitStrategy, 47 - } from './rate-limit'; 48 - export { Scraper, type ScraperOptions } from './scraper'; 49 - export { SearchMode } from './search'; 50 - export type { QueryProfilesResponse, QueryTweetsResponse } from './timeline-v1'; 51 - export type { 52 - Tweet, 53 - TweetQuery, 54 - Mention, 55 - Photo, 56 - PlaceRaw, 57 - Video, 58 - } from './tweets';
-179
twitter-scraper/src/api-data.ts
··· 1 - import stringify from 'json-stable-stringify'; 2 - 3 - /** 4 - * Examples of requests to API endpoints. These are parsed at runtime and used 5 - * as templates for requests to a particular endpoint. Please ensure these do 6 - * not contain any information that you do not want published to NPM. 7 - */ 8 - const endpoints = { 9 - UserTweets: 10 - 'https://x.com/i/api/graphql/oRJs8SLCRNRbQzuZG93_oA/UserTweets?variables=%7B%22userId%22%3A%221806359170830172162%22%2C%22count%22%3A20%2C%22includePromotedContent%22%3Atrue%2C%22withQuickPromoteEligibilityTweetFields%22%3Atrue%2C%22withVoice%22%3Atrue%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22payments_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Atrue%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Atrue%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_imagine_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_community_note_auto_translation_is_enabled%22%3Afalse%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D&fieldToggles=%7B%22withArticlePlainText%22%3Afalse%7D', 11 - UserTweetsAndReplies: 12 - 'https://x.com/i/api/graphql/Hk4KlJ-ONjlJsucqR55P7g/UserTweetsAndReplies?variables=%7B%22userId%22%3A%221806359170830172162%22%2C%22count%22%3A20%2C%22includePromotedContent%22%3Atrue%2C%22withCommunity%22%3Atrue%2C%22withVoice%22%3Atrue%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Afalse%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Afalse%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D&fieldToggles=%7B%22withArticlePlainText%22%3Afalse%7D', 13 - UserLikedTweets: 14 - 'https://x.com/i/api/graphql/XHTMjDbiTGLQ9cP1em-aqQ/Likes?variables=%7B%22userId%22%3A%222244196397%22%2C%22count%22%3A20%2C%22includePromotedContent%22%3Afalse%2C%22withClientEventToken%22%3Afalse%2C%22withBirdwatchNotes%22%3Afalse%2C%22withVoice%22%3Atrue%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Afalse%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Afalse%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D&fieldToggles=%7B%22withArticlePlainText%22%3Afalse%7D', 15 - UserByScreenName: 16 - 'https://api.x.com/graphql/-oaLodhGbbnzJBACb1kk2Q/UserByScreenName?variables=%7B%22screen_name%22%3A%22geminiapp%22%2C%22withGrokTranslatedBio%22%3Afalse%7D&features=%7B%22hidden_profile_subscriptions_enabled%22%3Atrue%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22subscriptions_verification_info_is_identity_verified_enabled%22%3Atrue%2C%22subscriptions_verification_info_verified_since_enabled%22%3Atrue%2C%22highlights_tweets_tab_ui_enabled%22%3Atrue%2C%22responsive_web_twitter_article_notes_tab_enabled%22%3Atrue%2C%22subscriptions_feature_can_gift_premium%22%3Atrue%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%7D&fieldToggles=%7B%22withPayments%22%3Afalse%2C%22withAuxiliaryUserLabels%22%3Atrue%7D', 17 - TweetDetail: 18 - 'https://x.com/i/api/graphql/YVyS4SfwYW7Uw5qwy0mQCA/TweetDetail?variables=%7B%22focalTweetId%22%3A%221985465713096794294%22%2C%22referrer%22%3A%22profile%22%2C%22with_rux_injections%22%3Afalse%2C%22rankingMode%22%3A%22Relevance%22%2C%22includePromotedContent%22%3Atrue%2C%22withCommunity%22%3Atrue%2C%22withQuickPromoteEligibilityTweetFields%22%3Atrue%2C%22withBirdwatchNotes%22%3Atrue%2C%22withVoice%22%3Atrue%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22payments_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Atrue%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Atrue%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_imagine_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_community_note_auto_translation_is_enabled%22%3Afalse%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D&fieldToggles=%7B%22withArticleRichContentState%22%3Atrue%2C%22withArticlePlainText%22%3Afalse%2C%22withGrokAnalyze%22%3Afalse%2C%22withDisallowedReplyControls%22%3Afalse%7D', 19 - TweetResultByRestId: 20 - 'https://api.x.com/graphql/tCVRZ3WCvoj0BVO7BKnL-Q/TweetResultByRestId?variables=%7B%22tweetId%22%3A%221985465713096794294%22%2C%22withCommunity%22%3Afalse%2C%22includePromotedContent%22%3Afalse%2C%22withVoice%22%3Afalse%7D&features=%7B%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Afalse%2C%22responsive_web_jetfuel_frame%22%3Atrue%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Afalse%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22payments_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_imagine_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_community_note_auto_translation_is_enabled%22%3Afalse%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D&fieldToggles=%7B%22withArticleRichContentState%22%3Atrue%2C%22withArticlePlainText%22%3Afalse%2C%22withGrokAnalyze%22%3Afalse%2C%22withDisallowedReplyControls%22%3Afalse%7D', 21 - ListTweets: 22 - 'https://x.com/i/api/graphql/S1Sm3_mNJwa-fnY9htcaAQ/ListLatestTweetsTimeline?variables=%7B%22listId%22%3A%221736495155002106192%22%2C%22count%22%3A20%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Afalse%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Afalse%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D', 23 - SearchTimeline: 24 - 'https://x.com/i/api/graphql/nK1dw4oV3k4w5TdtcAdSww/SearchTimeline?variables=%7B%22rawQuery%22%3A%22twitter%22%2C%22count%22%3A20%2C%22querySource%22%3A%22typed_query%22%2C%22product%22%3A%22Top%22%2C%22withGrokTranslatedBio%22%3Afalse%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Atrue%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Atrue%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_imagine_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_community_note_auto_translation_is_enabled%22%3Afalse%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%2C%22responsive_web_graphql_exclude_directive_enabled%22%3Atrue%2C%22tweetypie_unmention_optimization_enabled%22%3Atrue%2C%22responsive_web_media_download_video_enabled%22%3Afalse%2C%22rweb_lists_timeline_redesign_enabled%22%3Atrue%7D', 25 - Followers: 26 - 'https://x.com/i/api/graphql/SCu9fVIlCUm-BM8-tL5pkQ/Followers?variables=%7B%22userId%22%3A%221806359170830172162%22%2C%22count%22%3A20%2C%22includePromotedContent%22%3Afalse%2C%22withGrokTranslatedBio%22%3Afalse%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Atrue%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Atrue%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_imagine_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_community_note_auto_translation_is_enabled%22%3Afalse%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D', 27 - Following: 28 - 'https://x.com/i/api/graphql/S5xUN9s2v4xk50KWGGvyvQ/Following?variables=%7B%22userId%22%3A%221806359170830172162%22%2C%22count%22%3A20%2C%22includePromotedContent%22%3Afalse%2C%22withGrokTranslatedBio%22%3Afalse%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Atrue%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Atrue%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_imagine_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_community_note_auto_translation_is_enabled%22%3Afalse%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D', 29 - } as const; 30 - 31 - export interface EndpointFieldInfo { 32 - /** 33 - * Request variables, used for providing arguments such as user IDs or result counts. 34 - */ 35 - variables: Record<string, unknown>; 36 - 37 - /** 38 - * Request features, used for encoding feature flags into the request. These may either be 39 - * boolean values or numerically-encoded booleans (1 or 0). It is possible this may change 40 - * to include other representations of booleans as Twitter's backend evolves. 41 - */ 42 - features: Record<string, unknown>; 43 - 44 - /** 45 - * Request field toggles, used for limiting how returned fields are represented. This is 46 - * rarely used. 47 - */ 48 - fieldToggles: Record<string, unknown>; 49 - } 50 - 51 - type SomePartial<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>; 52 - 53 - type EndpointVersion = string; 54 - type EndpointName = string; 55 - type EncodedVariables = string; 56 - type EncodedFeatures = string; 57 - type EncodedFieldToggles = string; 58 - 59 - // TODO: Set up field-level Intellisense for the QraphQL parameters in these? 60 - type BaseUrl = 61 - | 'https://twitter.com/i/api/graphql' 62 - | 'https://x.com/i/api/graphql' 63 - | 'https://api.x.com/graphql'; 64 - type EndpointFields<EndpointUrl> = 65 - EndpointUrl extends `${BaseUrl}/${EndpointVersion}/${EndpointName}?variables=${EncodedVariables}&features=${EncodedFeatures}&fieldToggles=${EncodedFieldToggles}` 66 - ? EndpointFieldInfo 67 - : EndpointUrl extends `${BaseUrl}/${EndpointVersion}/${EndpointName}?variables=${EncodedVariables}&features=${EncodedFeatures}` 68 - ? SomePartial<EndpointFieldInfo, 'fieldToggles'> 69 - : EndpointUrl extends `${BaseUrl}/${EndpointVersion}/${EndpointName}?variables=${EncodedVariables}` 70 - ? SomePartial<EndpointFieldInfo, 'features' | 'fieldToggles'> 71 - : Partial<EndpointFieldInfo>; 72 - 73 - export type ApiRequestInfo<EndpointUrl> = EndpointFields<EndpointUrl> & { 74 - /** 75 - * The URL, without any GraphQL query parameters. 76 - */ 77 - url: string; 78 - 79 - /** 80 - * Converts the request back into a URL to be sent to the Twitter API. 81 - */ 82 - toRequestUrl(): string; 83 - }; 84 - 85 - /** Wrapper class for API request information. */ 86 - class ApiRequest<EndpointUrl> { 87 - url: string; 88 - variables?: Record<string, unknown> | undefined; 89 - features?: Record<string, unknown> | undefined; 90 - fieldToggles?: Record<string, unknown> | undefined; 91 - 92 - constructor(info: Omit<ApiRequestInfo<EndpointUrl>, 'toRequestUrl'>) { 93 - this.url = info.url; 94 - this.variables = info.variables; 95 - this.features = info.features; 96 - this.fieldToggles = info.fieldToggles; 97 - } 98 - 99 - toRequestUrl(): string { 100 - const params = new URLSearchParams(); 101 - 102 - // Only include query parameters with values 103 - if (this.variables) { 104 - // Stringify with the query keys in sorted order like the Go package 105 - const variablesStr = stringify(this.variables); 106 - if (variablesStr) params.set('variables', variablesStr); 107 - } 108 - 109 - if (this.features) { 110 - const featuresStr = stringify(this.features); 111 - if (featuresStr) params.set('features', featuresStr); 112 - } 113 - 114 - if (this.fieldToggles) { 115 - const fieldTogglesStr = stringify(this.fieldToggles); 116 - if (fieldTogglesStr) params.set('fieldToggles', fieldTogglesStr); 117 - } 118 - 119 - return `${this.url}?${params.toString()}`; 120 - } 121 - } 122 - 123 - /** 124 - * Parses information from a Twitter API endpoint using an example request 125 - * URL against that endpoint. This can be used to extract GraphQL parameters 126 - * in order to easily reuse and/or override them later. 127 - * @param example An example of the endpoint to analyze. 128 - * @returns The parsed endpoint information. 129 - */ 130 - function parseEndpointExample< 131 - Endpoints, 132 - Endpoint extends string & keyof Endpoints, 133 - >(example: Endpoint): ApiRequestInfo<Endpoints[Endpoint]> { 134 - const { protocol, host, pathname, searchParams: query } = new URL(example); 135 - 136 - const base = `${protocol}//${host}${pathname}`; 137 - const variables = query.get('variables'); 138 - const features = query.get('features'); 139 - const fieldToggles = query.get('fieldToggles'); 140 - 141 - return new ApiRequest<Endpoints[Endpoint]>({ 142 - url: base, 143 - variables: variables ? JSON.parse(variables) : undefined, 144 - features: features ? JSON.parse(features) : undefined, 145 - fieldToggles: fieldToggles ? JSON.parse(fieldToggles) : undefined, 146 - } as Omit< 147 - ApiRequestInfo<Endpoints[Endpoint]>, 148 - 'toRequestUrl' 149 - >) as ApiRequestInfo<Endpoints[Endpoint]>; 150 - } 151 - 152 - type ApiRequestFactory<Endpoints> = { 153 - [Endpoint in keyof Endpoints as `create${string & 154 - Endpoint}Request`]: () => ApiRequestInfo<Endpoints[Endpoint]>; 155 - }; 156 - 157 - function createApiRequestFactory<Endpoints extends Record<string, string>>( 158 - endpoints: Endpoints, 159 - ): ApiRequestFactory<Endpoints> { 160 - type UntypedApiRequestFactory = ApiRequestFactory<Record<string, string>>; 161 - 162 - return Object.entries(endpoints) 163 - .map<UntypedApiRequestFactory>(([endpointName, endpointExample]) => { 164 - // Create a partial factory for only one endpoint 165 - return { 166 - [`create${endpointName}Request`]: () => { 167 - // Create a new instance on each invocation so that we can safely 168 - // mutate requests before sending them off 169 - return parseEndpointExample<Endpoints, any>(endpointExample); 170 - }, 171 - }; 172 - }) 173 - .reduce((agg, next) => { 174 - // Merge all of our factories into one that includes every endpoint 175 - return Object.assign(agg, next); 176 - }) as ApiRequestFactory<Endpoints>; 177 - } 178 - 179 - export const apiRequestFactory = createApiRequestFactory(endpoints);
-3
twitter-scraper/src/api-types.ts
··· 1 - // For some reason using Parameters<typeof fetch> reduces the request transform function to 2 - // `(url: string) => string` in tests. 3 - export type FetchParameters = [input: RequestInfo | URL, init?: RequestInit];
-222
twitter-scraper/src/api.ts
··· 1 - import { FetchParameters } from './api-types'; 2 - import { TwitterAuth, TwitterGuestAuth } from './auth'; 3 - import { ApiError } from './errors'; 4 - import { Platform, PlatformExtensions } from './platform'; 5 - import { updateCookieJar } from './requests'; 6 - import { Headers } from 'headers-polyfill'; 7 - import debug from 'debug'; 8 - import { generateTransactionId } from './xctxid'; 9 - 10 - const log = debug('twitter-scraper:api'); 11 - 12 - export interface FetchTransformOptions { 13 - /** 14 - * Transforms the request options before a request is made. This executes after all of the default 15 - * parameters have been configured, and is stateless. It is safe to return new request options 16 - * objects. 17 - * @param args The request options. 18 - * @returns The transformed request options. 19 - */ 20 - request: ( 21 - ...args: FetchParameters 22 - ) => FetchParameters | Promise<FetchParameters>; 23 - 24 - /** 25 - * Transforms the response after a request completes. This executes immediately after the request 26 - * completes, and is stateless. It is safe to return a new response object. 27 - * @param response The response object. 28 - * @returns The transformed response object. 29 - */ 30 - response: (response: Response) => Response | Promise<Response>; 31 - } 32 - 33 - export const bearerToken = 34 - 'AAAAAAAAAAAAAAAAAAAAAFQODgEAAAAAVHTp76lzh3rFzcHbmHVvQxYYpTw%3DckAlMINMjmCwxUcaXbAN4XqJVdgMJaHqNOFgPMK0zN1qLqLQCF'; 35 - 36 - export const bearerToken2 = 37 - 'AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA'; 38 - 39 - export async function jitter(maxMs: number): Promise<void> { 40 - const jitter = Math.random() * maxMs; 41 - await new Promise((resolve) => setTimeout(resolve, jitter)); 42 - } 43 - 44 - /** 45 - * An API result container. 46 - */ 47 - export type RequestApiResult<T> = 48 - | { success: true; value: T } 49 - | { success: false; err: Error }; 50 - 51 - /** 52 - * Used internally to send HTTP requests to the Twitter API. 53 - * @internal 54 - * @param url - The URL to send the request to. 55 - * @param auth - The instance of {@link TwitterAuth} that will be used to authorize this request. 56 - * @param method - The HTTP method used when sending this request. 57 - * @param platform - The platform extensions to use. 58 - * @param headers - The headers to include in the request. 59 - * @param bearerTokenOverride - Optional bearer token to use instead of the default one. 60 - */ 61 - export async function requestApi<T>( 62 - url: string, 63 - auth: TwitterAuth, 64 - method: 'GET' | 'POST' = 'GET', 65 - platform: PlatformExtensions = new Platform(), 66 - headers: Headers = new Headers(), 67 - bearerTokenOverride?: string, 68 - ): Promise<RequestApiResult<T>> { 69 - log(`Making ${method} request to ${url}`); 70 - 71 - await auth.installTo(headers, url, bearerTokenOverride); 72 - await platform.randomizeCiphers(); 73 - 74 - if ( 75 - auth instanceof TwitterGuestAuth && 76 - auth.options?.experimental?.xClientTransactionId 77 - ) { 78 - const transactionId = await generateTransactionId( 79 - url, 80 - auth.fetch.bind(auth), 81 - method, 82 - ); 83 - headers.set('x-client-transaction-id', transactionId); 84 - } 85 - 86 - let res: Response; 87 - do { 88 - const fetchParameters: FetchParameters = [ 89 - url, 90 - { 91 - method, 92 - headers, 93 - credentials: 'include', 94 - }, 95 - ]; 96 - 97 - try { 98 - res = await auth.fetch(...fetchParameters); 99 - } catch (err) { 100 - if (!(err instanceof Error)) { 101 - throw err; 102 - } 103 - 104 - return { 105 - success: false, 106 - err: new Error('Failed to perform request.'), 107 - }; 108 - } 109 - 110 - await updateCookieJar(auth.cookieJar(), res.headers); 111 - 112 - if (res.status === 429) { 113 - log('Rate limit hit, waiting for retry...'); 114 - await auth.onRateLimit({ 115 - fetchParameters: fetchParameters, 116 - response: res, 117 - }); 118 - } 119 - } while (res.status === 429); 120 - 121 - if (!res.ok) { 122 - return { 123 - success: false, 124 - err: await ApiError.fromResponse(res), 125 - }; 126 - } 127 - 128 - const value: T = await flexParseJson(res); 129 - if (res.headers.get('x-rate-limit-incoming') == '0') { 130 - auth.deleteToken(); 131 - return { success: true, value }; 132 - } else { 133 - return { success: true, value }; 134 - } 135 - } 136 - 137 - export async function flexParseJson<T>(res: Response): Promise<T> { 138 - try { 139 - return await res.json(); 140 - } catch { 141 - log('Failed to parse response as JSON, trying text parse...'); 142 - const text = await res.text(); 143 - log('Response text:', text); 144 - return JSON.parse(text); 145 - } 146 - } 147 - 148 - /** @internal */ 149 - export function addApiFeatures(o: object) { 150 - return { 151 - ...o, 152 - rweb_lists_timeline_redesign_enabled: true, 153 - responsive_web_graphql_exclude_directive_enabled: true, 154 - verified_phone_label_enabled: false, 155 - creator_subscriptions_tweet_preview_api_enabled: true, 156 - responsive_web_graphql_timeline_navigation_enabled: true, 157 - responsive_web_graphql_skip_user_profile_image_extensions_enabled: false, 158 - tweetypie_unmention_optimization_enabled: true, 159 - responsive_web_edit_tweet_api_enabled: true, 160 - graphql_is_translatable_rweb_tweet_is_translatable_enabled: true, 161 - view_counts_everywhere_api_enabled: true, 162 - longform_notetweets_consumption_enabled: true, 163 - tweet_awards_web_tipping_enabled: false, 164 - freedom_of_speech_not_reach_fetch_enabled: true, 165 - standardized_nudges_misinfo: true, 166 - longform_notetweets_rich_text_read_enabled: true, 167 - responsive_web_enhance_cards_enabled: false, 168 - subscriptions_verification_info_enabled: true, 169 - subscriptions_verification_info_reason_enabled: true, 170 - subscriptions_verification_info_verified_since_enabled: true, 171 - super_follow_badge_privacy_enabled: false, 172 - super_follow_exclusive_tweet_notifications_enabled: false, 173 - super_follow_tweet_api_enabled: false, 174 - super_follow_user_api_enabled: false, 175 - android_graphql_skip_api_media_color_palette: false, 176 - creator_subscriptions_subscription_count_enabled: false, 177 - blue_business_profile_image_shape_enabled: false, 178 - unified_cards_ad_metadata_container_dynamic_card_content_query_enabled: 179 - false, 180 - }; 181 - } 182 - 183 - export function addApiParams( 184 - params: URLSearchParams, 185 - includeTweetReplies: boolean, 186 - ): URLSearchParams { 187 - params.set('include_profile_interstitial_type', '1'); 188 - params.set('include_blocking', '1'); 189 - params.set('include_blocked_by', '1'); 190 - params.set('include_followed_by', '1'); 191 - params.set('include_want_retweets', '1'); 192 - params.set('include_mute_edge', '1'); 193 - params.set('include_can_dm', '1'); 194 - params.set('include_can_media_tag', '1'); 195 - params.set('include_ext_has_nft_avatar', '1'); 196 - params.set('include_ext_is_blue_verified', '1'); 197 - params.set('include_ext_verified_type', '1'); 198 - params.set('skip_status', '1'); 199 - params.set('cards_platform', 'Web-12'); 200 - params.set('include_cards', '1'); 201 - params.set('include_ext_alt_text', 'true'); 202 - params.set('include_ext_limited_action_results', 'false'); 203 - params.set('include_quote_count', 'true'); 204 - params.set('include_reply_count', '1'); 205 - params.set('tweet_mode', 'extended'); 206 - params.set('include_ext_collab_control', 'true'); 207 - params.set('include_ext_views', 'true'); 208 - params.set('include_entities', 'true'); 209 - params.set('include_user_entities', 'true'); 210 - params.set('include_ext_media_color', 'true'); 211 - params.set('include_ext_media_availability', 'true'); 212 - params.set('include_ext_sensitive_media_warning', 'true'); 213 - params.set('include_ext_trusted_friends_metadata', 'true'); 214 - params.set('send_error_codes', 'true'); 215 - params.set('simple_quoted_tweet', 'true'); 216 - params.set('include_tweet_replies', `${includeTweetReplies}`); 217 - params.set( 218 - 'ext', 219 - 'mediaStats,highlightedLabel,hasNftAvatar,voiceInfo,birdwatchPivot,enrichments,superFollowMetadata,unmentionInfo,editControl,collab_control,vibe', 220 - ); 221 - return params; 222 - }
-397
twitter-scraper/src/auth-user.test.ts
··· 1 - import { TwitterUserAuth } from './auth-user'; 2 - import { bearerToken } from './api'; 3 - import { jest } from '@jest/globals'; 4 - 5 - describe('TwitterUserAuth', () => { 6 - const mockFetch = jest.fn<typeof fetch>(); 7 - let auth: TwitterUserAuth; 8 - 9 - // Common login flows 10 - const loginFlows = { 11 - standard: [ 12 - 'LoginJsInstrumentationSubtask', 13 - 'LoginEnterUserIdentifierSSO', 14 - 'LoginEnterPassword', 15 - 'LoginSuccessSubtask', 16 - ], 17 - twoFactor: [ 18 - 'LoginJsInstrumentationSubtask', 19 - 'LoginEnterUserIdentifierSSO', 20 - 'LoginEnterPassword', 21 - 'LoginTwoFactorAuthChallenge', 22 - 'LoginSuccessSubtask', 23 - ], 24 - }; 25 - 26 - // Common mock responses 27 - const mockResponses = { 28 - xcomHomepage: { 29 - ok: true, 30 - status: 200, 31 - text: () => 32 - Promise.resolve( 33 - '<!DOCTYPE html><html><head></head><body><input type="hidden" name="authenticity_token" value="test_token" /></body></html>', 34 - ), 35 - headers: new Headers(), 36 - } as Response, 37 - guestToken: { 38 - ok: true, 39 - json: () => Promise.resolve({ guest_token: 'test-guest-token' }), 40 - text: () => 41 - Promise.resolve(JSON.stringify({ guest_token: 'test-guest-token' })), 42 - headers: new Headers(), 43 - } as Response, 44 - success: (token: string): Response => 45 - ({ 46 - ok: true, 47 - json: () => Promise.resolve({ flow_token: token }), 48 - text: () => Promise.resolve(JSON.stringify({ flow_token: token })), 49 - headers: new Headers(), 50 - } as Response), 51 - subtask: (token: string, subtaskId: string): Response => 52 - ({ 53 - ok: true, 54 - json: () => 55 - Promise.resolve({ 56 - flow_token: token, 57 - subtasks: [{ subtask_id: subtaskId }], 58 - }), 59 - text: () => 60 - Promise.resolve( 61 - JSON.stringify({ 62 - flow_token: token, 63 - subtasks: [{ subtask_id: subtaskId }], 64 - }), 65 - ), 66 - headers: new Headers(), 67 - } as Response), 68 - error: (code: number, message: string): Response => 69 - ({ 70 - ok: true, 71 - json: () => 72 - Promise.resolve({ 73 - flow_token: 'error-token', 74 - errors: [{ code, message }], 75 - }), 76 - text: () => 77 - Promise.resolve( 78 - JSON.stringify({ 79 - flow_token: 'error-token', 80 - errors: [{ code, message }], 81 - }), 82 - ), 83 - headers: new Headers(), 84 - } as Response), 85 - httpError: ( 86 - status: number, 87 - statusText: string, 88 - message: string, 89 - ): Response => 90 - ({ 91 - ok: false, 92 - status, 93 - statusText, 94 - headers: new Headers(), 95 - text: () => Promise.resolve(message), 96 - json: () => Promise.resolve({ errors: [{ code: status, message }] }), 97 - } as Response), 98 - }; 99 - 100 - // Test utilities 101 - const setupAuth = () => { 102 - mockFetch.mockReset(); 103 - return new TwitterUserAuth(bearerToken, { 104 - fetch: mockFetch, 105 - transform: {}, 106 - rateLimitStrategy: { 107 - onRateLimit: async () => { 108 - throw new Error('Rate limit hit'); 109 - }, 110 - }, 111 - }); 112 - }; 113 - 114 - const mockLoginFlow = (subtasks: string[]) => { 115 - // Guest token fetch 116 - mockFetch.mockResolvedValueOnce(mockResponses.guestToken); 117 - 118 - // initLogin: task endpoint returns first subtask 119 - mockFetch.mockResolvedValueOnce( 120 - mockResponses.subtask('token1', subtasks[0]), 121 - ); 122 - 123 - // Each subsequent subtask handler: task endpoint 124 - for (let i = 1; i < subtasks.length; i++) { 125 - mockFetch.mockResolvedValueOnce( 126 - mockResponses.subtask(`token${i + 1}`, subtasks[i]), 127 - ); 128 - } 129 - }; 130 - 131 - const setupAuthenticatedState = async () => { 132 - // Use a minimal login flow that goes straight to success 133 - mockFetch 134 - .mockResolvedValueOnce(mockResponses.guestToken) 135 - .mockResolvedValueOnce( 136 - mockResponses.subtask('token1', 'LoginSuccessSubtask'), 137 - ); 138 - 139 - await auth.login('testuser', 'testpass'); 140 - mockFetch.mockClear(); 141 - }; 142 - 143 - beforeEach(() => { 144 - auth = setupAuth(); 145 - }); 146 - 147 - describe('login', () => { 148 - it('should handle successful login flow', async () => { 149 - mockLoginFlow(loginFlows.standard); 150 - await auth.login('testuser', 'testpass'); 151 - 152 - // Guest token + 4 subtask calls = 5 total 153 - expect(mockFetch).toHaveBeenCalledTimes(5); 154 - expect(mockFetch.mock.calls[0][0]).toBe( 155 - 'https://api.x.com/1.1/guest/activate.json', 156 - ); 157 - expect(mockFetch.mock.calls[1][0]).toBe( 158 - 'https://api.x.com/1.1/onboarding/task.json?flow_name=login', 159 - ); 160 - }); 161 - 162 - it('should handle login failure', async () => { 163 - mockFetch 164 - .mockResolvedValueOnce(mockResponses.guestToken) 165 - .mockResolvedValueOnce(mockResponses.error(99, 'Invalid credentials')); 166 - 167 - await expect(auth.login('testuser', 'wrongpass')).rejects.toThrow( 168 - 'Authentication error (99): Invalid credentials', 169 - ); 170 - }); 171 - 172 - it('should handle DenyLoginSubtask flow', async () => { 173 - mockFetch 174 - .mockResolvedValueOnce(mockResponses.guestToken) 175 - .mockResolvedValueOnce( 176 - mockResponses.subtask('token1', 'DenyLoginSubtask'), 177 - ); 178 - 179 - await expect(auth.login('testuser', 'wrongpass')).rejects.toThrow( 180 - 'Authentication error: DenyLoginSubtask', 181 - ); 182 - }); 183 - 184 - it('should handle 2FA challenge', async () => { 185 - mockLoginFlow(loginFlows.twoFactor); 186 - await auth.login('testuser', 'testpass', undefined, 'JBSWY3DPEHPK3PXP'); 187 - // Guest token + 5 subtask calls = 6 total 188 - expect(mockFetch).toHaveBeenCalledTimes(6); 189 - }); 190 - 191 - it('should retry 2FA challenge after failure', async () => { 192 - mockFetch 193 - .mockResolvedValueOnce(mockResponses.guestToken) 194 - // initLogin 195 - .mockResolvedValueOnce( 196 - mockResponses.subtask('token1', 'LoginTwoFactorAuthChallenge'), 197 - ) 198 - // First 2FA attempt fails - returns same subtask 199 - .mockResolvedValueOnce( 200 - mockResponses.subtask('token2', 'LoginTwoFactorAuthChallenge'), 201 - ) 202 - // Second 2FA attempt succeeds 203 - .mockResolvedValueOnce( 204 - mockResponses.subtask('token3', 'LoginSuccessSubtask'), 205 - ); 206 - 207 - await auth.login('testuser', 'testpass', undefined, 'JBSWY3DPEHPK3PXP'); 208 - expect(mockFetch).toHaveBeenCalledTimes(4); 209 - }); 210 - 211 - it('should handle all 2FA attempts failing', async () => { 212 - mockFetch 213 - .mockResolvedValueOnce(mockResponses.guestToken) 214 - // initLogin returns 2FA challenge 215 - .mockResolvedValueOnce( 216 - mockResponses.subtask('token1', 'LoginTwoFactorAuthChallenge'), 217 - ) 218 - // First 2FA attempt fails 219 - .mockResolvedValueOnce(mockResponses.error(236, 'Bad 2FA code')) 220 - // Second 2FA attempt fails 221 - .mockResolvedValueOnce(mockResponses.error(236, 'Bad 2FA code')) 222 - // Third 2FA attempt fails 223 - .mockResolvedValueOnce(mockResponses.error(236, 'Bad 2FA code')); 224 - 225 - await expect( 226 - auth.login('testuser', 'testpass', undefined, 'JBSWY3DPEHPK3PXP'), 227 - ).rejects.toThrow('Bad 2FA code'); 228 - }); 229 - 230 - it('should handle missing TOTP secret during 2FA challenge', async () => { 231 - mockFetch 232 - .mockResolvedValueOnce(mockResponses.guestToken) 233 - // initLogin returns 2FA challenge 234 - .mockResolvedValueOnce( 235 - mockResponses.subtask('token1', 'LoginTwoFactorAuthChallenge'), 236 - ); 237 - 238 - await expect(auth.login('testuser', 'testpass')).rejects.toThrow( 239 - 'Two-factor authentication is required but no secret was provided', 240 - ); 241 - }); 242 - 243 - it('should handle invalid TOTP secret during 2FA challenge', async () => { 244 - mockFetch 245 - .mockResolvedValueOnce(mockResponses.guestToken) 246 - // initLogin returns 2FA challenge 247 - .mockResolvedValueOnce( 248 - mockResponses.subtask('token1', 'LoginTwoFactorAuthChallenge'), 249 - ); 250 - 251 - await expect( 252 - auth.login('testuser', 'testpass', undefined, 'INVALID_SECRET'), 253 - ).rejects.toThrow(); 254 - }); 255 - 256 - it('should handle invalid subtask type', async () => { 257 - mockFetch 258 - .mockResolvedValueOnce(mockResponses.guestToken) 259 - .mockResolvedValueOnce( 260 - mockResponses.subtask('token1', 'UnknownSubtask'), 261 - ); 262 - 263 - await expect(auth.login('testuser', 'testpass')).rejects.toThrow( 264 - 'Unknown subtask UnknownSubtask', 265 - ); 266 - }); 267 - 268 - it('should handle network errors', async () => { 269 - mockFetch 270 - .mockResolvedValueOnce(mockResponses.guestToken) 271 - // initLogin fails on task endpoint 272 - .mockRejectedValueOnce(new Error('Network error')); 273 - 274 - await expect(auth.login('testuser', 'testpass')).rejects.toThrow( 275 - 'Network error', 276 - ); 277 - }); 278 - 279 - it('should handle invalid response format', async () => { 280 - mockFetch 281 - .mockResolvedValueOnce(mockResponses.guestToken) 282 - .mockResolvedValueOnce({ 283 - ok: true, 284 - json: () => Promise.resolve({}), 285 - text: () => Promise.resolve('{}'), 286 - headers: new Headers(), 287 - } as Response); 288 - 289 - await expect(auth.login('testuser', 'testpass')).rejects.toThrow(); 290 - }); 291 - 292 - it('should handle rate limit errors', async () => { 293 - mockFetch 294 - .mockResolvedValueOnce(mockResponses.guestToken) 295 - // initLogin gets rate limited 296 - .mockResolvedValueOnce( 297 - mockResponses.httpError(429, 'Too Many Requests', 'Rate limit hit'), 298 - ); 299 - 300 - await expect(auth.login('testuser', 'testpass')).rejects.toThrow( 301 - 'Rate limit hit', 302 - ); 303 - }); 304 - 305 - it('should handle unauthorized errors', async () => { 306 - mockFetch 307 - .mockResolvedValueOnce(mockResponses.guestToken) 308 - // initLogin gets 401 error 309 - .mockResolvedValueOnce( 310 - mockResponses.httpError( 311 - 401, 312 - 'Unauthorized', 313 - 'Could not authenticate you', 314 - ), 315 - ); 316 - 317 - await expect(auth.login('testuser', 'testpass')).rejects.toThrow( 318 - 'Could not authenticate you', 319 - ); 320 - }); 321 - }); 322 - 323 - describe('logout', () => { 324 - it('should handle successful logout', async () => { 325 - await setupAuthenticatedState(); 326 - mockFetch.mockResolvedValueOnce(mockResponses.success('logout')); 327 - 328 - await auth.logout(); 329 - 330 - expect(mockFetch).toHaveBeenCalledWith( 331 - 'https://api.x.com/1.1/account/logout.json', 332 - expect.objectContaining({ 333 - method: 'POST', 334 - }), 335 - ); 336 - 337 - expect(auth.hasToken()).toBe(false); 338 - expect(await auth.cookieJar().getCookies('https://x.com')).toHaveLength( 339 - 0, 340 - ); 341 - }); 342 - 343 - it('should clear state on network error during logout', async () => { 344 - mockFetch.mockRejectedValueOnce(new Error('Network error')); 345 - await auth.logout(); 346 - 347 - expect(auth.hasToken()).toBe(false); 348 - expect(await auth.cookieJar().getCookies('https://x.com')).toHaveLength( 349 - 0, 350 - ); 351 - }); 352 - 353 - it('should clear state on failed logout', async () => { 354 - mockFetch.mockResolvedValueOnce( 355 - mockResponses.httpError(400, 'Bad Request', 'User not found'), 356 - ); 357 - 358 - await auth.logout(); 359 - 360 - expect(auth.hasToken()).toBe(false); 361 - expect(await auth.cookieJar().getCookies('https://x.com')).toHaveLength( 362 - 0, 363 - ); 364 - }); 365 - }); 366 - 367 - describe('isLoggedIn', () => { 368 - it('should return true when ct0 cookie is present', async () => { 369 - // Set up a ct0 cookie in the jar 370 - await auth.cookieJar().setCookie('ct0=test_token', 'https://x.com'); 371 - const result = await auth.isLoggedIn(); 372 - expect(result).toBe(true); 373 - }); 374 - 375 - it('should return false when ct0 cookie is not present', async () => { 376 - const result = await auth.isLoggedIn(); 377 - expect(result).toBe(false); 378 - }); 379 - 380 - it('should return false after logout', async () => { 381 - // Set up authenticated state with login 382 - await setupAuthenticatedState(); 383 - 384 - // Manually set ct0 cookie to ensure isLoggedIn returns true 385 - await auth.cookieJar().setCookie('ct0=test_token', 'https://x.com'); 386 - expect(await auth.isLoggedIn()).toBe(true); 387 - 388 - // Logout should clear cookies 389 - mockFetch.mockResolvedValueOnce(mockResponses.success('logout')); 390 - await auth.logout(); 391 - 392 - // Now should be logged out 393 - const result = await auth.isLoggedIn(); 394 - expect(result).toBe(false); 395 - }); 396 - }); 397 - });
-706
twitter-scraper/src/auth-user.ts
··· 1 - import { TwitterAuthOptions, TwitterGuestAuth } from './auth'; 2 - import { flexParseJson, requestApi } from './api'; 3 - import { CookieJar } from 'tough-cookie'; 4 - import { updateCookieJar } from './requests'; 5 - import { Headers } from 'headers-polyfill'; 6 - import { TwitterApiErrorRaw, AuthenticationError, ApiError } from './errors'; 7 - import { Type, type Static } from '@sinclair/typebox'; 8 - import { Check } from '@sinclair/typebox/value'; 9 - import * as OTPAuth from 'otpauth'; 10 - import { FetchParameters } from './api-types'; 11 - import debug from 'debug'; 12 - import { generateXPFFHeader } from './xpff'; 13 - import { generateTransactionId } from './xctxid'; 14 - 15 - const log = debug('twitter-scraper:auth-user'); 16 - 17 - export interface TwitterUserAuthFlowInitRequest { 18 - flow_name: string; 19 - input_flow_data: Record<string, unknown>; 20 - subtask_versions: Record<string, number>; 21 - } 22 - 23 - export interface TwitterUserAuthFlowSubtaskRequest { 24 - flow_token: string; 25 - subtask_inputs: ({ 26 - subtask_id: string; 27 - } & Record<string, unknown>)[]; 28 - } 29 - 30 - export type TwitterUserAuthFlowRequest = 31 - | TwitterUserAuthFlowInitRequest 32 - | TwitterUserAuthFlowSubtaskRequest; 33 - 34 - export interface TwitterUserAuthFlowResponse { 35 - errors?: TwitterApiErrorRaw[]; 36 - flow_token?: string; 37 - status?: string; 38 - subtasks?: TwitterUserAuthSubtask[]; 39 - } 40 - 41 - interface TwitterUserAuthVerifyCredentials { 42 - errors?: TwitterApiErrorRaw[]; 43 - } 44 - 45 - const TwitterUserAuthSubtask = Type.Object({ 46 - subtask_id: Type.String(), 47 - enter_text: Type.Optional(Type.Object({})), 48 - }); 49 - type TwitterUserAuthSubtask = Static<typeof TwitterUserAuthSubtask>; 50 - 51 - export type FlowTokenResultSuccess = { 52 - status: 'success'; 53 - response: TwitterUserAuthFlowResponse; 54 - }; 55 - 56 - export type FlowTokenResultError = { 57 - status: 'error'; 58 - err: Error; 59 - }; 60 - 61 - export type FlowTokenResult = FlowTokenResultSuccess | FlowTokenResultError; 62 - 63 - export interface TwitterUserAuthCredentials { 64 - username: string; 65 - password: string; 66 - email?: string; 67 - twoFactorSecret?: string; 68 - } 69 - 70 - /** 71 - * The API interface provided to custom subtask handlers for interacting with the Twitter authentication flow. 72 - * This interface allows handlers to send flow requests and access the current flow token. 73 - * 74 - * The API is passed to each subtask handler and provides methods necessary for implementing 75 - * custom authentication subtasks. It abstracts away the low-level details of communicating 76 - * with Twitter's authentication API. 77 - * 78 - * @example 79 - * ```typescript 80 - * import { Scraper, FlowSubtaskHandler } from "@the-convocation/twitter-scraper"; 81 - * 82 - * // A custom subtask handler that implements a hypothetical example subtask 83 - * const exampleHandler: FlowSubtaskHandler = async (subtaskId, response, credentials, api) => { 84 - * // Process the example subtask somehow 85 - * const data = await processExampleTask(); 86 - * 87 - * // Submit the processed data using the provided API 88 - * return await api.sendFlowRequest({ 89 - * flow_token: api.getFlowToken(), 90 - * subtask_inputs: [{ 91 - * subtask_id: subtaskId, 92 - * example_data: { 93 - * value: data, 94 - * link: "next_link" 95 - * } 96 - * }] 97 - * }); 98 - * }; 99 - * 100 - * const scraper = new Scraper(); 101 - * scraper.registerAuthSubtaskHandler("ExampleSubtask", exampleHandler); 102 - * ``` 103 - */ 104 - export interface FlowSubtaskHandlerApi { 105 - /** 106 - * Send a flow request to the Twitter API. 107 - * @param request The request object containing flow token and subtask inputs 108 - * @returns The result of the flow task 109 - */ 110 - sendFlowRequest: ( 111 - request: TwitterUserAuthFlowRequest, 112 - ) => Promise<FlowTokenResult>; 113 - /** 114 - * Gets the current flow token. 115 - * @returns The current flow token 116 - */ 117 - getFlowToken: () => string; 118 - } 119 - 120 - /** 121 - * A handler function for processing Twitter authentication flow subtasks. 122 - * Library consumers can implement and register custom handlers for new or 123 - * existing subtask types using the Scraper.registerAuthSubtaskHandler method. 124 - * 125 - * Each subtask handler is called when its corresponding subtask ID is encountered 126 - * during the authentication flow. The handler receives the subtask ID, the previous 127 - * response data, the user's credentials, and an API interface for interacting with 128 - * the authentication flow. 129 - * 130 - * Handlers should process their specific subtask and return either a successful response 131 - * or an error. Success responses typically lead to the next subtask in the flow, while 132 - * errors will halt the authentication process. 133 - * 134 - * @param subtaskId - The identifier of the subtask being handled 135 - * @param previousResponse - The complete response from the previous authentication flow step 136 - * @param credentials - The user's authentication credentials including username, password, etc. 137 - * @param api - An interface providing methods to interact with the authentication flow 138 - * @returns A promise resolving to either a successful flow response or an error 139 - * 140 - * @example 141 - * ```typescript 142 - * import { Scraper, FlowSubtaskHandler } from "@the-convocation/twitter-scraper"; 143 - * 144 - * // Custom handler for a hypothetical verification subtask 145 - * const verificationHandler: FlowSubtaskHandler = async ( 146 - * subtaskId, 147 - * response, 148 - * credentials, 149 - * api 150 - * ) => { 151 - * // Extract the verification data from the response 152 - * const verificationData = response.subtasks?.[0].exampleData?.value; 153 - * if (!verificationData) { 154 - * return { 155 - * status: 'error', 156 - * err: new Error('No verification data found in response') 157 - * }; 158 - * } 159 - * 160 - * // Process the verification data somehow 161 - * const result = await processVerification(verificationData); 162 - * 163 - * // Submit the result using the flow API 164 - * return await api.sendFlowRequest({ 165 - * flow_token: api.getFlowToken(), 166 - * subtask_inputs: [{ 167 - * subtask_id: subtaskId, 168 - * example_verification: { 169 - * value: result, 170 - * link: "next_link" 171 - * } 172 - * }] 173 - * }); 174 - * }; 175 - * 176 - * const scraper = new Scraper(); 177 - * scraper.registerAuthSubtaskHandler("ExampleVerificationSubtask", verificationHandler); 178 - * 179 - * // Later, when logging in... 180 - * await scraper.login("username", "password"); 181 - * ``` 182 - */ 183 - export type FlowSubtaskHandler = ( 184 - subtaskId: string, 185 - previousResponse: TwitterUserAuthFlowResponse, 186 - credentials: TwitterUserAuthCredentials, 187 - api: FlowSubtaskHandlerApi, 188 - ) => Promise<FlowTokenResult>; 189 - 190 - /** 191 - * A user authentication token manager. 192 - */ 193 - export class TwitterUserAuth extends TwitterGuestAuth { 194 - private readonly subtaskHandlers: Map<string, FlowSubtaskHandler> = new Map(); 195 - 196 - constructor(bearerToken: string, options?: Partial<TwitterAuthOptions>) { 197 - super(bearerToken, options); 198 - this.initializeDefaultHandlers(); 199 - } 200 - 201 - /** 202 - * Register a custom subtask handler or override an existing one 203 - * @param subtaskId The ID of the subtask to handle 204 - * @param handler The handler function that processes the subtask 205 - */ 206 - registerSubtaskHandler(subtaskId: string, handler: FlowSubtaskHandler): void { 207 - this.subtaskHandlers.set(subtaskId, handler); 208 - } 209 - 210 - private initializeDefaultHandlers(): void { 211 - this.subtaskHandlers.set( 212 - 'LoginJsInstrumentationSubtask', 213 - this.handleJsInstrumentationSubtask.bind(this), 214 - ); 215 - this.subtaskHandlers.set( 216 - 'LoginEnterUserIdentifierSSO', 217 - this.handleEnterUserIdentifierSSO.bind(this), 218 - ); 219 - this.subtaskHandlers.set( 220 - 'LoginEnterAlternateIdentifierSubtask', 221 - this.handleEnterAlternateIdentifierSubtask.bind(this), 222 - ); 223 - this.subtaskHandlers.set( 224 - 'LoginEnterPassword', 225 - this.handleEnterPassword.bind(this), 226 - ); 227 - this.subtaskHandlers.set( 228 - 'AccountDuplicationCheck', 229 - this.handleAccountDuplicationCheck.bind(this), 230 - ); 231 - this.subtaskHandlers.set( 232 - 'LoginTwoFactorAuthChallenge', 233 - this.handleTwoFactorAuthChallenge.bind(this), 234 - ); 235 - this.subtaskHandlers.set('LoginAcid', this.handleAcid.bind(this)); 236 - this.subtaskHandlers.set( 237 - 'LoginSuccessSubtask', 238 - this.handleSuccessSubtask.bind(this), 239 - ); 240 - } 241 - 242 - async isLoggedIn(): Promise<boolean> { 243 - const cookie = await this.getCookieString(); 244 - return cookie.includes('ct0='); 245 - } 246 - 247 - async login( 248 - username: string, 249 - password: string, 250 - email?: string, 251 - twoFactorSecret?: string, 252 - ): Promise<void> { 253 - await this.updateGuestToken(); 254 - 255 - const credentials: TwitterUserAuthCredentials = { 256 - username, 257 - password, 258 - email, 259 - twoFactorSecret, 260 - }; 261 - 262 - let next: FlowTokenResult = await this.initLogin(); 263 - while (next.status === 'success' && next.response.subtasks?.length) { 264 - const flowToken = next.response.flow_token; 265 - if (flowToken == null) { 266 - // Should never happen 267 - throw new Error('flow_token not found.'); 268 - } 269 - 270 - const subtaskId = next.response.subtasks[0].subtask_id; 271 - const handler = this.subtaskHandlers.get(subtaskId); 272 - 273 - if (handler) { 274 - next = await handler(subtaskId, next.response, credentials, { 275 - sendFlowRequest: this.executeFlowTask.bind(this), 276 - getFlowToken: () => flowToken, 277 - }); 278 - } else { 279 - throw new Error(`Unknown subtask ${subtaskId}`); 280 - } 281 - } 282 - if (next.status === 'error') { 283 - throw next.err; 284 - } 285 - } 286 - 287 - async logout(): Promise<void> { 288 - if (!this.hasToken()) { 289 - return; 290 - } 291 - 292 - try { 293 - await requestApi<void>( 294 - 'https://api.x.com/1.1/account/logout.json', 295 - this, 296 - 'POST', 297 - ); 298 - } catch (error) { 299 - // Ignore errors during logout but still clean up state 300 - console.warn('Error during logout:', error); 301 - } finally { 302 - this.deleteToken(); 303 - this.jar = new CookieJar(); 304 - } 305 - } 306 - 307 - async installTo( 308 - headers: Headers, 309 - _url: string, 310 - bearerTokenOverride?: string, 311 - ): Promise<void> { 312 - // Use the override token if provided, otherwise use the instance's bearer token 313 - const tokenToUse = bearerTokenOverride ?? this.bearerToken; 314 - headers.set('authorization', `Bearer ${tokenToUse}`); 315 - headers.set( 316 - 'user-agent', 317 - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36', 318 - ); 319 - 320 - if (this.guestToken) { 321 - // Guest token is optional for authenticated users 322 - headers.set('x-guest-token', this.guestToken); 323 - } 324 - 325 - await this.installCsrfToken(headers); 326 - 327 - if (this.options?.experimental?.xpff) { 328 - const guestId = await this.guestId(); 329 - if (guestId != null) { 330 - const xpffHeader = await generateXPFFHeader(guestId); 331 - headers.set('x-xp-forwarded-for', xpffHeader); 332 - } 333 - } 334 - 335 - const cookie = await this.getCookieString(); 336 - headers.set('cookie', cookie); 337 - } 338 - 339 - private async initLogin(): Promise<FlowTokenResult> { 340 - // Reset certain session-related cookies because Twitter complains sometimes if we don't 341 - this.removeCookie('twitter_ads_id='); 342 - this.removeCookie('ads_prefs='); 343 - this.removeCookie('_twitter_sess='); 344 - this.removeCookie('zipbox_forms_auth_token='); 345 - this.removeCookie('lang='); 346 - this.removeCookie('bouncer_reset_cookie='); 347 - this.removeCookie('twid='); 348 - this.removeCookie('twitter_ads_idb='); 349 - this.removeCookie('email_uid='); 350 - this.removeCookie('external_referer='); 351 - this.removeCookie('ct0='); 352 - this.removeCookie('aa_u='); 353 - this.removeCookie('__cf_bm='); 354 - 355 - return await this.executeFlowTask({ 356 - flow_name: 'login', 357 - input_flow_data: { 358 - flow_context: { 359 - debug_overrides: {}, 360 - start_location: { 361 - location: 'unknown', 362 - }, 363 - }, 364 - }, 365 - subtask_versions: { 366 - action_list: 2, 367 - alert_dialog: 1, 368 - app_download_cta: 1, 369 - check_logged_in_account: 1, 370 - choice_selection: 3, 371 - contacts_live_sync_permission_prompt: 0, 372 - cta: 7, 373 - email_verification: 2, 374 - end_flow: 1, 375 - enter_date: 1, 376 - enter_email: 2, 377 - enter_password: 5, 378 - enter_phone: 2, 379 - enter_recaptcha: 1, 380 - enter_text: 5, 381 - enter_username: 2, 382 - generic_urt: 3, 383 - in_app_notification: 1, 384 - interest_picker: 3, 385 - js_instrumentation: 1, 386 - menu_dialog: 1, 387 - notifications_permission_prompt: 2, 388 - open_account: 2, 389 - open_home_timeline: 1, 390 - open_link: 1, 391 - phone_verification: 4, 392 - privacy_options: 1, 393 - security_key: 3, 394 - select_avatar: 4, 395 - select_banner: 2, 396 - settings_list: 7, 397 - show_code: 1, 398 - sign_up: 2, 399 - sign_up_review: 4, 400 - tweet_selection_urt: 1, 401 - update_users: 1, 402 - upload_media: 1, 403 - user_recommendations_list: 4, 404 - user_recommendations_urt: 1, 405 - wait_spinner: 3, 406 - web_modal: 1, 407 - }, 408 - }); 409 - } 410 - 411 - private async handleJsInstrumentationSubtask( 412 - subtaskId: string, 413 - _prev: TwitterUserAuthFlowResponse, 414 - _credentials: TwitterUserAuthCredentials, 415 - api: FlowSubtaskHandlerApi, 416 - ): Promise<FlowTokenResult> { 417 - return await api.sendFlowRequest({ 418 - flow_token: api.getFlowToken(), 419 - subtask_inputs: [ 420 - { 421 - subtask_id: subtaskId, 422 - js_instrumentation: { 423 - response: '{}', 424 - link: 'next_link', 425 - }, 426 - }, 427 - ], 428 - }); 429 - } 430 - 431 - private async handleEnterAlternateIdentifierSubtask( 432 - subtaskId: string, 433 - _prev: TwitterUserAuthFlowResponse, 434 - credentials: TwitterUserAuthCredentials, 435 - api: FlowSubtaskHandlerApi, 436 - ): Promise<FlowTokenResult> { 437 - return await this.executeFlowTask({ 438 - flow_token: api.getFlowToken(), 439 - subtask_inputs: [ 440 - { 441 - subtask_id: subtaskId, 442 - enter_text: { 443 - text: credentials.email, 444 - link: 'next_link', 445 - }, 446 - }, 447 - ], 448 - }); 449 - } 450 - 451 - private async handleEnterUserIdentifierSSO( 452 - subtaskId: string, 453 - _prev: TwitterUserAuthFlowResponse, 454 - credentials: TwitterUserAuthCredentials, 455 - api: FlowSubtaskHandlerApi, 456 - ): Promise<FlowTokenResult> { 457 - return await this.executeFlowTask({ 458 - flow_token: api.getFlowToken(), 459 - subtask_inputs: [ 460 - { 461 - subtask_id: subtaskId, 462 - settings_list: { 463 - setting_responses: [ 464 - { 465 - key: 'user_identifier', 466 - response_data: { 467 - text_data: { result: credentials.username }, 468 - }, 469 - }, 470 - ], 471 - link: 'next_link', 472 - }, 473 - }, 474 - ], 475 - }); 476 - } 477 - 478 - private async handleEnterPassword( 479 - subtaskId: string, 480 - _prev: TwitterUserAuthFlowResponse, 481 - credentials: TwitterUserAuthCredentials, 482 - api: FlowSubtaskHandlerApi, 483 - ): Promise<FlowTokenResult> { 484 - return await this.executeFlowTask({ 485 - flow_token: api.getFlowToken(), 486 - subtask_inputs: [ 487 - { 488 - subtask_id: subtaskId, 489 - enter_password: { 490 - password: credentials.password, 491 - link: 'next_link', 492 - }, 493 - }, 494 - ], 495 - }); 496 - } 497 - 498 - private async handleAccountDuplicationCheck( 499 - subtaskId: string, 500 - _prev: TwitterUserAuthFlowResponse, 501 - _credentials: TwitterUserAuthCredentials, 502 - api: FlowSubtaskHandlerApi, 503 - ): Promise<FlowTokenResult> { 504 - return await this.executeFlowTask({ 505 - flow_token: api.getFlowToken(), 506 - subtask_inputs: [ 507 - { 508 - subtask_id: subtaskId, 509 - check_logged_in_account: { 510 - link: 'AccountDuplicationCheck_false', 511 - }, 512 - }, 513 - ], 514 - }); 515 - } 516 - 517 - private async handleTwoFactorAuthChallenge( 518 - subtaskId: string, 519 - _prev: TwitterUserAuthFlowResponse, 520 - credentials: TwitterUserAuthCredentials, 521 - api: FlowSubtaskHandlerApi, 522 - ): Promise<FlowTokenResult> { 523 - if (!credentials.twoFactorSecret) { 524 - return { 525 - status: 'error', 526 - err: new AuthenticationError( 527 - 'Two-factor authentication is required but no secret was provided', 528 - ), 529 - }; 530 - } 531 - 532 - const totp = new OTPAuth.TOTP({ secret: credentials.twoFactorSecret }); 533 - let error; 534 - for (let attempts = 1; attempts < 4; attempts += 1) { 535 - try { 536 - return await api.sendFlowRequest({ 537 - flow_token: api.getFlowToken(), 538 - subtask_inputs: [ 539 - { 540 - subtask_id: subtaskId, 541 - enter_text: { 542 - link: 'next_link', 543 - text: totp.generate(), 544 - }, 545 - }, 546 - ], 547 - }); 548 - } catch (err) { 549 - error = err; 550 - await new Promise((resolve) => setTimeout(resolve, 2000 * attempts)); 551 - } 552 - } 553 - throw error; 554 - } 555 - 556 - private async handleAcid( 557 - subtaskId: string, 558 - _prev: TwitterUserAuthFlowResponse, 559 - credentials: TwitterUserAuthCredentials, 560 - api: FlowSubtaskHandlerApi, 561 - ): Promise<FlowTokenResult> { 562 - return await this.executeFlowTask({ 563 - flow_token: api.getFlowToken(), 564 - subtask_inputs: [ 565 - { 566 - subtask_id: subtaskId, 567 - enter_text: { 568 - text: credentials.email, 569 - link: 'next_link', 570 - }, 571 - }, 572 - ], 573 - }); 574 - } 575 - 576 - private async handleSuccessSubtask(): Promise<FlowTokenResult> { 577 - // Login completed successfully, nothing more to do 578 - log('Successfully logged in with user credentials.'); 579 - return { 580 - status: 'success', 581 - response: {}, 582 - }; 583 - } 584 - 585 - private async executeFlowTask( 586 - data: TwitterUserAuthFlowRequest, 587 - ): Promise<FlowTokenResult> { 588 - let onboardingTaskUrl = 'https://api.x.com/1.1/onboarding/task.json'; 589 - if ('flow_name' in data) { 590 - onboardingTaskUrl = `https://api.x.com/1.1/onboarding/task.json?flow_name=${data.flow_name}`; 591 - } 592 - 593 - log(`Making POST request to ${onboardingTaskUrl}`); 594 - const headers = new Headers({ 595 - accept: '*/*', 596 - 'accept-language': 'en-US,en;q=0.9', 597 - 'content-type': 'application/json', 598 - 'cache-control': 'no-cache', 599 - origin: 'https://x.com', 600 - pragma: 'no-cache', 601 - priority: 'u=1, i', 602 - referer: 'https://x.com/', 603 - 'sec-ch-ua': 604 - '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"', 605 - 'sec-ch-ua-mobile': '?0', 606 - 'sec-ch-ua-platform': '"Windows"', 607 - 'sec-fetch-dest': 'empty', 608 - 'sec-fetch-mode': 'cors', 609 - 'sec-fetch-site': 'same-origin', 610 - 'user-agent': 611 - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36', 612 - 'x-twitter-auth-type': 'OAuth2Client', 613 - 'x-twitter-active-user': 'yes', 614 - 'x-twitter-client-language': 'en', 615 - }); 616 - await this.installTo(headers, onboardingTaskUrl); 617 - 618 - if (this.options?.experimental?.xClientTransactionId) { 619 - const transactionId = await generateTransactionId( 620 - onboardingTaskUrl, 621 - this.fetch.bind(this), 622 - 'POST', 623 - ); 624 - headers.set('x-client-transaction-id', transactionId); 625 - } 626 - 627 - let res: Response; 628 - do { 629 - const fetchParameters: FetchParameters = [ 630 - onboardingTaskUrl, 631 - { 632 - credentials: 'include', 633 - method: 'POST', 634 - headers: headers, 635 - body: JSON.stringify(data), 636 - }, 637 - ]; 638 - 639 - try { 640 - res = await this.fetch(...fetchParameters); 641 - } catch (err) { 642 - if (!(err instanceof Error)) { 643 - throw err; 644 - } 645 - 646 - return { 647 - status: 'error', 648 - err: err, 649 - }; 650 - } 651 - 652 - await updateCookieJar(this.jar, res.headers); 653 - 654 - if (res.status === 429) { 655 - log('Rate limit hit, waiting before retrying...'); 656 - await this.onRateLimit({ 657 - fetchParameters: fetchParameters, 658 - response: res, 659 - }); 660 - } 661 - } while (res.status === 429); 662 - 663 - if (!res.ok) { 664 - return { status: 'error', err: await ApiError.fromResponse(res) }; 665 - } 666 - 667 - const flow: TwitterUserAuthFlowResponse = await flexParseJson(res); 668 - if (flow?.flow_token == null) { 669 - return { 670 - status: 'error', 671 - err: new AuthenticationError('flow_token not found.'), 672 - }; 673 - } 674 - 675 - if (flow.errors?.length) { 676 - return { 677 - status: 'error', 678 - err: new AuthenticationError( 679 - `Authentication error (${flow.errors[0].code}): ${flow.errors[0].message}`, 680 - ), 681 - }; 682 - } 683 - 684 - if (typeof flow.flow_token !== 'string') { 685 - return { 686 - status: 'error', 687 - err: new AuthenticationError('flow_token was not a string.'), 688 - }; 689 - } 690 - 691 - const subtask = flow.subtasks?.length ? flow.subtasks[0] : undefined; 692 - Check(TwitterUserAuthSubtask, subtask); 693 - 694 - if (subtask && subtask.subtask_id === 'DenyLoginSubtask') { 695 - return { 696 - status: 'error', 697 - err: new AuthenticationError('Authentication error: DenyLoginSubtask'), 698 - }; 699 - } 700 - 701 - return { 702 - status: 'success', 703 - response: flow, 704 - }; 705 - } 706 - }
-45
twitter-scraper/src/auth.test.ts
··· 1 - import { getScraper } from './test-utils'; 2 - 3 - const testLogin = process.env['TWITTER_PASSWORD'] ? test : test.skip; 4 - 5 - testLogin( 6 - 'scraper can log in', 7 - async () => { 8 - const scraper = await getScraper({ authMethod: 'password' }); 9 - await expect(scraper.isLoggedIn()).resolves.toBeTruthy(); 10 - }, 11 - 15000, 12 - ); 13 - 14 - test('scraper can log in with cookies', async () => { 15 - const scraper = await getScraper(); 16 - await expect(scraper.isLoggedIn()).resolves.toBeTruthy(); 17 - }); 18 - 19 - test('scraper can restore its login state from cookies', async () => { 20 - const scraper = await getScraper(); 21 - await expect(scraper.isLoggedIn()).resolves.toBeTruthy(); 22 - const scraper2 = await getScraper({ authMethod: 'anonymous' }); 23 - await expect(scraper2.isLoggedIn()).resolves.toBeFalsy(); 24 - 25 - // Serialize since that's the usual usage pattern 26 - const cookies = await scraper 27 - .getCookies() 28 - .then((cookies) => cookies.map((cookie) => cookie.toString())); 29 - await scraper2.setCookies(cookies); 30 - 31 - await expect(scraper2.isLoggedIn()).resolves.toBeTruthy(); 32 - }); 33 - 34 - testLogin( 35 - 'scraper can log out', 36 - async () => { 37 - const scraper = await getScraper({ authMethod: 'password' }); 38 - await expect(scraper.isLoggedIn()).resolves.toBeTruthy(); 39 - 40 - await scraper.logout(); 41 - 42 - await expect(scraper.isLoggedIn()).resolves.toBeFalsy(); 43 - }, 44 - 15000, 45 - );
-343
twitter-scraper/src/auth.ts
··· 1 - import { Cookie, CookieJar, MemoryCookieStore } from 'tough-cookie'; 2 - import { updateCookieJar } from './requests'; 3 - import { Headers } from 'headers-polyfill'; 4 - import fetch from 'cross-fetch'; 5 - import { FetchTransformOptions, flexParseJson } from './api'; 6 - import { 7 - RateLimitEvent, 8 - RateLimitStrategy, 9 - WaitingRateLimitStrategy, 10 - } from './rate-limit'; 11 - import { AuthenticationError } from './errors'; 12 - import debug from 'debug'; 13 - import { generateXPFFHeader } from './xpff'; 14 - 15 - const log = debug('twitter-scraper:auth'); 16 - 17 - export interface TwitterAuthOptions { 18 - fetch: typeof fetch; 19 - transform: Partial<FetchTransformOptions>; 20 - rateLimitStrategy: RateLimitStrategy; 21 - experimental: { 22 - xClientTransactionId?: boolean; 23 - xpff?: boolean; 24 - }; 25 - } 26 - 27 - export interface TwitterAuth { 28 - fetch: typeof fetch; 29 - 30 - /** 31 - * How to behave when being rate-limited. 32 - * @param event The event information. 33 - */ 34 - onRateLimit(event: RateLimitEvent): Promise<void>; 35 - 36 - /** 37 - * Returns the current cookie jar. 38 - */ 39 - cookieJar(): CookieJar; 40 - 41 - /** 42 - * Returns the current cookies. 43 - */ 44 - getCookies(): Promise<Cookie[]>; 45 - 46 - /** 47 - * Returns if a user is logged-in to Twitter through this instance. 48 - * @returns `true` if a user is logged-in; otherwise `false`. 49 - */ 50 - isLoggedIn(): Promise<boolean>; 51 - 52 - /** 53 - * Logs into a Twitter account. 54 - * @param username The username to log in with. 55 - * @param password The password to log in with. 56 - * @param email The email to log in with, if you have email confirmation enabled. 57 - * @param twoFactorSecret The secret to generate two factor authentication tokens with, if you have two factor authentication enabled. 58 - */ 59 - login( 60 - username: string, 61 - password: string, 62 - email?: string, 63 - twoFactorSecret?: string, 64 - ): Promise<void>; 65 - 66 - /** 67 - * Logs out of the current session. 68 - */ 69 - logout(): Promise<void>; 70 - 71 - /** 72 - * Deletes the current guest token token. 73 - */ 74 - deleteToken(): void; 75 - 76 - /** 77 - * Returns if the authentication state has a token. 78 - * @returns `true` if the authentication state has a token; `false` otherwise. 79 - */ 80 - hasToken(): boolean; 81 - 82 - /** 83 - * Returns the time that authentication was performed. 84 - * @returns The time at which the authentication token was created, or `null` if it hasn't been created yet. 85 - */ 86 - authenticatedAt(): Date | null; 87 - 88 - /** 89 - * Installs the authentication information into a headers-like object. If needed, the 90 - * authentication token will be updated from the API automatically. 91 - * @param headers A Headers instance representing a request's headers. 92 - * @param _url The URL being requested (currently unused, reserved for future use). 93 - * @param bearerTokenOverride Optional bearer token to use instead of the default one. 94 - */ 95 - installTo( 96 - headers: Headers, 97 - _url: string, 98 - bearerTokenOverride?: string, 99 - ): Promise<void>; 100 - } 101 - 102 - /** 103 - * Wraps the provided fetch function with transforms. 104 - * @param fetchFn The fetch function. 105 - * @param transform The transform options. 106 - * @returns The input fetch function, wrapped with the provided transforms. 107 - */ 108 - function withTransform( 109 - fetchFn: typeof fetch, 110 - transform?: Partial<FetchTransformOptions>, 111 - ): typeof fetch { 112 - return async (input, init) => { 113 - const fetchArgs = (await transform?.request?.(input, init)) ?? [ 114 - input, 115 - init, 116 - ]; 117 - const res = await fetchFn(...fetchArgs); 118 - return (await transform?.response?.(res)) ?? res; 119 - }; 120 - } 121 - 122 - /** 123 - * A guest authentication token manager. Automatically handles token refreshes. 124 - */ 125 - export class TwitterGuestAuth implements TwitterAuth { 126 - protected bearerToken: string; 127 - protected jar: CookieJar; 128 - protected guestToken?: string; 129 - protected guestCreatedAt?: Date; 130 - protected rateLimitStrategy: RateLimitStrategy; 131 - 132 - fetch: typeof fetch; 133 - 134 - constructor( 135 - bearerToken: string, 136 - readonly options?: Partial<TwitterAuthOptions>, 137 - ) { 138 - this.fetch = withTransform(options?.fetch ?? fetch, options?.transform); 139 - this.rateLimitStrategy = 140 - options?.rateLimitStrategy ?? new WaitingRateLimitStrategy(); 141 - this.bearerToken = bearerToken; 142 - this.jar = new CookieJar(); 143 - } 144 - 145 - async onRateLimit(event: RateLimitEvent): Promise<void> { 146 - await this.rateLimitStrategy.onRateLimit(event); 147 - } 148 - 149 - cookieJar(): CookieJar { 150 - return this.jar; 151 - } 152 - 153 - isLoggedIn(): Promise<boolean> { 154 - return Promise.resolve(false); 155 - } 156 - 157 - // eslint-disable-next-line @typescript-eslint/no-unused-vars 158 - login(_username: string, _password: string, _email?: string): Promise<void> { 159 - return this.updateGuestToken(); 160 - } 161 - 162 - logout(): Promise<void> { 163 - this.deleteToken(); 164 - this.jar = new CookieJar(); 165 - return Promise.resolve(); 166 - } 167 - 168 - deleteToken() { 169 - delete this.guestToken; 170 - delete this.guestCreatedAt; 171 - } 172 - 173 - hasToken(): boolean { 174 - return this.guestToken != null; 175 - } 176 - 177 - authenticatedAt(): Date | null { 178 - if (this.guestCreatedAt == null) { 179 - return null; 180 - } 181 - 182 - return new Date(this.guestCreatedAt); 183 - } 184 - 185 - async installTo( 186 - headers: Headers, 187 - _url: string, 188 - bearerTokenOverride?: string, 189 - ): Promise<void> { 190 - // Use the override token if provided, otherwise use the instance's bearer token 191 - const tokenToUse = bearerTokenOverride ?? this.bearerToken; 192 - 193 - // Only use guest tokens when not overriding the bearer token 194 - // Guest tokens are tied to the bearer token they were generated with 195 - if (!bearerTokenOverride) { 196 - if (this.shouldUpdate()) { 197 - await this.updateGuestToken(); 198 - } 199 - 200 - if (this.guestToken) { 201 - headers.set('x-guest-token', this.guestToken); 202 - } 203 - } 204 - 205 - headers.set('authorization', `Bearer ${tokenToUse}`); 206 - headers.set( 207 - 'user-agent', 208 - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36', 209 - ); 210 - 211 - await this.installCsrfToken(headers); 212 - 213 - if (this.options?.experimental?.xpff) { 214 - const guestId = await this.guestId(); 215 - if (guestId != null) { 216 - const xpffHeader = await generateXPFFHeader(guestId); 217 - headers.set('x-xp-forwarded-for', xpffHeader); 218 - } 219 - } 220 - 221 - headers.set('cookie', await this.getCookieString()); 222 - } 223 - 224 - async installCsrfToken(headers: Headers): Promise<void> { 225 - const cookies = await this.getCookies(); 226 - const xCsrfToken = cookies.find((cookie) => cookie.key === 'ct0'); 227 - if (xCsrfToken) { 228 - headers.set('x-csrf-token', xCsrfToken.value); 229 - } 230 - } 231 - 232 - protected async setCookie(key: string, value: string): Promise<void> { 233 - const cookie = Cookie.parse(`${key}=${value}`); 234 - if (!cookie) { 235 - throw new Error('Failed to parse cookie.'); 236 - } 237 - 238 - await this.jar.setCookie(cookie, this.getCookieJarUrl()); 239 - 240 - if (typeof document !== 'undefined') { 241 - document.cookie = cookie.toString(); 242 - } 243 - } 244 - 245 - public async getCookies(): Promise<Cookie[]> { 246 - return this.jar.getCookies(this.getCookieJarUrl()); 247 - } 248 - 249 - protected async getCookieString(): Promise<string> { 250 - const cookies = await this.getCookies(); 251 - return cookies.map((cookie) => `${cookie.key}=${cookie.value}`).join('; '); 252 - } 253 - 254 - protected async removeCookie(key: string): Promise<void> { 255 - //@ts-expect-error don't care 256 - const store: MemoryCookieStore = this.jar.store; 257 - const cookies = await this.jar.getCookies(this.getCookieJarUrl()); 258 - for (const cookie of cookies) { 259 - if (!cookie.domain || !cookie.path) continue; 260 - store.removeCookie(cookie.domain, cookie.path, key); 261 - 262 - if (typeof document !== 'undefined') { 263 - document.cookie = `${cookie.key}=; Max-Age=0; path=${cookie.path}; domain=${cookie.domain}`; 264 - } 265 - } 266 - } 267 - 268 - private getCookieJarUrl(): string { 269 - return typeof document !== 'undefined' 270 - ? document.location.toString() 271 - : 'https://x.com'; 272 - } 273 - 274 - protected async guestId(): Promise<string | null> { 275 - const cookies = await this.getCookies(); 276 - const guestIdCookie = cookies.find((cookie) => cookie.key === 'guest_id'); 277 - return guestIdCookie ? guestIdCookie.value : null; 278 - } 279 - 280 - /** 281 - * Updates the authentication state with a new guest token from the Twitter API. 282 - */ 283 - protected async updateGuestToken() { 284 - try { 285 - await this.updateGuestTokenCore(); 286 - } catch (err) { 287 - log('Failed to update guest token; this may cause issues:', err); 288 - } 289 - } 290 - 291 - private async updateGuestTokenCore() { 292 - const guestActivateUrl = 'https://api.x.com/1.1/guest/activate.json'; 293 - 294 - const headers = new Headers({ 295 - Authorization: `Bearer ${this.bearerToken}`, 296 - Cookie: await this.getCookieString(), 297 - }); 298 - 299 - log(`Making POST request to ${guestActivateUrl}`); 300 - 301 - const res = await this.fetch(guestActivateUrl, { 302 - method: 'POST', 303 - headers: headers, 304 - referrerPolicy: 'no-referrer', 305 - }); 306 - 307 - await updateCookieJar(this.jar, res.headers); 308 - 309 - if (!res.ok) { 310 - throw new AuthenticationError(await res.text()); 311 - } 312 - 313 - const o = await flexParseJson<any>(res); 314 - if (o == null || o['guest_token'] == null) { 315 - throw new AuthenticationError('guest_token not found.'); 316 - } 317 - 318 - const newGuestToken = o['guest_token']; 319 - if (typeof newGuestToken !== 'string') { 320 - throw new AuthenticationError('guest_token was not a string.'); 321 - } 322 - 323 - this.guestToken = newGuestToken; 324 - this.guestCreatedAt = new Date(); 325 - 326 - await this.setCookie('gt', newGuestToken); 327 - 328 - log(`Updated guest token: ${newGuestToken}`); 329 - } 330 - 331 - /** 332 - * Returns if the authentication token needs to be updated or not. 333 - * @returns `true` if the token needs to be updated; `false` otherwise. 334 - */ 335 - private shouldUpdate(): boolean { 336 - return ( 337 - !this.hasToken() || 338 - (this.guestCreatedAt != null && 339 - this.guestCreatedAt < 340 - new Date(new Date().valueOf() - 3 * 60 * 60 * 1000)) 341 - ); 342 - } 343 - }
-141
twitter-scraper/src/cycletls-fetch.ts
··· 1 - import initCycleTLS from 'cycletls'; 2 - import { Headers } from 'headers-polyfill'; 3 - import debug from 'debug'; 4 - 5 - const log = debug('twitter-scraper:cycletls'); 6 - 7 - let cycleTLSInstance: Awaited<ReturnType<typeof initCycleTLS>> | null = null; 8 - 9 - /** 10 - * Initialize the CycleTLS instance. This should be called once before using the fetch wrapper. 11 - */ 12 - export async function initCycleTLSFetch() { 13 - if (!cycleTLSInstance) { 14 - log('Initializing CycleTLS...'); 15 - cycleTLSInstance = await initCycleTLS(); 16 - log('CycleTLS initialized successfully'); 17 - } 18 - return cycleTLSInstance; 19 - } 20 - 21 - /** 22 - * Cleanup the CycleTLS instance. Call this when you're done making requests. 23 - */ 24 - export function cycleTLSExit() { 25 - if (cycleTLSInstance) { 26 - log('Exiting CycleTLS...'); 27 - cycleTLSInstance.exit(); 28 - cycleTLSInstance = null; 29 - } 30 - } 31 - 32 - /** 33 - * A fetch-compatible wrapper around CycleTLS that mimics Chrome's TLS fingerprint 34 - * to bypass Cloudflare and other bot detection systems. 35 - */ 36 - export async function cycleTLSFetch( 37 - input: RequestInfo | URL, 38 - init?: RequestInit, 39 - ): Promise<Response> { 40 - const instance = await initCycleTLSFetch(); 41 - 42 - const url = 43 - typeof input === 'string' 44 - ? input 45 - : input instanceof URL 46 - ? input.toString() 47 - : input.url; 48 - const method = (init?.method || 'GET').toUpperCase(); 49 - 50 - log(`Making ${method} request to ${url}`); 51 - 52 - // Extract headers from RequestInit 53 - const headers: Record<string, string> = {}; 54 - if (init?.headers) { 55 - if (init.headers instanceof Headers) { 56 - init.headers.forEach((value, key) => { 57 - headers[key] = value; 58 - }); 59 - } else if (Array.isArray(init.headers)) { 60 - init.headers.forEach(([key, value]) => { 61 - headers[key] = value; 62 - }); 63 - } else { 64 - Object.assign(headers, init.headers); 65 - } 66 - } 67 - 68 - // Convert body to string if needed 69 - let body: string | undefined; 70 - if (init?.body) { 71 - if (typeof init.body === 'string') { 72 - body = init.body; 73 - } else if (init.body instanceof URLSearchParams) { 74 - body = init.body.toString(); 75 - } else { 76 - body = init.body.toString(); 77 - } 78 - } 79 - 80 - // Use Chrome 120 JA3 fingerprint for maximum compatibility 81 - const options = { 82 - body, 83 - headers, 84 - // Chrome 120 on Windows 10 85 - ja3: '771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513,29-23-24,0', 86 - userAgent: 87 - headers['user-agent'] || 88 - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36', 89 - }; 90 - 91 - try { 92 - const response = await instance( 93 - url, 94 - options, 95 - method.toLowerCase() as 96 - | 'get' 97 - | 'post' 98 - | 'put' 99 - | 'delete' 100 - | 'patch' 101 - | 'head' 102 - | 'options', 103 - ); 104 - 105 - // Convert CycleTLS response to fetch Response 106 - // CycleTLS returns headers as an object 107 - const responseHeaders = new Headers(); 108 - if (response.headers) { 109 - Object.entries(response.headers).forEach(([key, value]) => { 110 - if (Array.isArray(value)) { 111 - value.forEach((v) => { 112 - responseHeaders.append(key, v); 113 - }); 114 - } else if (typeof value === 'string') { 115 - responseHeaders.set(key, value); 116 - } 117 - }); 118 - } 119 - 120 - // Get response body - cycletls provides helper methods, but we need the raw text 121 - // The response object has a text() method that returns the body as text 122 - let responseBody = ''; 123 - if (typeof response.text === 'function') { 124 - responseBody = await response.text(); 125 - } else if ((response as any).body) { 126 - responseBody = (response as any).body; 127 - } 128 - 129 - // Create a proper Response object using standard Response constructor 130 - const fetchResponse = new Response(responseBody, { 131 - status: response.status, 132 - statusText: '', // CycleTLS doesn't provide status text 133 - headers: responseHeaders, 134 - }); 135 - 136 - return fetchResponse; 137 - } catch (error) { 138 - log(`CycleTLS request failed: ${error}`); 139 - throw error; 140 - } 141 - }
-58
twitter-scraper/src/direct-messages-async.ts
··· 1 - import { 2 - DmConversationTimeline, 3 - DmMessageEntry, 4 - DmCursorOptions, 5 - } from './direct-messages'; 6 - import { jitter } from './api'; 7 - 8 - export interface FetchDmConversationMessagesResponse { 9 - conversation: DmConversationTimeline; 10 - next?: DmCursorOptions; 11 - } 12 - 13 - export type FetchDmConversationFn = ( 14 - conversationId: string, 15 - maxMessages: number, 16 - cursor: DmCursorOptions | undefined, 17 - ) => Promise<FetchDmConversationMessagesResponse>; 18 - 19 - export async function* getDmConversationMessagesGenerator( 20 - conversationId: string, 21 - maxMessages: number, 22 - initialCursor: DmCursorOptions | undefined, 23 - fetchFunc: FetchDmConversationFn, 24 - ): AsyncGenerator<DmMessageEntry, void> { 25 - let nMessages = 0; 26 - let cursor = initialCursor; 27 - 28 - while (nMessages < maxMessages) { 29 - const batch: FetchDmConversationMessagesResponse = await fetchFunc( 30 - conversationId, 31 - maxMessages, 32 - cursor, 33 - ); 34 - 35 - const { conversation, next } = batch; 36 - 37 - if (!conversation?.entries || conversation?.entries?.length === 0) { 38 - break; 39 - } 40 - 41 - for (const entry of conversation.entries) { 42 - if (nMessages < maxMessages) { 43 - yield entry; 44 - nMessages++; 45 - } else { 46 - break; 47 - } 48 - } 49 - 50 - cursor = next; 51 - 52 - if (conversation.status === 'AT_END' || !next) { 53 - break; 54 - } 55 - 56 - await jitter(1000); 57 - } 58 - }
-125
twitter-scraper/src/direct-messages.test.ts
··· 1 - import { getScraper } from './test-utils'; 2 - import { findDmConversationsByUserId, DmInbox } from './direct-messages'; 3 - 4 - async function getInboxWithConversations() { 5 - const scraper = await getScraper(); 6 - const directMessages = await scraper.getDmInbox(); 7 - expect(directMessages.conversations).toBeDefined(); 8 - 9 - const conversationIds = Object.keys(directMessages.conversations); 10 - expect(conversationIds.length).toBeGreaterThan(0); 11 - 12 - return { scraper, directMessages, conversationIds }; 13 - } 14 - 15 - function getFirstConversation( 16 - directMessages: DmInbox, 17 - conversationIds: string[], 18 - ) { 19 - // This should be your most recent DM. 20 - const firstConversation = directMessages.conversations[conversationIds[0]]; 21 - expect(firstConversation).toBeDefined(); 22 - 23 - return firstConversation; 24 - } 25 - 26 - test('scraper can get direct message inbox when authenticated', async () => { 27 - const scraper = await getScraper(); 28 - 29 - const directMessages = await scraper.getDmInbox(); 30 - expect(directMessages).toBeDefined(); 31 - 32 - expect(typeof directMessages).toBe('object'); 33 - }); 34 - 35 - test('getDmInbox throws error when not authenticated', async () => { 36 - const scraper = await getScraper({ authMethod: 'anonymous' }); 37 - 38 - await expect(scraper.isLoggedIn()).resolves.toBeFalsy(); 39 - await expect(scraper.getDmInbox()).rejects.toThrow(); 40 - }); 41 - 42 - test('scraper can get direct message conversation', async () => { 43 - const { scraper, directMessages, conversationIds } = 44 - await getInboxWithConversations(); 45 - 46 - const firstConversation = getFirstConversation( 47 - directMessages, 48 - conversationIds, 49 - ); 50 - expect(firstConversation.conversation_id).toBeDefined(); 51 - 52 - const conversation = await scraper.getDmConversation( 53 - firstConversation.conversation_id, 54 - ); 55 - 56 - expect(conversation.status).toBeDefined(); 57 - expect(conversation.min_entry_id).toBeDefined(); 58 - expect(conversation.max_entry_id).toBeDefined(); 59 - expect(conversation.entries).toBeDefined(); 60 - expect(conversation.users).toBeDefined(); 61 - expect(conversation.conversations).toBeDefined(); 62 - }); 63 - 64 - test('scraper can paginate through direct message conversation', async () => { 65 - const { scraper, directMessages, conversationIds } = 66 - await getInboxWithConversations(); 67 - 68 - const firstConversation = getFirstConversation( 69 - directMessages, 70 - conversationIds, 71 - ); 72 - expect(firstConversation.conversation_id).toBeDefined(); 73 - 74 - const conversationId = firstConversation.conversation_id; 75 - const messages = scraper.getDmMessages(conversationId, 30); 76 - 77 - let count = 0; 78 - for await (const entry of messages) { 79 - expect(entry).toBeDefined(); 80 - 81 - if (entry.message) { 82 - expect(entry.message).toBeDefined(); 83 - } else if (entry.welcome_message_create) { 84 - expect(entry.welcome_message_create).toBeDefined(); 85 - } else { 86 - fail('No messages were retrieved'); 87 - } 88 - 89 - count++; 90 - } 91 - 92 - // Your DM will need at least 20+ messages to test this. 93 - // 20 was chosen because that seems to be the max size per response. 94 - expect(count).toBeGreaterThan(20); 95 - }); 96 - 97 - test('findConversationsByUserId filters conversations by user ID', async () => { 98 - const { directMessages, conversationIds } = await getInboxWithConversations(); 99 - 100 - const firstConversation = getFirstConversation( 101 - directMessages, 102 - conversationIds, 103 - ); 104 - expect(firstConversation.participants).toBeDefined(); 105 - expect(firstConversation.participants.length).toBeGreaterThan(0); 106 - 107 - // in my responses, 0th is the current user and 1st is the other user. 108 - const targetUserId = firstConversation.participants[1].user_id; 109 - 110 - const foundConversations = findDmConversationsByUserId( 111 - directMessages, 112 - targetUserId, 113 - ); 114 - 115 - expect(foundConversations).toBeDefined(); 116 - expect(foundConversations.length).toBeGreaterThan(0); 117 - 118 - // make sure all convos are the right user 119 - foundConversations.forEach((conversation) => { 120 - const hasUser = conversation.participants.some( 121 - (participant) => participant.user_id === targetUserId, 122 - ); 123 - expect(hasUser).toBe(true); 124 - }); 125 - });
-301
twitter-scraper/src/direct-messages.ts
··· 1 - import { AuthenticationError } from './errors'; 2 - import { TwitterAuth } from './auth'; 3 - import { LegacyUserRaw } from './profile'; 4 - import { requestApi, addApiParams } from './api'; 5 - 6 - import { getDmConversationMessagesGenerator } from './direct-messages-async'; 7 - 8 - export interface DmInboxResponse { 9 - inbox_initial_state: DmInbox; 10 - } 11 - 12 - export interface DmInbox { 13 - last_seen_event_id: string; 14 - trusted_last_seen_event_id: string; 15 - untrusted_last_seen_event_id: string; 16 - cursor: string; 17 - inbox_timelines: DmInboxTimelines; 18 - entries: DmMessageEntry[]; 19 - users: { [key: string]: LegacyUserRaw }; 20 - conversations: { [key: string]: DmConversation }; 21 - } 22 - 23 - export interface DmConversationResponse { 24 - conversation_timeline: DmConversationTimeline; 25 - } 26 - 27 - export interface DmConversationTimeline { 28 - status: DmStatus; 29 - min_entry_id: string; 30 - max_entry_id: string; 31 - entries: DmMessageEntry[]; 32 - users: { [key: string]: LegacyUserRaw }; 33 - conversations: { [key: string]: DmConversation }; 34 - } 35 - 36 - export interface DmConversation { 37 - conversation_id: string; 38 - type: string; 39 - sort_event_id: string; 40 - sort_timestamp: string; 41 - participants: DmParticipant[]; 42 - nsfw: boolean; 43 - notifications_disabled: boolean; 44 - mention_notifications_disabled: boolean; 45 - last_read_event_id: string; 46 - read_only: boolean; 47 - trusted: boolean; 48 - muted: boolean; 49 - status: DmStatus; 50 - min_entry_id: string; 51 - max_entry_id: string; 52 - } 53 - 54 - export type DmStatus = 'AT_END' | 'HAS_MORE'; 55 - 56 - export interface DmParticipant { 57 - user_id: string; 58 - last_read_event_id?: string; 59 - } 60 - 61 - export interface DmMessageEntry { 62 - welcome_message_create?: DmWelcomeMessage; 63 - message?: DmMessage; 64 - } 65 - 66 - export interface DmMessage { 67 - id: string; 68 - time: string; 69 - affects_sort: boolean; 70 - request_id: string; 71 - conversation_id: string; 72 - message_data: DmMessageData; 73 - message_reactions: DmReaction[]; 74 - } 75 - 76 - export interface DmMessageData { 77 - id: string; 78 - time: string; 79 - recipient_id: string; 80 - sender_id: string; 81 - text: string; 82 - edit_count?: number; 83 - entities?: DmMessageEntities; 84 - } 85 - 86 - export interface DmReaction { 87 - id: string; 88 - time: string; 89 - conversation_id: string; 90 - message_id: string; 91 - reaction_key: string; 92 - emoji_reaction: string; 93 - sender_id: string; 94 - } 95 - 96 - export interface DmMessageEntities { 97 - // TODO: Not sure what these types are. 98 - hashtags: any[]; 99 - symbols: any[]; 100 - user_mentions: any[]; 101 - urls: DmMessageUrl[]; 102 - } 103 - 104 - export interface DmMessageUrl { 105 - url: string; 106 - expanded_url: string; 107 - display_url: string; 108 - indices: number[]; 109 - } 110 - 111 - export interface DmWelcomeMessage extends DmMessage { 112 - welcome_message_id: string; 113 - } 114 - 115 - export interface DmInboxTimelines { 116 - trusted: DmTimelineState; 117 - untrusted: DmTimelineState; 118 - untrusted_low_quality: DmTimelineState; 119 - } 120 - 121 - export interface DmTimelineState { 122 - status: DmStatus; 123 - min_entry_id: string; 124 - } 125 - 126 - export interface DmCursorOptions { 127 - maxId?: string; 128 - minId?: string; 129 - } 130 - 131 - export async function fetchDmInbox(auth: TwitterAuth) { 132 - if (!(await auth.isLoggedIn())) { 133 - throw new AuthenticationError( 134 - 'Scraper is not logged-in for fetching direct messages.', 135 - ); 136 - } 137 - 138 - // TODO: Not sure how the "cursor" works for this. I don't have enough DMs to test. 139 - const params = new URLSearchParams(); 140 - addApiParams(params, false); 141 - 142 - params.set('nsfw_filtering_enabled', 'false'); 143 - params.set('filter_low_quality', 'true'); 144 - params.set('include_quality', 'all'); 145 - params.set('include_ext_profile_image_shape', '1'); 146 - params.set('dm_secret_conversations_enabled', 'false'); 147 - params.set('krs_registration_enabled', 'false'); 148 - params.set('include_ext_limited_action_results', 'true'); 149 - params.set('dm_users', 'true'); 150 - params.set('include_groups', 'true'); 151 - params.set('include_inbox_timelines', 'true'); 152 - params.set('supports_reactions', 'true'); 153 - params.set('supports_edit', 'true'); 154 - params.set('include_ext_edit_control', 'true'); 155 - params.set('include_ext_business_affiliations_label', 'true'); 156 - params.set('include_ext_parody_commentary_fan_label', 'true'); 157 - params.set( 158 - 'ext', 159 - 'mediaColor,altText,mediaStats,highlightedLabel,parodyCommentaryFanLabel,voiceInfo,birdwatchPivot,superFollowMetadata,unmentionInfo,editControl,article', 160 - ); 161 - 162 - const res = await requestApi<DmInboxResponse>( 163 - `https://x.com/i/api/1.1/dm/inbox_initial_state.json?${params.toString()}`, 164 - auth, 165 - ); 166 - 167 - if (!res.success) { 168 - throw res.err; 169 - } 170 - 171 - return parseDmInbox(res.value); 172 - } 173 - 174 - export async function parseDmInbox(inbox: DmInboxResponse) { 175 - return inbox.inbox_initial_state; 176 - } 177 - 178 - // This gets the current authenticated user's direct messages. 179 - // This requires the user to be authenticated. 180 - export async function getDmInbox(auth: TwitterAuth) { 181 - return await fetchDmInbox(auth); 182 - } 183 - 184 - // This gets the current authenticated user's direct conversations. 185 - // This requires the user to be authenticated. 186 - export async function fetchDmConversation( 187 - conversationId: string, 188 - cursor: DmCursorOptions | undefined, 189 - auth: TwitterAuth, 190 - ) { 191 - if (!(await auth.isLoggedIn())) { 192 - throw new AuthenticationError( 193 - 'Scraper is not logged-in for fetching direct messages.', 194 - ); 195 - } 196 - 197 - const params = new URLSearchParams(); 198 - addApiParams(params, false); 199 - 200 - params.set('context', 'FETCH_DM_CONVERSATION_HISTORY'); 201 - params.set('include_ext_profile_image_shape', '1'); 202 - params.set('dm_secret_conversations_enabled', 'false'); 203 - params.set('krs_registration_enabled', 'false'); 204 - params.set('include_ext_limited_action_results', 'true'); 205 - params.set('dm_users', 'true'); 206 - params.set('include_groups', 'true'); 207 - params.set('include_inbox_timelines', 'true'); 208 - params.set('supports_reactions', 'true'); 209 - params.set('supports_edit', 'true'); 210 - params.set('include_conversation_info', 'true'); 211 - params.set( 212 - 'ext', 213 - 'mediaColor,altText,mediaStats,highlightedLabel,parodyCommentaryFanLabel,voiceInfo,birdwatchPivot,superFollowMetadata,unmentionInfo,editControl,article', 214 - ); 215 - 216 - // By default, passing no cursor means you get the latest results. 217 - // `max_id` does backwards pagination using min_entry_id as the maxId to get older messages. 218 - // `min_id` does forward pagination using max_entry_id as the minId to get newer messages. 219 - // To know when there are no more pages, the response's "status" will return "AT_END". 220 - if (cursor) { 221 - if (cursor.maxId) { 222 - params.set('max_id', cursor.maxId); 223 - } 224 - if (cursor.minId) { 225 - params.set('min_id', cursor.minId); 226 - } 227 - } 228 - 229 - const url = `https://x.com/i/api/1.1/dm/conversation/${conversationId}.json?${params.toString()}`; 230 - 231 - const res = await requestApi<DmConversationResponse>(url, auth); 232 - 233 - if (!res.success) { 234 - throw res.err; 235 - } 236 - 237 - return parseDmConversation(res.value); 238 - } 239 - 240 - export async function parseDmConversation( 241 - conversation: DmConversationResponse, 242 - ) { 243 - return conversation.conversation_timeline; 244 - } 245 - 246 - export async function getDmConversation( 247 - conversationId: string, 248 - cursor: DmCursorOptions | undefined, 249 - auth: TwitterAuth, 250 - ) { 251 - return await fetchDmConversation(conversationId, cursor, auth); 252 - } 253 - 254 - export function getDmMessages( 255 - conversationId: string, 256 - maxMessages: number, 257 - cursor: DmCursorOptions | undefined, 258 - auth: TwitterAuth, 259 - ): AsyncGenerator<DmMessageEntry, void> { 260 - return getDmConversationMessagesGenerator( 261 - conversationId, 262 - maxMessages, 263 - cursor, 264 - async (id, _max, cursor) => { 265 - const conversation = await fetchDmConversation(id, cursor, auth); 266 - 267 - let next: DmCursorOptions | undefined = undefined; 268 - 269 - if (cursor?.minId && conversation.max_entry_id) { 270 - next = { minId: conversation.max_entry_id }; 271 - } else if (conversation.min_entry_id) { 272 - next = { maxId: conversation.min_entry_id }; 273 - } 274 - 275 - return { 276 - conversation, 277 - next, 278 - }; 279 - }, 280 - ); 281 - } 282 - 283 - export function findDmConversationsByUserId( 284 - inbox: DmInbox, 285 - userId: string, 286 - ): DmConversation[] { 287 - const conversations: DmConversation[] = []; 288 - 289 - for (const conversationId in inbox.conversations) { 290 - const conversation = inbox.conversations[conversationId]; 291 - const hasUser = conversation.participants.some( 292 - (participant) => participant.user_id === userId, 293 - ); 294 - 295 - if (hasUser) { 296 - conversations.push(conversation); 297 - } 298 - } 299 - 300 - return conversations; 301 - }
-66
twitter-scraper/src/errors.ts
··· 1 - export class ApiError extends Error { 2 - constructor(readonly response: Response, readonly data: any) { 3 - super( 4 - `Response status: ${response.status} | headers: ${JSON.stringify( 5 - headersToString(response.headers), 6 - )} | data: ${typeof data === 'string' ? data : JSON.stringify(data)}`, 7 - ); 8 - } 9 - 10 - static async fromResponse(response: Response) { 11 - // Try our best to parse the result, but don't bother if we can't 12 - let data: string | object | undefined = undefined; 13 - try { 14 - if (response.headers.get('content-type')?.includes('application/json')) { 15 - data = await response.json(); 16 - } else { 17 - data = await response.text(); 18 - } 19 - } catch { 20 - try { 21 - data = await response.text(); 22 - } catch {} 23 - } 24 - 25 - return new ApiError(response, data); 26 - } 27 - } 28 - 29 - function headersToString(headers: Headers): string { 30 - const result: string[] = []; 31 - headers.forEach((value, key) => { 32 - result.push(`${key}: ${value}`); 33 - }); 34 - return result.join('\n'); 35 - } 36 - 37 - export class AuthenticationError extends Error { 38 - constructor(message?: string) { 39 - super(message || 'Authentication failed'); 40 - this.name = 'AuthenticationError'; 41 - } 42 - } 43 - 44 - export interface TwitterApiErrorPosition { 45 - line: number; 46 - column: number; 47 - } 48 - 49 - export interface TwitterApiErrorTraceInfo { 50 - trace_id: string; 51 - } 52 - 53 - export interface TwitterApiErrorExtensions { 54 - code?: number; 55 - kind?: string; 56 - name?: string; 57 - source?: string; 58 - tracing?: TwitterApiErrorTraceInfo; 59 - } 60 - 61 - export interface TwitterApiErrorRaw extends TwitterApiErrorExtensions { 62 - message?: string; 63 - locations?: TwitterApiErrorPosition[]; 64 - path?: string[]; 65 - extensions?: TwitterApiErrorExtensions; 66 - }
-21
twitter-scraper/src/platform/index.ts
··· 1 - import { PlatformExtensions, genericPlatform } from './platform-interface'; 2 - 3 - export * from './platform-interface'; 4 - 5 - declare const PLATFORM_NODE: boolean; 6 - 7 - export class Platform implements PlatformExtensions { 8 - async randomizeCiphers() { 9 - const platform = await Platform.importPlatform(); 10 - await platform?.randomizeCiphers(); 11 - } 12 - 13 - private static async importPlatform(): Promise<null | PlatformExtensions> { 14 - if (PLATFORM_NODE) { 15 - const { platform } = await import('./node/index.js'); 16 - return platform as PlatformExtensions; 17 - } 18 - 19 - return genericPlatform; 20 - } 21 - }
-11
twitter-scraper/src/platform/node/index.ts
··· 1 - import { PlatformExtensions } from '../platform-interface'; 2 - import { randomizeCiphers } from './randomize-ciphers'; 3 - 4 - class NodePlatform implements PlatformExtensions { 5 - randomizeCiphers(): Promise<void> { 6 - randomizeCiphers(); 7 - return Promise.resolve(); 8 - } 9 - } 10 - 11 - export const platform = new NodePlatform();
-29
twitter-scraper/src/platform/node/randomize-ciphers.ts
··· 1 - import tls from 'node:tls'; 2 - import { randomBytes } from 'node:crypto'; 3 - 4 - const ORIGINAL_CIPHERS = tls.DEFAULT_CIPHERS; 5 - 6 - // How many ciphers from the top of the list to shuffle. 7 - // The remaining ciphers are left in the original order. 8 - const TOP_N_SHUFFLE = 8; 9 - 10 - // Modified variation of https://stackoverflow.com/a/12646864 11 - const shuffleArray = (array: unknown[]) => { 12 - for (let i = array.length - 1; i > 0; i--) { 13 - const j = randomBytes(4).readUint32LE() % array.length; 14 - [array[i], array[j]] = [array[j], array[i]]; 15 - } 16 - 17 - return array; 18 - }; 19 - 20 - // https://github.com/imputnet/cobalt/pull/574 21 - export const randomizeCiphers = () => { 22 - do { 23 - const cipherList = ORIGINAL_CIPHERS.split(':'); 24 - const shuffled = shuffleArray(cipherList.slice(0, TOP_N_SHUFFLE)); 25 - const retained = cipherList.slice(TOP_N_SHUFFLE); 26 - 27 - tls.DEFAULT_CIPHERS = [...shuffled, ...retained].join(':'); 28 - } while (tls.DEFAULT_CIPHERS === ORIGINAL_CIPHERS); 29 - };
-16
twitter-scraper/src/platform/platform-interface.ts
··· 1 - export interface PlatformExtensions { 2 - /** 3 - * Randomizes the runtime's TLS ciphers to bypass TLS client fingerprinting, which 4 - * hopefully avoids random 404s on some requests. 5 - * 6 - * **References:** 7 - * - https://github.com/imputnet/cobalt/pull/574 8 - */ 9 - randomizeCiphers(): Promise<void>; 10 - } 11 - 12 - export const genericPlatform = new (class implements PlatformExtensions { 13 - randomizeCiphers(): Promise<void> { 14 - return Promise.resolve(); 15 - } 16 - })();
-138
twitter-scraper/src/profile.test.ts
··· 1 - import { Profile } from './profile'; 2 - import { getScraper } from './test-utils'; 3 - 4 - test('scraper can get profile', async () => { 5 - const expected: Profile = { 6 - avatar: 7 - 'https://pbs.twimg.com/profile_images/436075027193004032/XlDa2oaz.jpeg', 8 - banner: 'https://pbs.twimg.com/profile_banners/106037940/1541084318', 9 - biography: 'nothing', 10 - isPrivate: false, 11 - isVerified: undefined, 12 - isBlueVerified: false, 13 - joined: new Date(Date.UTC(2010, 0, 18, 8, 49, 30, 0)), 14 - location: 'Ukraine', 15 - name: 'Nomadic', 16 - pinnedTweetIds: [], 17 - url: 'https://x.com/nomadic_ua', 18 - userId: '106037940', 19 - username: 'nomadic_ua', 20 - website: 'https://nomadic.name', 21 - }; 22 - 23 - const scraper = await getScraper(); 24 - 25 - const actual = await scraper.getProfile('nomadic_ua'); 26 - expect(actual.avatar).toEqual(expected.avatar); 27 - expect(actual.banner).toEqual(expected.banner); 28 - expect(actual.biography).toEqual(expected.biography); 29 - expect(actual.isPrivate).toEqual(expected.isPrivate); 30 - expect(actual.isVerified).toEqual(expected.isVerified); 31 - expect(actual.isBlueVerified).toEqual(expected.isBlueVerified); 32 - expect(actual.joined).toEqual(expected.joined); 33 - expect(actual.location).toEqual(expected.location); 34 - expect(actual.name).toEqual(expected.name); 35 - expect(actual.pinnedTweetIds).toEqual(expected.pinnedTweetIds); 36 - expect(actual.url).toEqual(expected.url); 37 - expect(actual.userId).toEqual(expected.userId); 38 - expect(actual.username).toEqual(expected.username); 39 - expect(actual.website).toEqual(expected.website); 40 - }); 41 - 42 - test('scraper can get profile without logging in', async () => { 43 - const expected: Profile = { 44 - avatar: 45 - 'https://pbs.twimg.com/profile_images/436075027193004032/XlDa2oaz.jpeg', 46 - banner: 'https://pbs.twimg.com/profile_banners/106037940/1541084318', 47 - biography: 'nothing', 48 - isPrivate: false, 49 - isVerified: undefined, 50 - isBlueVerified: false, 51 - joined: new Date(Date.UTC(2010, 0, 18, 8, 49, 30, 0)), 52 - location: 'Ukraine', 53 - name: 'Nomadic', 54 - pinnedTweetIds: [], 55 - url: 'https://x.com/nomadic_ua', 56 - userId: '106037940', 57 - username: 'nomadic_ua', 58 - website: 'https://nomadic.name', 59 - }; 60 - 61 - const scraper = await getScraper({ authMethod: 'anonymous' }); 62 - 63 - const actual = await scraper.getProfile('nomadic_ua'); 64 - expect(actual.avatar).toEqual(expected.avatar); 65 - expect(actual.banner).toEqual(expected.banner); 66 - expect(actual.biography).toEqual(expected.biography); 67 - expect(actual.isPrivate).toEqual(expected.isPrivate); 68 - expect(actual.isVerified).toEqual(expected.isVerified); 69 - expect(actual.isBlueVerified).toEqual(expected.isBlueVerified); 70 - expect(actual.joined).toEqual(expected.joined); 71 - expect(actual.location).toEqual(expected.location); 72 - expect(actual.name).toEqual(expected.name); 73 - expect(actual.pinnedTweetIds).toEqual(expected.pinnedTweetIds); 74 - expect(actual.url).toEqual(expected.url); 75 - expect(actual.userId).toEqual(expected.userId); 76 - expect(actual.username).toEqual(expected.username); 77 - expect(actual.website).toEqual(expected.website); 78 - }); 79 - 80 - test('scraper can get partial private profile', async () => { 81 - const expected: Profile = { 82 - avatar: 83 - 'https://pbs.twimg.com/profile_images/1612213936082030594/_HEsjv7Q.jpg', 84 - banner: 85 - 'https://pbs.twimg.com/profile_banners/1221221876849995777/1673110776', 86 - biography: `t h e h e r m i t`, 87 - isPrivate: true, 88 - isVerified: false, 89 - joined: new Date(Date.UTC(2020, 0, 26, 0, 3, 5, 0)), 90 - location: 'sometimes', 91 - name: 'private account', 92 - pinnedTweetIds: [], 93 - url: 'https://x.com/tomdumont', 94 - userId: '1221221876849995777', 95 - username: 'tomdumont', 96 - website: undefined, 97 - }; 98 - 99 - const scraper = await getScraper(); 100 - 101 - const actual = await scraper.getProfile('tomdumont'); 102 - expect(actual.avatar).toEqual(expected.avatar); 103 - expect(actual.banner).toEqual(expected.banner); 104 - expect(actual.biography).toEqual(expected.biography); 105 - expect(actual.isPrivate).toEqual(expected.isPrivate); 106 - expect(actual.isVerified).toEqual(expected.isVerified); 107 - expect(actual.joined).toEqual(expected.joined); 108 - expect(actual.location).toEqual(expected.location); 109 - expect(actual.name).toEqual(expected.name); 110 - expect(actual.pinnedTweetIds).toEqual(expected.pinnedTweetIds); 111 - expect(actual.url).toEqual(expected.url); 112 - expect(actual.userId).toEqual(expected.userId); 113 - expect(actual.username).toEqual(expected.username); 114 - expect(actual.website).toEqual(expected.website); 115 - }); 116 - 117 - test('scraper cannot get suspended profile', async () => { 118 - const scraper = await getScraper(); 119 - // taken from https://en.wikipedia.org/wiki/Twitter_suspensions#List_of_notable_suspensions 120 - expect(scraper.getProfile('RobertC20041800')).rejects.toThrow(); 121 - }); 122 - 123 - test('scraper cannot get not found profile', async () => { 124 - const scraper = await getScraper(); 125 - expect(scraper.getProfile('sample3123131')).rejects.toThrow(); 126 - }); 127 - 128 - test('scraper can get profile by screen name', async () => { 129 - const scraper = await getScraper(); 130 - await scraper.getProfile('GeminiApp'); 131 - }); 132 - 133 - test('scraper return error on suspended profile', async () => { 134 - const scraper = await getScraper(); 135 - await expect(scraper.getProfile('elon')).rejects.toThrow( 136 - 'User is suspended.', 137 - ); 138 - });
-291
twitter-scraper/src/profile.ts
··· 1 - import { requestApi, RequestApiResult, bearerToken2 } from './api'; 2 - import { TwitterAuth } from './auth'; 3 - import { TwitterApiErrorRaw } from './errors'; 4 - import { apiRequestFactory } from './api-data'; 5 - 6 - export interface CoreUserRaw { 7 - created_at?: string; 8 - name?: string; 9 - screen_name?: string; 10 - } 11 - 12 - export interface LegacyUserRaw { 13 - created_at?: string; 14 - description?: string; 15 - entities?: { 16 - url?: { 17 - urls?: { 18 - url?: string; 19 - expanded_url?: string; 20 - display_url?: string; 21 - indices?: [number, number]; 22 - }[]; 23 - }; 24 - description?: { 25 - // TODO: Get the proper type of this. 26 - urls?: any[]; 27 - }; 28 - }; 29 - favourites_count?: number; 30 - followers_count?: number; 31 - friends_count?: number; 32 - media_count?: number; 33 - statuses_count?: number; 34 - id_str?: string; 35 - listed_count?: number; 36 - name?: string; 37 - location?: string; 38 - geo_enabled?: boolean; 39 - pinned_tweet_ids_str?: string[]; 40 - profile_background_color?: string; 41 - profile_banner_url?: string; 42 - profile_image_url_https?: string; 43 - protected?: boolean; 44 - screen_name?: string; 45 - verified?: boolean; 46 - has_custom_timelines?: boolean; 47 - has_extended_profile?: boolean; 48 - url?: string; 49 - can_dm?: boolean; 50 - id?: number; 51 - // TODO: Get the proper type of this. 52 - utc_offset?: any; 53 - // TODO: Get the proper type of this. 54 - time_zone?: any; 55 - // TODO: Get the proper type of this. 56 - lang?: any; 57 - contributors_enabled?: boolean; 58 - is_translator?: boolean; 59 - is_translation_enabled?: boolean; 60 - profile_background_image_url?: string; 61 - profile_background_image_url_https?: string; 62 - profile_background_tile?: boolean; 63 - profile_image_url?: string; 64 - profile_link_color?: string; 65 - profile_sidebar_border_color?: string; 66 - profile_sidebar_fill_color?: string; 67 - profile_text_color?: string; 68 - profile_use_background_image?: boolean; 69 - default_profile?: boolean; 70 - default_profile_image?: boolean; 71 - can_secret_dm?: boolean; 72 - can_media_tag?: boolean; 73 - following?: boolean; 74 - follow_request_sent?: boolean; 75 - notifications?: boolean; 76 - blocking?: boolean; 77 - subscribed_by?: boolean; 78 - blocked_by?: boolean; 79 - want_retweets?: boolean; 80 - dm_blocked_by?: boolean; 81 - dm_blocking?: boolean; 82 - business_profile_state?: string; 83 - translator_type?: string; 84 - // TODO: Get the proper type of this. 85 - withheld_in_countries?: any[]; 86 - followed_by?: boolean; 87 - } 88 - 89 - /** 90 - * A parsed profile object. 91 - */ 92 - export interface Profile { 93 - avatar?: string; 94 - banner?: string; 95 - biography?: string; 96 - birthday?: string; 97 - followersCount?: number; 98 - followingCount?: number; 99 - friendsCount?: number; 100 - mediaCount?: number; 101 - statusesCount?: number; 102 - isPrivate?: boolean; 103 - isVerified?: boolean; 104 - isBlueVerified?: boolean; 105 - joined?: Date; 106 - likesCount?: number; 107 - listedCount?: number; 108 - location?: string; 109 - name?: string; 110 - pinnedTweetIds?: string[]; 111 - tweetsCount?: number; 112 - url?: string; 113 - userId?: string; 114 - username?: string; 115 - website?: string; 116 - canDm?: boolean; 117 - } 118 - 119 - export interface UserRaw { 120 - data: { 121 - user: { 122 - result: { 123 - __typename?: string; 124 - message?: string; 125 - reason?: string; 126 - rest_id?: string; 127 - is_blue_verified?: boolean; 128 - legacy: LegacyUserRaw; 129 - core?: CoreUserRaw; 130 - avatar?: { 131 - image_url?: string; 132 - }; 133 - location?: { 134 - location?: string; 135 - }; 136 - }; 137 - }; 138 - }; 139 - errors?: TwitterApiErrorRaw[]; 140 - } 141 - 142 - function getAvatarOriginalSizeUrl(avatarUrl: string | undefined) { 143 - return avatarUrl ? avatarUrl.replace('_normal', '') : undefined; 144 - } 145 - 146 - export function parseProfile( 147 - legacy: LegacyUserRaw, 148 - isBlueVerified?: boolean, 149 - ): Profile { 150 - const profile: Profile = { 151 - avatar: getAvatarOriginalSizeUrl(legacy.profile_image_url_https), 152 - banner: legacy.profile_banner_url, 153 - biography: legacy.description, 154 - followersCount: legacy.followers_count, 155 - followingCount: legacy.friends_count, 156 - friendsCount: legacy.friends_count, 157 - mediaCount: legacy.media_count, 158 - isPrivate: legacy.protected ?? false, 159 - isVerified: legacy.verified, 160 - likesCount: legacy.favourites_count, 161 - listedCount: legacy.listed_count, 162 - location: legacy.location, 163 - name: legacy.name, 164 - pinnedTweetIds: legacy.pinned_tweet_ids_str, 165 - tweetsCount: legacy.statuses_count, 166 - url: `https://x.com/${legacy.screen_name}`, 167 - userId: legacy.id_str, 168 - username: legacy.screen_name, 169 - isBlueVerified: isBlueVerified ?? false, 170 - canDm: legacy.can_dm, 171 - }; 172 - 173 - if (legacy.created_at != null) { 174 - profile.joined = new Date(Date.parse(legacy.created_at)); 175 - } 176 - 177 - const urls = legacy.entities?.url?.urls; 178 - if (urls?.length != null && urls?.length > 0) { 179 - profile.website = urls[0].expanded_url; 180 - } 181 - 182 - return profile; 183 - } 184 - 185 - export async function getProfile( 186 - username: string, 187 - auth: TwitterAuth, 188 - ): Promise<RequestApiResult<Profile>> { 189 - const request = apiRequestFactory.createUserByScreenNameRequest(); 190 - request.variables.screen_name = username; 191 - 192 - // Use bearerToken2 for UserByScreenName endpoint 193 - const res = await requestApi<UserRaw>( 194 - request.toRequestUrl(), 195 - auth, 196 - 'GET', 197 - undefined, 198 - undefined, 199 - bearerToken2, 200 - ); 201 - if (!res.success) { 202 - return res; 203 - } 204 - 205 - const { value } = res; 206 - const { errors } = value; 207 - if ( 208 - (!value.data || !value.data.user || !value.data.user.result) && 209 - errors != null && 210 - errors.length > 0 211 - ) { 212 - return { 213 - success: false, 214 - err: new Error(errors.map((e) => e.message).join('\n')), 215 - }; 216 - } 217 - 218 - if (!value.data || !value.data.user || !value.data.user.result) { 219 - return { 220 - success: false, 221 - err: new Error('User not found.'), 222 - }; 223 - } 224 - const { result: user } = value.data.user; 225 - const { legacy } = user; 226 - 227 - if (user.__typename === 'UserUnavailable' && user?.reason === 'Suspended') { 228 - return { 229 - success: false, 230 - err: new Error('User is suspended.'), 231 - }; 232 - } 233 - 234 - if (user.rest_id == null || user.rest_id.length === 0) { 235 - return { 236 - success: false, 237 - err: new Error('rest_id not found.'), 238 - }; 239 - } 240 - 241 - legacy.id_str = user.rest_id; 242 - legacy.screen_name ??= user.core?.screen_name; 243 - legacy.profile_image_url_https ??= user.avatar?.image_url; 244 - legacy.created_at ??= user.core?.created_at; 245 - legacy.location ??= user.location?.location; 246 - legacy.name ??= user.core?.name; 247 - 248 - if (legacy.screen_name == null || legacy.screen_name.length === 0) { 249 - return { 250 - success: false, 251 - err: new Error(`User ${username} does not exist or is private.`), 252 - }; 253 - } 254 - 255 - return { 256 - success: true, 257 - value: parseProfile(legacy, user.is_blue_verified), 258 - }; 259 - } 260 - 261 - const idCache = new Map<string, string>(); 262 - 263 - export async function getUserIdByScreenName( 264 - screenName: string, 265 - auth: TwitterAuth, 266 - ): Promise<RequestApiResult<string>> { 267 - const cached = idCache.get(screenName); 268 - if (cached != null) { 269 - return { success: true, value: cached }; 270 - } 271 - 272 - const profileRes = await getProfile(screenName, auth); 273 - if (!profileRes.success) { 274 - return profileRes; 275 - } 276 - 277 - const profile = profileRes.value; 278 - if (profile.userId != null) { 279 - idCache.set(screenName, profile.userId); 280 - 281 - return { 282 - success: true, 283 - value: profile.userId, 284 - }; 285 - } 286 - 287 - return { 288 - success: false, 289 - err: new Error('User ID is undefined.'), 290 - }; 291 - }
-41
twitter-scraper/src/rate-limit.test.ts
··· 1 - import { ApiError } from './errors'; 2 - import { ErrorRateLimitStrategy } from './rate-limit'; 3 - 4 - test('error rate limit strategy throws error when triggered', async () => { 5 - const strategy = new ErrorRateLimitStrategy(); 6 - 7 - await expect(() => 8 - strategy.onRateLimit({ 9 - fetchParameters: ['/', {}], 10 - response: { 11 - headers: new Headers(), 12 - ok: false, 13 - redirected: false, 14 - status: 0, 15 - statusText: '', 16 - type: 'basic', 17 - url: '', 18 - clone: function (): Response { 19 - throw new Error('Function not implemented.'); 20 - }, 21 - body: null, 22 - bodyUsed: false, 23 - arrayBuffer: function (): Promise<ArrayBuffer> { 24 - throw new Error('Function not implemented.'); 25 - }, 26 - blob: function (): Promise<Blob> { 27 - throw new Error('Function not implemented.'); 28 - }, 29 - formData: function (): Promise<FormData> { 30 - throw new Error('Function not implemented.'); 31 - }, 32 - json: function (): Promise<any> { 33 - throw new Error('Function not implemented.'); 34 - }, 35 - text: function (): Promise<string> { 36 - throw new Error('Function not implemented.'); 37 - }, 38 - }, 39 - }), 40 - ).rejects.toThrow(ApiError); 41 - });
-85
twitter-scraper/src/rate-limit.ts
··· 1 - import { FetchParameters } from './api-types'; 2 - import { ApiError } from './errors'; 3 - import debug from 'debug'; 4 - 5 - const log = debug('twitter-scraper:rate-limit'); 6 - 7 - /** 8 - * Information about a rate-limiting event. Both the request and response 9 - * information are provided. 10 - */ 11 - export interface RateLimitEvent { 12 - /** The complete arguments that were passed to the fetch function. */ 13 - fetchParameters: FetchParameters; 14 - /** The failing HTTP response. */ 15 - response: Response; 16 - } 17 - 18 - /** 19 - * The public interface for all rate-limiting strategies. Library consumers are 20 - * welcome to provide their own implementations of this interface in the Scraper 21 - * constructor options. 22 - * 23 - * The {@link RateLimitEvent} object contains both the request and response 24 - * information associated with the event. 25 - * 26 - * @example 27 - * import { Scraper, RateLimitStrategy } from "@the-convocation/twitter-scraper"; 28 - * 29 - * // A custom rate-limiting implementation that just logs request/response information. 30 - * class ConsoleLogRateLimitStrategy implements RateLimitStrategy { 31 - * async onRateLimit(event: RateLimitEvent): Promise<void> { 32 - * console.log(event.fetchParameters, event.response); 33 - * } 34 - * } 35 - * 36 - * const scraper = new Scraper({ 37 - * rateLimitStrategy: new ConsoleLogRateLimitStrategy(), 38 - * }); 39 - */ 40 - export interface RateLimitStrategy { 41 - /** 42 - * Called when the scraper is rate limited. 43 - * @param event The event information, including the request and response info. 44 - */ 45 - onRateLimit(event: RateLimitEvent): Promise<void>; 46 - } 47 - 48 - /** 49 - * A rate-limiting strategy that simply waits for the current rate limit period to expire. 50 - * This has been known to take up to 13 minutes, in some cases. 51 - */ 52 - export class WaitingRateLimitStrategy implements RateLimitStrategy { 53 - async onRateLimit({ response: res }: RateLimitEvent): Promise<void> { 54 - /* 55 - Known headers at this point: 56 - - x-rate-limit-limit: Maximum number of requests per time period? 57 - - x-rate-limit-reset: UNIX timestamp when the current rate limit will be reset. 58 - - x-rate-limit-remaining: Number of requests remaining in current time period? 59 - */ 60 - const xRateLimitLimit = res.headers.get('x-rate-limit-limit'); 61 - const xRateLimitRemaining = res.headers.get('x-rate-limit-remaining'); 62 - const xRateLimitReset = res.headers.get('x-rate-limit-reset'); 63 - 64 - log( 65 - `Rate limit event: limit=${xRateLimitLimit}, remaining=${xRateLimitRemaining}, reset=${xRateLimitReset}`, 66 - ); 67 - 68 - if (xRateLimitRemaining == '0' && xRateLimitReset) { 69 - const currentTime = new Date().valueOf() / 1000; 70 - const timeDeltaMs = 1000 * (parseInt(xRateLimitReset) - currentTime); 71 - 72 - // I have seen this block for 800s (~13 *minutes*) 73 - await new Promise((resolve) => setTimeout(resolve, timeDeltaMs)); 74 - } 75 - } 76 - } 77 - 78 - /** 79 - * A rate-limiting strategy that throws an {@link ApiError} when a rate limiting event occurs. 80 - */ 81 - export class ErrorRateLimitStrategy implements RateLimitStrategy { 82 - async onRateLimit({ response: res }: RateLimitEvent): Promise<void> { 83 - throw await ApiError.fromResponse(res); 84 - } 85 - }
-59
twitter-scraper/src/relationships.test.ts
··· 1 - import { getScraper } from './test-utils'; 2 - 3 - test('scraper can get profile followers', async () => { 4 - const scraper = await getScraper(); 5 - 6 - const seenProfiles = new Map<string, boolean>(); 7 - const maxProfiles = 50; 8 - let nProfiles = 0; 9 - 10 - const profiles = await scraper.getFollowers( 11 - '1425600122885394432', 12 - maxProfiles, 13 - ); 14 - 15 - for await (const profile of profiles) { 16 - nProfiles++; 17 - 18 - const id = profile.userId; 19 - expect(id).toBeTruthy(); 20 - 21 - if (id != null) { 22 - expect(seenProfiles.has(id)).toBeFalsy(); 23 - seenProfiles.set(id, true); 24 - } 25 - 26 - expect(profile.username).toBeTruthy(); 27 - } 28 - 29 - expect(nProfiles).toEqual(maxProfiles); 30 - }); 31 - 32 - test('scraper can get profile following', async () => { 33 - const scraper = await getScraper(); 34 - 35 - const seenProfiles = new Map<string, boolean>(); 36 - const maxProfiles = 50; 37 - let nProfiles = 0; 38 - 39 - const profiles = await scraper.getFollowing( 40 - '1425600122885394432', 41 - maxProfiles, 42 - ); 43 - 44 - for await (const profile of profiles) { 45 - nProfiles++; 46 - 47 - const id = profile.userId; 48 - expect(id).toBeTruthy(); 49 - 50 - if (id != null) { 51 - expect(seenProfiles.has(id)).toBeFalsy(); 52 - seenProfiles.set(id, true); 53 - } 54 - 55 - expect(profile.username).toBeTruthy(); 56 - } 57 - 58 - expect(nProfiles).toEqual(maxProfiles); 59 - });
-157
twitter-scraper/src/relationships.ts
··· 1 - import { bearerToken2, requestApi } from './api'; 2 - import { TwitterAuth } from './auth'; 3 - import { Profile } from './profile'; 4 - import { QueryProfilesResponse } from './timeline-v1'; 5 - import { getUserTimeline } from './timeline-async'; 6 - import { 7 - RelationshipTimeline, 8 - parseRelationshipTimeline, 9 - } from './timeline-relationship'; 10 - import { AuthenticationError } from './errors'; 11 - import { apiRequestFactory } from './api-data'; 12 - 13 - export function getFollowing( 14 - userId: string, 15 - maxProfiles: number, 16 - auth: TwitterAuth, 17 - ): AsyncGenerator<Profile, void> { 18 - return getUserTimeline(userId, maxProfiles, (q, mt, c) => { 19 - return fetchProfileFollowing(q, mt, auth, c); 20 - }); 21 - } 22 - 23 - export function getFollowers( 24 - userId: string, 25 - maxProfiles: number, 26 - auth: TwitterAuth, 27 - ): AsyncGenerator<Profile, void> { 28 - return getUserTimeline(userId, maxProfiles, (q, mt, c) => { 29 - return fetchProfileFollowers(q, mt, auth, c); 30 - }); 31 - } 32 - 33 - export async function fetchProfileFollowing( 34 - userId: string, 35 - maxProfiles: number, 36 - auth: TwitterAuth, 37 - cursor?: string, 38 - ): Promise<QueryProfilesResponse> { 39 - if (!(await auth.isLoggedIn())) { 40 - throw new AuthenticationError( 41 - 'Scraper is not logged-in for profile following.', 42 - ); 43 - } 44 - 45 - const timeline = await getFollowingTimeline( 46 - userId, 47 - maxProfiles, 48 - auth, 49 - cursor, 50 - ); 51 - 52 - return parseRelationshipTimeline(timeline); 53 - } 54 - 55 - export async function fetchProfileFollowers( 56 - userId: string, 57 - maxProfiles: number, 58 - auth: TwitterAuth, 59 - cursor?: string, 60 - ): Promise<QueryProfilesResponse> { 61 - if (!(await auth.isLoggedIn())) { 62 - throw new AuthenticationError( 63 - 'Scraper is not logged-in for profile followers.', 64 - ); 65 - } 66 - 67 - const timeline = await getFollowersTimeline( 68 - userId, 69 - maxProfiles, 70 - auth, 71 - cursor, 72 - ); 73 - 74 - return parseRelationshipTimeline(timeline); 75 - } 76 - 77 - async function getFollowingTimeline( 78 - userId: string, 79 - maxItems: number, 80 - auth: TwitterAuth, 81 - cursor?: string, 82 - ): Promise<RelationshipTimeline> { 83 - if (!auth.isLoggedIn()) { 84 - throw new AuthenticationError( 85 - 'Scraper is not logged-in for profile following.', 86 - ); 87 - } 88 - 89 - if (maxItems > 50) { 90 - maxItems = 50; 91 - } 92 - 93 - const followingRequest = apiRequestFactory.createFollowingRequest(); 94 - followingRequest.variables.userId = userId; 95 - followingRequest.variables.count = maxItems; 96 - followingRequest.variables.includePromotedContent = false; 97 - 98 - if (cursor != null && cursor != '') { 99 - followingRequest.variables.cursor = cursor; 100 - } 101 - 102 - const res = await requestApi<RelationshipTimeline>( 103 - followingRequest.toRequestUrl(), 104 - auth, 105 - 'GET', 106 - undefined, 107 - undefined, 108 - bearerToken2, 109 - ); 110 - 111 - if (!res.success) { 112 - throw res.err; 113 - } 114 - 115 - return res.value; 116 - } 117 - 118 - async function getFollowersTimeline( 119 - userId: string, 120 - maxItems: number, 121 - auth: TwitterAuth, 122 - cursor?: string, 123 - ): Promise<RelationshipTimeline> { 124 - if (!auth.isLoggedIn()) { 125 - throw new AuthenticationError( 126 - 'Scraper is not logged-in for profile followers.', 127 - ); 128 - } 129 - 130 - if (maxItems > 50) { 131 - maxItems = 50; 132 - } 133 - 134 - const followersRequest = apiRequestFactory.createFollowersRequest(); 135 - followersRequest.variables.userId = userId; 136 - followersRequest.variables.count = maxItems; 137 - followersRequest.variables.includePromotedContent = false; 138 - 139 - if (cursor != null && cursor != '') { 140 - followersRequest.variables.cursor = cursor; 141 - } 142 - 143 - const res = await requestApi<RelationshipTimeline>( 144 - followersRequest.toRequestUrl(), 145 - auth, 146 - 'GET', 147 - undefined, 148 - undefined, 149 - bearerToken2, 150 - ); 151 - 152 - if (!res.success) { 153 - throw res.err; 154 - } 155 - 156 - return res.value; 157 - }
-80
twitter-scraper/src/requests.ts
··· 1 - import { Cookie, CookieJar } from 'tough-cookie'; 2 - import setCookie from 'set-cookie-parser'; 3 - import type { Headers as HeadersPolyfill } from 'headers-polyfill'; 4 - import debug from 'debug'; 5 - 6 - const log = debug('twitter-scraper:requests'); 7 - 8 - /** 9 - * Updates a cookie jar with the Set-Cookie headers from the provided Headers instance. 10 - * @param cookieJar The cookie jar to update. 11 - * @param headers The response headers to populate the cookie jar with. 12 - */ 13 - export async function updateCookieJar( 14 - cookieJar: CookieJar, 15 - headers: Headers | HeadersPolyfill, 16 - ) { 17 - // Try to use getSetCookie() if available (proper way to get all set-cookie headers) 18 - let setCookieHeaders: string[] = []; 19 - 20 - if (typeof headers.getSetCookie === 'function') { 21 - setCookieHeaders = headers.getSetCookie(); 22 - } else { 23 - // Fallback: get the single set-cookie header 24 - const setCookieHeader = headers.get('set-cookie'); 25 - if (setCookieHeader) { 26 - // Split combined set-cookie headers 27 - setCookieHeaders = setCookie.splitCookiesString(setCookieHeader); 28 - } 29 - } 30 - 31 - if (setCookieHeaders.length > 0) { 32 - for (const cookieStr of setCookieHeaders) { 33 - const cookie = Cookie.parse(cookieStr); 34 - if (!cookie) { 35 - log(`Failed to parse cookie: ${cookieStr.substring(0, 100)}`); 36 - continue; 37 - } 38 - 39 - // Skip cookies that are being explicitly deleted (Max-Age=0 or expired) 40 - // This prevents twitter from clearing important cookies like ct0 41 - if ( 42 - cookie.maxAge === 0 || 43 - (cookie.expires && cookie.expires < new Date()) 44 - ) { 45 - if (cookie.key === 'ct0') { 46 - log(`Skipping deletion of ct0 cookie (Max-Age=0)`); 47 - } 48 - continue; 49 - } 50 - 51 - try { 52 - const url = `${cookie.secure ? 'https' : 'http'}://${cookie.domain}${ 53 - cookie.path 54 - }`; 55 - await cookieJar.setCookie(cookie, url); 56 - if (cookie.key === 'ct0') { 57 - log( 58 - `Successfully set ct0 cookie with value: ${cookie.value.substring( 59 - 0, 60 - 20, 61 - )}...`, 62 - ); 63 - } 64 - } catch (err) { 65 - // Log cookie setting errors 66 - log(`Failed to set cookie ${cookie.key}: ${err}`); 67 - if (cookie.key === 'ct0') { 68 - log(`FAILED to set ct0 cookie! Error: ${err}`); 69 - } 70 - } 71 - } 72 - } else if (typeof document !== 'undefined') { 73 - for (const cookie of document.cookie.split(';')) { 74 - const hardCookie = Cookie.parse(cookie); 75 - if (hardCookie) { 76 - await cookieJar.setCookie(hardCookie, document.location.toString()); 77 - } 78 - } 79 - } 80 - }
-38
twitter-scraper/src/scraper.test.ts
··· 1 - import { ErrorRateLimitStrategy } from './rate-limit'; 2 - import { Scraper } from './scraper'; 3 - 4 - test('scraper uses request transform when provided', async () => { 5 - const scraper = new Scraper({ 6 - transform: { 7 - // Should throw "TypeError: Only absolute URLs are supported" 8 - request: () => [''], 9 - }, 10 - }); 11 - 12 - await expect(scraper.getLatestTweet('twitter')).rejects.toThrowError( 13 - TypeError, 14 - ); 15 - }); 16 - 17 - test('scraper uses response transform when provided', async () => { 18 - const scraper = new Scraper({ 19 - transform: { 20 - response: (response) => 21 - new Proxy(response, { 22 - get(target, p, receiver) { 23 - if (p === 'status') { 24 - return 400; 25 - } 26 - 27 - if (p === 'ok') { 28 - return false; 29 - } 30 - 31 - return Reflect.get(target, p, receiver); 32 - }, 33 - }), 34 - }, 35 - }); 36 - 37 - await expect(scraper.getLatestTweet('twitter')).rejects.toThrowError(); 38 - });
-626
twitter-scraper/src/scraper.ts
··· 1 - import { Cookie } from 'tough-cookie'; 2 - import { bearerToken, FetchTransformOptions, RequestApiResult } from './api'; 3 - import { TwitterAuth, TwitterAuthOptions, TwitterGuestAuth } from './auth'; 4 - import { FlowSubtaskHandler, TwitterUserAuth } from './auth-user'; 5 - import { getProfile, getUserIdByScreenName, Profile } from './profile'; 6 - import { 7 - fetchSearchProfiles, 8 - fetchSearchTweets, 9 - SearchMode, 10 - searchProfiles, 11 - searchTweets, 12 - } from './search'; 13 - import { 14 - fetchProfileFollowing, 15 - fetchProfileFollowers, 16 - getFollowing, 17 - getFollowers, 18 - } from './relationships'; 19 - import { QueryProfilesResponse, QueryTweetsResponse } from './timeline-v1'; 20 - import { getTrends } from './trends'; 21 - import { 22 - Tweet, 23 - getTweetAnonymous, 24 - getTweets, 25 - getLatestTweet, 26 - getLikedTweets, 27 - getTweetWhere, 28 - getTweetsWhere, 29 - getTweetsByUserId, 30 - TweetQuery, 31 - getTweet, 32 - fetchListTweets, 33 - getTweetsAndRepliesByUserId, 34 - getTweetsAndReplies, 35 - fetchLikedTweets, 36 - } from './tweets'; 37 - import fetch from 'cross-fetch'; 38 - import { RateLimitStrategy } from './rate-limit'; 39 - import { 40 - DmConversationTimeline, 41 - DmInbox, 42 - DmMessageEntry, 43 - DmCursorOptions, 44 - getDmConversation, 45 - getDmMessages, 46 - getDmInbox, 47 - findDmConversationsByUserId, 48 - DmConversation, 49 - } from './direct-messages'; 50 - 51 - const twUrl = 'https://x.com'; 52 - 53 - export interface ScraperOptions { 54 - /** 55 - * An alternative fetch function to use instead of the default fetch function. This may be useful 56 - * in nonstandard runtime environments, such as edge workers. 57 - */ 58 - fetch: typeof fetch; 59 - 60 - /** 61 - * Additional options that control how requests and responses are processed. This can be used to 62 - * proxy requests through other hosts, for example. 63 - */ 64 - transform: Partial<FetchTransformOptions>; 65 - 66 - /** 67 - * A handling strategy for rate limits (HTTP 429). 68 - */ 69 - rateLimitStrategy: RateLimitStrategy; 70 - 71 - /** 72 - * Experimental features that may be added, changed, or removed at any time. Use with caution. 73 - */ 74 - experimental: { 75 - /** 76 - * Enables the generation of the `x-client-transaction-id` header on requests. This may resolve some errors. 77 - */ 78 - xClientTransactionId: boolean; 79 - /** 80 - * Enables the generation of the `x-xp-forwarded-for` header on requests. This may resolve some errors. 81 - */ 82 - xpff: boolean; 83 - }; 84 - } 85 - 86 - /** 87 - * An interface to Twitter's undocumented API. 88 - * - Reusing Scraper objects is recommended to minimize the time spent authenticating unnecessarily. 89 - */ 90 - export class Scraper { 91 - private auth!: TwitterAuth; 92 - private authTrends!: TwitterAuth; 93 - private token: string; 94 - 95 - /** 96 - * Creates a new Scraper object. 97 - * - Scrapers maintain their own guest tokens for Twitter's internal API. 98 - * - Reusing Scraper objects is recommended to minimize the time spent authenticating unnecessarily. 99 - */ 100 - constructor(private readonly options?: Partial<ScraperOptions>) { 101 - this.token = bearerToken; 102 - this.useGuestAuth(); 103 - } 104 - 105 - /** 106 - * Registers a subtask handler for the given subtask ID. This 107 - * will override any existing handler for the same subtask. 108 - * @param subtaskId The ID of the subtask to register the handler for. 109 - * @param subtaskHandler The handler function to register. 110 - */ 111 - public registerAuthSubtaskHandler( 112 - subtaskId: string, 113 - subtaskHandler: FlowSubtaskHandler, 114 - ): void { 115 - if (this.auth instanceof TwitterUserAuth) { 116 - this.auth.registerSubtaskHandler(subtaskId, subtaskHandler); 117 - } 118 - 119 - if (this.authTrends instanceof TwitterUserAuth) { 120 - this.authTrends.registerSubtaskHandler(subtaskId, subtaskHandler); 121 - } 122 - } 123 - 124 - /** 125 - * Initializes auth properties using a guest token. 126 - * Used when creating a new instance of this class, and when logging out. 127 - * @internal 128 - */ 129 - private useGuestAuth() { 130 - this.auth = new TwitterGuestAuth(this.token, this.getAuthOptions()); 131 - this.authTrends = new TwitterGuestAuth(this.token, this.getAuthOptions()); 132 - } 133 - 134 - /** 135 - * Fetches a Twitter profile. 136 - * @param username The Twitter username of the profile to fetch, without an `@` at the beginning. 137 - * @returns The requested {@link Profile}. 138 - */ 139 - public async getProfile(username: string): Promise<Profile> { 140 - const res = await getProfile(username, this.auth); 141 - return this.handleResponse(res); 142 - } 143 - 144 - /** 145 - * Fetches the user ID corresponding to the provided screen name. 146 - * @param screenName The Twitter screen name of the profile to fetch. 147 - * @returns The ID of the corresponding account. 148 - */ 149 - public async getUserIdByScreenName(screenName: string): Promise<string> { 150 - const res = await getUserIdByScreenName(screenName, this.auth); 151 - return this.handleResponse(res); 152 - } 153 - 154 - /** 155 - * Fetches tweets from Twitter. 156 - * @param query The search query. Any Twitter-compatible query format can be used. 157 - * @param maxTweets The maximum number of tweets to return. 158 - * @param includeReplies Whether or not replies should be included in the response. 159 - * @param searchMode The category filter to apply to the search. Defaults to `Top`. 160 - * @returns An {@link AsyncGenerator} of tweets matching the provided filters. 161 - */ 162 - public searchTweets( 163 - query: string, 164 - maxTweets: number, 165 - searchMode: SearchMode = SearchMode.Top, 166 - ): AsyncGenerator<Tweet, void> { 167 - return searchTweets(query, maxTweets, searchMode, this.auth); 168 - } 169 - 170 - /** 171 - * Fetches profiles from Twitter. 172 - * @param query The search query. Any Twitter-compatible query format can be used. 173 - * @param maxProfiles The maximum number of profiles to return. 174 - * @returns An {@link AsyncGenerator} of tweets matching the provided filter(s). 175 - */ 176 - public searchProfiles( 177 - query: string, 178 - maxProfiles: number, 179 - ): AsyncGenerator<Profile, void> { 180 - return searchProfiles(query, maxProfiles, this.auth); 181 - } 182 - 183 - /** 184 - * Fetches tweets from Twitter. 185 - * @param query The search query. Any Twitter-compatible query format can be used. 186 - * @param maxTweets The maximum number of tweets to return. 187 - * @param includeReplies Whether or not replies should be included in the response. 188 - * @param searchMode The category filter to apply to the search. Defaults to `Top`. 189 - * @param cursor The search cursor, which can be passed into further requests for more results. 190 - * @returns A page of results, containing a cursor that can be used in further requests. 191 - */ 192 - public fetchSearchTweets( 193 - query: string, 194 - maxTweets: number, 195 - searchMode: SearchMode, 196 - cursor?: string, 197 - ): Promise<QueryTweetsResponse> { 198 - return fetchSearchTweets(query, maxTweets, searchMode, this.auth, cursor); 199 - } 200 - 201 - /** 202 - * Fetches profiles from Twitter. 203 - * @param query The search query. Any Twitter-compatible query format can be used. 204 - * @param maxProfiles The maximum number of profiles to return. 205 - * @param cursor The search cursor, which can be passed into further requests for more results. 206 - * @returns A page of results, containing a cursor that can be used in further requests. 207 - */ 208 - public fetchSearchProfiles( 209 - query: string, 210 - maxProfiles: number, 211 - cursor?: string, 212 - ): Promise<QueryProfilesResponse> { 213 - return fetchSearchProfiles(query, maxProfiles, this.auth, cursor); 214 - } 215 - 216 - /** 217 - * Fetches list tweets from Twitter. 218 - * @param listId The list id 219 - * @param maxTweets The maximum number of tweets to return. 220 - * @param cursor The search cursor, which can be passed into further requests for more results. 221 - * @returns A page of results, containing a cursor that can be used in further requests. 222 - */ 223 - public fetchListTweets( 224 - listId: string, 225 - maxTweets: number, 226 - cursor?: string, 227 - ): Promise<QueryTweetsResponse> { 228 - return fetchListTweets(listId, maxTweets, cursor, this.auth); 229 - } 230 - 231 - /** 232 - * Fetch the tweets a user has liked 233 - * @param userId The user whose liked tweets should be returned 234 - * @param maxTweets The maximum number of tweets to return. 235 - * @param cursor The search cursor, which can be passed into further requests for more results. 236 - * @returns A page of results, containing a cursor that can be used in further requests. 237 - */ 238 - public fetchLikedTweets( 239 - userId: string, 240 - maxTweets: number, 241 - cursor?: string, 242 - ): Promise<QueryTweetsResponse> { 243 - return fetchLikedTweets(userId, maxTweets, cursor, this.auth); 244 - } 245 - 246 - /** 247 - * Fetch the profiles a user is following 248 - * @param userId The user whose following should be returned 249 - * @param maxProfiles The maximum number of profiles to return. 250 - * @returns An {@link AsyncGenerator} of following profiles for the provided user. 251 - */ 252 - public getFollowing( 253 - userId: string, 254 - maxProfiles: number, 255 - ): AsyncGenerator<Profile, void> { 256 - return getFollowing(userId, maxProfiles, this.auth); 257 - } 258 - 259 - /** 260 - * Fetch the profiles that follow a user 261 - * @param userId The user whose followers should be returned 262 - * @param maxProfiles The maximum number of profiles to return. 263 - * @returns An {@link AsyncGenerator} of profiles following the provided user. 264 - */ 265 - public getFollowers( 266 - userId: string, 267 - maxProfiles: number, 268 - ): AsyncGenerator<Profile, void> { 269 - return getFollowers(userId, maxProfiles, this.auth); 270 - } 271 - 272 - /** 273 - * Fetches following profiles from Twitter. 274 - * @param userId The user whose following should be returned 275 - * @param maxProfiles The maximum number of profiles to return. 276 - * @param cursor The search cursor, which can be passed into further requests for more results. 277 - * @returns A page of results, containing a cursor that can be used in further requests. 278 - */ 279 - public fetchProfileFollowing( 280 - userId: string, 281 - maxProfiles: number, 282 - cursor?: string, 283 - ): Promise<QueryProfilesResponse> { 284 - return fetchProfileFollowing(userId, maxProfiles, this.auth, cursor); 285 - } 286 - 287 - /** 288 - * Fetches profile followers from Twitter. 289 - * @param userId The user whose following should be returned 290 - * @param maxProfiles The maximum number of profiles to return. 291 - * @param cursor The search cursor, which can be passed into further requests for more results. 292 - * @returns A page of results, containing a cursor that can be used in further requests. 293 - */ 294 - public fetchProfileFollowers( 295 - userId: string, 296 - maxProfiles: number, 297 - cursor?: string, 298 - ): Promise<QueryProfilesResponse> { 299 - return fetchProfileFollowers(userId, maxProfiles, this.auth, cursor); 300 - } 301 - 302 - /** 303 - * Fetches the current trends from Twitter. 304 - * @returns The current list of trends. 305 - */ 306 - public getTrends(): Promise<string[]> { 307 - return getTrends(this.authTrends); 308 - } 309 - 310 - /** 311 - * Fetches tweets from a Twitter user. 312 - * @param user The user whose tweets should be returned. 313 - * @param maxTweets The maximum number of tweets to return. Defaults to `200`. 314 - * @returns An {@link AsyncGenerator} of tweets from the provided user. 315 - */ 316 - public getTweets(user: string, maxTweets = 200): AsyncGenerator<Tweet> { 317 - return getTweets(user, maxTweets, this.auth); 318 - } 319 - 320 - /** 321 - * Fetches liked tweets from a Twitter user. Requires authentication. 322 - * @param user The user whose likes should be returned. 323 - * @param maxTweets The maximum number of tweets to return. Defaults to `200`. 324 - * @returns An {@link AsyncGenerator} of liked tweets from the provided user. 325 - */ 326 - public getLikedTweets(user: string, maxTweets = 200): AsyncGenerator<Tweet> { 327 - return getLikedTweets(user, maxTweets, this.auth); 328 - } 329 - 330 - /** 331 - * Fetches tweets from a Twitter user using their ID. 332 - * @param userId The user whose tweets should be returned. 333 - * @param maxTweets The maximum number of tweets to return. Defaults to `200`. 334 - * @returns An {@link AsyncGenerator} of tweets from the provided user. 335 - */ 336 - public getTweetsByUserId( 337 - userId: string, 338 - maxTweets = 200, 339 - ): AsyncGenerator<Tweet, void> { 340 - return getTweetsByUserId(userId, maxTweets, this.auth); 341 - } 342 - 343 - /** 344 - * Fetches tweets and replies from a Twitter user. 345 - * @param user The user whose tweets should be returned. 346 - * @param maxTweets The maximum number of tweets to return. Defaults to `200`. 347 - * @returns An {@link AsyncGenerator} of tweets from the provided user. 348 - */ 349 - public getTweetsAndReplies( 350 - user: string, 351 - maxTweets = 200, 352 - ): AsyncGenerator<Tweet> { 353 - return getTweetsAndReplies(user, maxTweets, this.auth); 354 - } 355 - 356 - /** 357 - * Fetches tweets and replies from a Twitter user using their ID. 358 - * @param userId The user whose tweets should be returned. 359 - * @param maxTweets The maximum number of tweets to return. Defaults to `200`. 360 - * @returns An {@link AsyncGenerator} of tweets from the provided user. 361 - */ 362 - public getTweetsAndRepliesByUserId( 363 - userId: string, 364 - maxTweets = 200, 365 - ): AsyncGenerator<Tweet, void> { 366 - return getTweetsAndRepliesByUserId(userId, maxTweets, this.auth); 367 - } 368 - 369 - /** 370 - * Fetches the first tweet matching the given query. 371 - * 372 - * Example: 373 - * ```js 374 - * const timeline = scraper.getTweets('user', 200); 375 - * const retweet = await scraper.getTweetWhere(timeline, { isRetweet: true }); 376 - * ``` 377 - * @param tweets The {@link AsyncIterable} of tweets to search through. 378 - * @param query A query to test **all** tweets against. This may be either an 379 - * object of key/value pairs or a predicate. If this query is an object, all 380 - * key/value pairs must match a {@link Tweet} for it to be returned. If this query 381 - * is a predicate, it must resolve to `true` for a {@link Tweet} to be returned. 382 - * - All keys are optional. 383 - * - If specified, the key must be implemented by that of {@link Tweet}. 384 - */ 385 - public getTweetWhere( 386 - tweets: AsyncIterable<Tweet>, 387 - query: TweetQuery, 388 - ): Promise<Tweet | null> { 389 - return getTweetWhere(tweets, query); 390 - } 391 - 392 - /** 393 - * Fetches all tweets matching the given query. 394 - * 395 - * Example: 396 - * ```js 397 - * const timeline = scraper.getTweets('user', 200); 398 - * const retweets = await scraper.getTweetsWhere(timeline, { isRetweet: true }); 399 - * ``` 400 - * @param tweets The {@link AsyncIterable} of tweets to search through. 401 - * @param query A query to test **all** tweets against. This may be either an 402 - * object of key/value pairs or a predicate. If this query is an object, all 403 - * key/value pairs must match a {@link Tweet} for it to be returned. If this query 404 - * is a predicate, it must resolve to `true` for a {@link Tweet} to be returned. 405 - * - All keys are optional. 406 - * - If specified, the key must be implemented by that of {@link Tweet}. 407 - */ 408 - public getTweetsWhere( 409 - tweets: AsyncIterable<Tweet>, 410 - query: TweetQuery, 411 - ): Promise<Tweet[]> { 412 - return getTweetsWhere(tweets, query); 413 - } 414 - 415 - /** 416 - * Fetches the most recent tweet from a Twitter user. 417 - * @param user The user whose latest tweet should be returned. 418 - * @param includeRetweets Whether or not to include retweets. Defaults to `false`. 419 - * @returns The {@link Tweet} object or `null`/`undefined` if it couldn't be fetched. 420 - */ 421 - public getLatestTweet( 422 - user: string, 423 - includeRetweets = false, 424 - max = 200, 425 - ): Promise<Tweet | null | void> { 426 - return getLatestTweet(user, includeRetweets, max, this.auth); 427 - } 428 - 429 - /** 430 - * Fetches a single tweet. 431 - * @param id The ID of the tweet to fetch. 432 - * @returns The {@link Tweet} object, or `null` if it couldn't be fetched. 433 - */ 434 - public getTweet(id: string): Promise<Tweet | null> { 435 - if (this.auth instanceof TwitterUserAuth) { 436 - return getTweet(id, this.auth); 437 - } else { 438 - return getTweetAnonymous(id, this.auth); 439 - } 440 - } 441 - 442 - /** 443 - * Retrieves the direct message inbox for the authenticated user. 444 - * 445 - * @return A promise that resolves to an object representing the direct message inbox. 446 - */ 447 - public getDmInbox(): Promise<DmInbox> { 448 - return getDmInbox(this.auth); 449 - } 450 - 451 - /** 452 - * Retrieves the direct message conversation for the specified conversation ID. 453 - * 454 - * @param conversationId - The unique identifier of the DM conversation to retrieve. 455 - * @param cursor - Use `maxId` to get messages before a message ID (older messages), or `minId` to get messages after a message ID (newer messages). 456 - * @return A promise that resolves to the timeline of the DM conversation. 457 - */ 458 - public getDmConversation( 459 - conversationId: string, 460 - cursor?: DmCursorOptions, 461 - ): Promise<DmConversationTimeline> { 462 - return getDmConversation(conversationId, cursor, this.auth); 463 - } 464 - 465 - /** 466 - * Retrieves direct messages from a specific conversation. 467 - * 468 - * @param conversationId - The unique identifier of the conversation to fetch messages from. 469 - * @param [maxMessages=20] - The maximum number of messages to retrieve per request. 470 - * @param cursor - Use `maxId` to get messages before a message ID (older messages), or `minId` to get messages after a message ID (newer messages). 471 - * @returns An {@link AsyncGenerator} of messages from the provided conversation. 472 - */ 473 - public getDmMessages( 474 - conversationId: string, 475 - maxMessages = 20, 476 - cursor?: DmCursorOptions, 477 - ): AsyncGenerator<DmMessageEntry, void> { 478 - return getDmMessages(conversationId, maxMessages, cursor, this.auth); 479 - } 480 - 481 - /** 482 - * Retrieves a list of direct message conversations for a specific user based on their user ID. 483 - * 484 - * @param inbox - The DM inbox containing all available conversations. 485 - * @param userId - The unique identifier of the user whose DM conversations are to be retrieved. 486 - * @return An array of DM conversations associated with the specified user ID. 487 - */ 488 - public findDmConversationsByUserId( 489 - inbox: DmInbox, 490 - userId: string, 491 - ): DmConversation[] { 492 - return findDmConversationsByUserId(inbox, userId); 493 - } 494 - 495 - /** 496 - * Returns if the scraper has a guest token. The token may not be valid. 497 - * @returns `true` if the scraper has a guest token; otherwise `false`. 498 - */ 499 - public hasGuestToken(): boolean { 500 - return this.auth.hasToken() || this.authTrends.hasToken(); 501 - } 502 - 503 - /** 504 - * Returns if the scraper is logged in as a real user. 505 - * @returns `true` if the scraper is logged in with a real user account; otherwise `false`. 506 - */ 507 - public async isLoggedIn(): Promise<boolean> { 508 - return ( 509 - (await this.auth.isLoggedIn()) && (await this.authTrends.isLoggedIn()) 510 - ); 511 - } 512 - 513 - /** 514 - * Login to Twitter as a real Twitter account. This enables running 515 - * searches. 516 - * @param username The username of the Twitter account to login with. 517 - * @param password The password of the Twitter account to login with. 518 - * @param email The email to log in with, if you have email confirmation enabled. 519 - * @param twoFactorSecret The secret to generate two factor authentication tokens with, if you have two factor authentication enabled. 520 - */ 521 - public async login( 522 - username: string, 523 - password: string, 524 - email?: string, 525 - twoFactorSecret?: string, 526 - ): Promise<void> { 527 - // Swap in a real authorizer for all requests 528 - const userAuth = new TwitterUserAuth(this.token, this.getAuthOptions()); 529 - await userAuth.login(username, password, email, twoFactorSecret); 530 - this.auth = userAuth; 531 - this.authTrends = userAuth; 532 - } 533 - 534 - /** 535 - * Log out of Twitter. 536 - */ 537 - public async logout(): Promise<void> { 538 - await this.auth.logout(); 539 - await this.authTrends.logout(); 540 - 541 - // Swap in guest authorizers for all requests 542 - this.useGuestAuth(); 543 - } 544 - 545 - /** 546 - * Retrieves all cookies for the current session. 547 - * @returns All cookies for the current session. 548 - */ 549 - public async getCookies(): Promise<Cookie[]> { 550 - return await this.authTrends 551 - .cookieJar() 552 - .getCookies( 553 - typeof document !== 'undefined' ? document.location.toString() : twUrl, 554 - ); 555 - } 556 - 557 - /** 558 - * Set cookies for the current session. 559 - * @param cookies The cookies to set for the current session. 560 - */ 561 - public async setCookies(cookies: (string | Cookie)[]): Promise<void> { 562 - const userAuth = new TwitterUserAuth(this.token, this.getAuthOptions()); 563 - for (const cookie of cookies) { 564 - await userAuth.cookieJar().setCookie(cookie, twUrl); 565 - } 566 - 567 - this.auth = userAuth; 568 - this.authTrends = userAuth; 569 - } 570 - 571 - /** 572 - * Clear all cookies for the current session. 573 - */ 574 - public async clearCookies(): Promise<void> { 575 - await this.auth.cookieJar().removeAllCookies(); 576 - await this.authTrends.cookieJar().removeAllCookies(); 577 - } 578 - 579 - /** 580 - * Sets the optional cookie to be used in requests. 581 - * @param _cookie The cookie to be used in requests. 582 - * @deprecated This function no longer represents any part of Twitter's auth flow. 583 - * @returns This scraper instance. 584 - */ 585 - // eslint-disable-next-line @typescript-eslint/no-unused-vars 586 - public withCookie(_cookie: string): Scraper { 587 - console.warn( 588 - 'Warning: Scraper#withCookie is deprecated and will be removed in a later version. Use Scraper#login or Scraper#setCookies instead.', 589 - ); 590 - return this; 591 - } 592 - 593 - /** 594 - * Sets the optional CSRF token to be used in requests. 595 - * @param _token The CSRF token to be used in requests. 596 - * @deprecated This function no longer represents any part of Twitter's auth flow. 597 - * @returns This scraper instance. 598 - */ 599 - // eslint-disable-next-line @typescript-eslint/no-unused-vars 600 - public withXCsrfToken(_token: string): Scraper { 601 - console.warn( 602 - 'Warning: Scraper#withXCsrfToken is deprecated and will be removed in a later version.', 603 - ); 604 - return this; 605 - } 606 - 607 - private getAuthOptions(): Partial<TwitterAuthOptions> { 608 - return { 609 - fetch: this.options?.fetch, 610 - transform: this.options?.transform, 611 - rateLimitStrategy: this.options?.rateLimitStrategy, 612 - experimental: { 613 - xClientTransactionId: this.options?.experimental?.xClientTransactionId, 614 - xpff: this.options?.experimental?.xpff, 615 - }, 616 - }; 617 - } 618 - 619 - private handleResponse<T>(res: RequestApiResult<T>): T { 620 - if (!res.success) { 621 - throw res.err; 622 - } 623 - 624 - return res.value; 625 - } 626 - }
-79
twitter-scraper/src/search.test.ts
··· 1 - import { getScraper } from './test-utils'; 2 - import { SearchMode } from './search'; 3 - import { QueryTweetsResponse } from './timeline-v1'; 4 - 5 - test('scraper can process search cursor', async () => { 6 - const scraper = await getScraper(); 7 - 8 - let cursor: string | undefined = undefined; 9 - const maxTweets = 30; 10 - let nTweets = 0; 11 - while (nTweets < maxTweets) { 12 - const res: QueryTweetsResponse = await scraper.fetchSearchTweets( 13 - 'twitter', 14 - maxTweets, 15 - SearchMode.Top, 16 - cursor, 17 - ); 18 - 19 - expect(res.next).toBeTruthy(); 20 - 21 - nTweets += res.tweets.length; 22 - cursor = res.next; 23 - } 24 - }, 30000); 25 - 26 - test('scraper can search profiles', async () => { 27 - const scraper = await getScraper(); 28 - 29 - const seenProfiles = new Map<string, boolean>(); 30 - const maxProfiles = 150; 31 - let nProfiles = 0; 32 - 33 - const profiles = scraper.searchProfiles('Twitter', maxProfiles); 34 - for await (const profile of profiles) { 35 - nProfiles++; 36 - 37 - const profileId = profile.userId; 38 - expect(profileId).toBeTruthy(); 39 - 40 - if (profileId != null) { 41 - expect(seenProfiles.has(profileId)).toBeFalsy(); 42 - seenProfiles.set(profileId, true); 43 - } 44 - } 45 - 46 - expect(nProfiles).toEqual(maxProfiles); 47 - }, 30000); 48 - 49 - test('scraper can search tweets', async () => { 50 - const scraper = await getScraper(); 51 - 52 - const seenTweets = new Map<string, boolean>(); 53 - const maxTweets = 150; 54 - let nTweets = 0; 55 - 56 - const profiles = scraper.searchTweets( 57 - 'twitter', 58 - maxTweets, 59 - SearchMode.Latest, 60 - ); 61 - 62 - for await (const tweet of profiles) { 63 - nTweets++; 64 - 65 - const id = tweet.id; 66 - expect(id).toBeTruthy(); 67 - 68 - if (id != null) { 69 - expect(seenTweets.has(id)).toBeFalsy(); 70 - seenTweets.set(id, true); 71 - } 72 - 73 - expect(tweet.permanentUrl).toBeTruthy(); 74 - expect(tweet.isRetweet).toBeFalsy(); 75 - expect(tweet.text).toBeTruthy(); 76 - } 77 - 78 - expect(nTweets).toEqual(maxTweets); 79 - }, 30000);
-138
twitter-scraper/src/search.ts
··· 1 - import { bearerToken2, requestApi } from './api'; 2 - import { TwitterAuth } from './auth'; 3 - import { Profile } from './profile'; 4 - import { QueryProfilesResponse, QueryTweetsResponse } from './timeline-v1'; 5 - import { getTweetTimeline, getUserTimeline } from './timeline-async'; 6 - import { Tweet } from './tweets'; 7 - import { 8 - SearchTimeline, 9 - parseSearchTimelineTweets, 10 - parseSearchTimelineUsers, 11 - } from './timeline-search'; 12 - import { AuthenticationError } from './errors'; 13 - import { apiRequestFactory } from './api-data'; 14 - 15 - /** 16 - * The categories that can be used in Twitter searches. 17 - */ 18 - export enum SearchMode { 19 - Top, 20 - Latest, 21 - Photos, 22 - Videos, 23 - Users, 24 - } 25 - 26 - export function searchTweets( 27 - query: string, 28 - maxTweets: number, 29 - searchMode: SearchMode, 30 - auth: TwitterAuth, 31 - ): AsyncGenerator<Tweet, void> { 32 - return getTweetTimeline(query, maxTweets, (q, mt, c) => { 33 - return fetchSearchTweets(q, mt, searchMode, auth, c); 34 - }); 35 - } 36 - 37 - export function searchProfiles( 38 - query: string, 39 - maxProfiles: number, 40 - auth: TwitterAuth, 41 - ): AsyncGenerator<Profile, void> { 42 - return getUserTimeline(query, maxProfiles, (q, mt, c) => { 43 - return fetchSearchProfiles(q, mt, auth, c); 44 - }); 45 - } 46 - 47 - export async function fetchSearchTweets( 48 - query: string, 49 - maxTweets: number, 50 - searchMode: SearchMode, 51 - auth: TwitterAuth, 52 - cursor?: string, 53 - ): Promise<QueryTweetsResponse> { 54 - const timeline = await getSearchTimeline( 55 - query, 56 - maxTweets, 57 - searchMode, 58 - auth, 59 - cursor, 60 - ); 61 - 62 - return parseSearchTimelineTweets(timeline); 63 - } 64 - 65 - export async function fetchSearchProfiles( 66 - query: string, 67 - maxProfiles: number, 68 - auth: TwitterAuth, 69 - cursor?: string, 70 - ): Promise<QueryProfilesResponse> { 71 - const timeline = await getSearchTimeline( 72 - query, 73 - maxProfiles, 74 - SearchMode.Users, 75 - auth, 76 - cursor, 77 - ); 78 - 79 - return parseSearchTimelineUsers(timeline); 80 - } 81 - 82 - async function getSearchTimeline( 83 - query: string, 84 - maxItems: number, 85 - searchMode: SearchMode, 86 - auth: TwitterAuth, 87 - cursor?: string, 88 - ): Promise<SearchTimeline> { 89 - if (!(await auth.isLoggedIn())) { 90 - throw new AuthenticationError('Scraper is not logged-in for search.'); 91 - } 92 - 93 - if (maxItems > 50) { 94 - maxItems = 50; 95 - } 96 - 97 - const searchTimelineRequest = apiRequestFactory.createSearchTimelineRequest(); 98 - searchTimelineRequest.variables.rawQuery = query; 99 - searchTimelineRequest.variables.count = maxItems; 100 - searchTimelineRequest.variables.querySource = 'typed_query'; 101 - searchTimelineRequest.variables.product = 'Top'; 102 - 103 - if (cursor != null && cursor != '') { 104 - searchTimelineRequest.variables['cursor'] = cursor; 105 - } 106 - 107 - switch (searchMode) { 108 - case SearchMode.Latest: 109 - searchTimelineRequest.variables.product = 'Latest'; 110 - break; 111 - case SearchMode.Photos: 112 - searchTimelineRequest.variables.product = 'Photos'; 113 - break; 114 - case SearchMode.Videos: 115 - searchTimelineRequest.variables.product = 'Videos'; 116 - break; 117 - case SearchMode.Users: 118 - searchTimelineRequest.variables.product = 'People'; 119 - break; 120 - default: 121 - break; 122 - } 123 - 124 - const res = await requestApi<SearchTimeline>( 125 - searchTimelineRequest.toRequestUrl(), 126 - auth, 127 - 'GET', 128 - undefined, 129 - undefined, 130 - bearerToken2, 131 - ); 132 - 133 - if (!res.success) { 134 - throw res.err; 135 - } 136 - 137 - return res.value; 138 - }
-73
twitter-scraper/src/test-utils.ts
··· 1 - import { HttpsProxyAgent } from 'https-proxy-agent'; 2 - import { Scraper } from './scraper'; 3 - import { Cookie } from 'tough-cookie'; 4 - import dotenv from 'dotenv'; 5 - import { cycleTLSFetch } from './cycletls-fetch'; 6 - 7 - dotenv.config({ path: '.env.local' }); 8 - 9 - export interface ScraperTestOptions { 10 - /** 11 - * Force the scraper to use username/password to authenticate instead of cookies. Only used 12 - * by this file for testing auth, but very unreliable. Should always use cookies to resume 13 - * session when possible. 14 - */ 15 - authMethod: 'password' | 'cookies' | 'anonymous'; 16 - } 17 - 18 - export async function getScraper( 19 - options: Partial<ScraperTestOptions> = { authMethod: 'cookies' }, 20 - ) { 21 - const username = process.env['TWITTER_USERNAME']; 22 - const password = process.env['TWITTER_PASSWORD']; 23 - const email = process.env['TWITTER_EMAIL']; 24 - const twoFactorSecret = process.env['TWITTER_2FA_SECRET']; 25 - const cookies = process.env['TWITTER_COOKIES']; 26 - const proxyUrl = process.env['PROXY_URL']; 27 - let agent: any; 28 - 29 - if (options.authMethod === 'cookies' && !cookies) { 30 - console.warn( 31 - 'TWITTER_COOKIES variable is not defined, reverting to password auth (not recommended)', 32 - ); 33 - options.authMethod = 'password'; 34 - } 35 - 36 - if (options.authMethod === 'password' && !(username && password)) { 37 - throw new Error( 38 - 'TWITTER_USERNAME and TWITTER_PASSWORD variables must be defined.', 39 - ); 40 - } 41 - 42 - if (proxyUrl) { 43 - agent = new HttpsProxyAgent(proxyUrl, { 44 - rejectUnauthorized: false, 45 - }); 46 - } 47 - 48 - const scraper = new Scraper({ 49 - fetch: cycleTLSFetch, 50 - transform: { 51 - request: (input, init) => { 52 - if (agent) { 53 - return [input, { ...init, agent }]; 54 - } 55 - return [input, init]; 56 - }, 57 - }, 58 - experimental: { 59 - xClientTransactionId: true, 60 - xpff: true, 61 - }, 62 - }); 63 - 64 - if (options.authMethod === 'password') { 65 - await scraper.login(username!, password!, email, twoFactorSecret); 66 - } else if (options.authMethod === 'cookies') { 67 - await scraper.setCookies( 68 - JSON.parse(cookies!).map((c: string) => Cookie.fromJSON(c)), 69 - ); 70 - } 71 - 72 - return scraper; 73 - }
-95
twitter-scraper/src/timeline-async.ts
··· 1 - import { jitter } from './api'; 2 - import { Profile } from './profile'; 3 - import { Tweet } from './tweets'; 4 - 5 - export interface FetchProfilesResponse { 6 - profiles: Profile[]; 7 - next?: string; 8 - } 9 - 10 - export type FetchProfiles = ( 11 - query: string, 12 - maxProfiles: number, 13 - cursor: string | undefined, 14 - ) => Promise<FetchProfilesResponse>; 15 - 16 - export interface FetchTweetsResponse { 17 - tweets: Tweet[]; 18 - next?: string; 19 - } 20 - 21 - export type FetchTweets = ( 22 - query: string, 23 - maxTweets: number, 24 - cursor: string | undefined, 25 - ) => Promise<FetchTweetsResponse>; 26 - 27 - export async function* getUserTimeline( 28 - query: string, 29 - maxProfiles: number, 30 - fetchFunc: FetchProfiles, 31 - ): AsyncGenerator<Profile, void> { 32 - let nProfiles = 0; 33 - let cursor: string | undefined = undefined; 34 - let consecutiveEmptyBatches = 0; 35 - while (nProfiles < maxProfiles) { 36 - const batch: FetchProfilesResponse = await fetchFunc( 37 - query, 38 - maxProfiles, 39 - cursor, 40 - ); 41 - 42 - const { profiles, next } = batch; 43 - cursor = next; 44 - 45 - if (profiles.length === 0) { 46 - consecutiveEmptyBatches++; 47 - if (consecutiveEmptyBatches > 5) break; 48 - } else consecutiveEmptyBatches = 0; 49 - 50 - for (const profile of profiles) { 51 - if (nProfiles < maxProfiles) yield profile; 52 - else break; 53 - nProfiles++; 54 - } 55 - 56 - if (!next) break; 57 - 58 - await jitter(1000); 59 - } 60 - } 61 - 62 - export async function* getTweetTimeline( 63 - query: string, 64 - maxTweets: number, 65 - fetchFunc: FetchTweets, 66 - ): AsyncGenerator<Tweet, void> { 67 - let nTweets = 0; 68 - let cursor: string | undefined = undefined; 69 - while (nTweets < maxTweets) { 70 - const batch: FetchTweetsResponse = await fetchFunc( 71 - query, 72 - maxTweets, 73 - cursor, 74 - ); 75 - 76 - const { tweets, next } = batch; 77 - 78 - if (tweets.length === 0) { 79 - break; 80 - } 81 - 82 - for (const tweet of tweets) { 83 - if (nTweets < maxTweets) { 84 - cursor = next; 85 - yield tweet; 86 - } else { 87 - break; 88 - } 89 - 90 - nTweets++; 91 - } 92 - 93 - await jitter(1000); 94 - } 95 - }
-73
twitter-scraper/src/timeline-list.ts
··· 1 - import { QueryTweetsResponse } from './timeline-v1'; 2 - import { parseAndPush, TimelineEntryRaw } from './timeline-v2'; 3 - import { Tweet } from './tweets'; 4 - 5 - export interface ListTimeline { 6 - data?: { 7 - list?: { 8 - tweets_timeline?: { 9 - timeline?: { 10 - instructions?: { 11 - entries?: TimelineEntryRaw[]; 12 - entry?: TimelineEntryRaw; 13 - type?: string; 14 - }[]; 15 - }; 16 - }; 17 - }; 18 - }; 19 - } 20 - 21 - export function parseListTimelineTweets( 22 - timeline: ListTimeline, 23 - ): QueryTweetsResponse { 24 - let bottomCursor: string | undefined; 25 - let topCursor: string | undefined; 26 - const tweets: Tweet[] = []; 27 - const instructions = 28 - timeline.data?.list?.tweets_timeline?.timeline?.instructions ?? []; 29 - for (const instruction of instructions) { 30 - const entries = instruction.entries ?? []; 31 - 32 - for (const entry of entries) { 33 - const entryContent = entry.content; 34 - if (!entryContent) continue; 35 - 36 - if (entryContent.cursorType === 'Bottom') { 37 - bottomCursor = entryContent.value; 38 - continue; 39 - } else if (entryContent.cursorType === 'Top') { 40 - topCursor = entryContent.value; 41 - continue; 42 - } 43 - 44 - const idStr = entry.entryId; 45 - if ( 46 - !idStr.startsWith('tweet') && 47 - !idStr.startsWith('list-conversation') 48 - ) { 49 - continue; 50 - } 51 - 52 - if (entryContent.itemContent) { 53 - parseAndPush(tweets, entryContent.itemContent, idStr); 54 - } else if (entryContent.items) { 55 - for (const contentItem of entryContent.items) { 56 - if ( 57 - contentItem.item && 58 - contentItem.item.itemContent && 59 - contentItem.entryId 60 - ) { 61 - parseAndPush( 62 - tweets, 63 - contentItem.item.itemContent, 64 - contentItem.entryId.split('tweet-')[1], 65 - ); 66 - } 67 - } 68 - } 69 - } 70 - } 71 - 72 - return { tweets, next: bottomCursor, previous: topCursor }; 73 - }
-95
twitter-scraper/src/timeline-relationship.ts
··· 1 - import { Profile, parseProfile } from './profile'; 2 - import { QueryProfilesResponse } from './timeline-v1'; 3 - import { TimelineUserResultRaw } from './timeline-v2'; 4 - 5 - export interface RelationshipEntryItemContentRaw { 6 - itemType?: string; 7 - userDisplayType?: string; 8 - user_results?: { 9 - result?: TimelineUserResultRaw; 10 - }; 11 - } 12 - 13 - export interface RelationshipEntryRaw { 14 - entryId: string; 15 - sortIndex: string; 16 - content?: { 17 - cursorType?: string; 18 - entryType?: string; 19 - __typename?: string; 20 - value?: string; 21 - itemContent?: RelationshipEntryItemContentRaw; 22 - }; 23 - } 24 - 25 - export interface RelationshipTimeline { 26 - data?: { 27 - user?: { 28 - result?: { 29 - timeline?: { 30 - timeline?: { 31 - instructions?: { 32 - entries?: RelationshipEntryRaw[]; 33 - entry?: RelationshipEntryRaw; 34 - type?: string; 35 - }[]; 36 - }; 37 - }; 38 - }; 39 - }; 40 - }; 41 - } 42 - 43 - export function parseRelationshipTimeline( 44 - timeline: RelationshipTimeline, 45 - ): QueryProfilesResponse { 46 - let bottomCursor: string | undefined; 47 - let topCursor: string | undefined; 48 - const profiles: Profile[] = []; 49 - const instructions = 50 - timeline.data?.user?.result?.timeline?.timeline?.instructions ?? []; 51 - 52 - for (const instruction of instructions) { 53 - if ( 54 - instruction.type === 'TimelineAddEntries' || 55 - instruction.type === 'TimelineReplaceEntry' 56 - ) { 57 - if (instruction.entry?.content?.cursorType === 'Bottom') { 58 - bottomCursor = instruction.entry.content.value; 59 - continue; 60 - } 61 - 62 - if (instruction.entry?.content?.cursorType === 'Top') { 63 - topCursor = instruction.entry.content.value; 64 - continue; 65 - } 66 - 67 - const entries = instruction.entries ?? []; 68 - for (const entry of entries) { 69 - const itemContent = entry.content?.itemContent; 70 - if (itemContent?.userDisplayType === 'User') { 71 - const userResultRaw = itemContent.user_results?.result; 72 - 73 - if (userResultRaw?.legacy) { 74 - const profile = parseProfile( 75 - userResultRaw.legacy, 76 - userResultRaw.is_blue_verified, 77 - ); 78 - 79 - if (!profile.userId) { 80 - profile.userId = userResultRaw.rest_id; 81 - } 82 - 83 - profiles.push(profile); 84 - } 85 - } else if (entry.content?.cursorType === 'Bottom') { 86 - bottomCursor = entry.content.value; 87 - } else if (entry.content?.cursorType === 'Top') { 88 - topCursor = entry.content.value; 89 - } 90 - } 91 - } 92 - } 93 - 94 - return { profiles, next: bottomCursor, previous: topCursor }; 95 - }
-129
twitter-scraper/src/timeline-search.ts
··· 1 - import { Profile, parseProfile } from './profile'; 2 - import { QueryProfilesResponse, QueryTweetsResponse } from './timeline-v1'; 3 - import { SearchEntryRaw, parseLegacyTweet } from './timeline-v2'; 4 - import { Tweet } from './tweets'; 5 - 6 - export interface SearchTimeline { 7 - data?: { 8 - search_by_raw_query?: { 9 - search_timeline?: { 10 - timeline?: { 11 - instructions?: { 12 - entries?: SearchEntryRaw[]; 13 - entry?: SearchEntryRaw; 14 - type?: string; 15 - }[]; 16 - }; 17 - }; 18 - }; 19 - }; 20 - } 21 - 22 - export function parseSearchTimelineTweets( 23 - timeline: SearchTimeline, 24 - ): QueryTweetsResponse { 25 - let bottomCursor: string | undefined; 26 - let topCursor: string | undefined; 27 - const tweets: Tweet[] = []; 28 - const instructions = 29 - timeline.data?.search_by_raw_query?.search_timeline?.timeline 30 - ?.instructions ?? []; 31 - for (const instruction of instructions) { 32 - if ( 33 - instruction.type === 'TimelineAddEntries' || 34 - instruction.type === 'TimelineReplaceEntry' 35 - ) { 36 - if (instruction.entry?.content?.cursorType === 'Bottom') { 37 - bottomCursor = instruction.entry.content.value; 38 - continue; 39 - } else if (instruction.entry?.content?.cursorType === 'Top') { 40 - topCursor = instruction.entry.content.value; 41 - continue; 42 - } 43 - 44 - const entries = instruction.entries ?? []; 45 - for (const entry of entries) { 46 - const itemContent = entry.content?.itemContent; 47 - if (itemContent?.tweetDisplayType === 'Tweet') { 48 - const tweetResultRaw = itemContent.tweet_results?.result; 49 - const tweetResult = parseLegacyTweet( 50 - tweetResultRaw?.core?.user_results?.result?.core, 51 - tweetResultRaw?.core?.user_results?.result?.legacy, 52 - tweetResultRaw?.legacy, 53 - tweetResultRaw?.edit_control?.edit_control_initial, 54 - ); 55 - 56 - if (tweetResult.success) { 57 - if (!tweetResult.tweet.views && tweetResultRaw?.views?.count) { 58 - const views = parseInt(tweetResultRaw.views.count); 59 - if (!isNaN(views)) { 60 - tweetResult.tweet.views = views; 61 - } 62 - } 63 - 64 - tweets.push(tweetResult.tweet); 65 - } 66 - } else if (entry.content?.cursorType === 'Bottom') { 67 - bottomCursor = entry.content.value; 68 - } else if (entry.content?.cursorType === 'Top') { 69 - topCursor = entry.content.value; 70 - } 71 - } 72 - } 73 - } 74 - 75 - return { tweets, next: bottomCursor, previous: topCursor }; 76 - } 77 - 78 - export function parseSearchTimelineUsers( 79 - timeline: SearchTimeline, 80 - ): QueryProfilesResponse { 81 - let bottomCursor: string | undefined; 82 - let topCursor: string | undefined; 83 - const profiles: Profile[] = []; 84 - const instructions = 85 - timeline.data?.search_by_raw_query?.search_timeline?.timeline 86 - ?.instructions ?? []; 87 - 88 - for (const instruction of instructions) { 89 - if ( 90 - instruction.type === 'TimelineAddEntries' || 91 - instruction.type === 'TimelineReplaceEntry' 92 - ) { 93 - if (instruction.entry?.content?.cursorType === 'Bottom') { 94 - bottomCursor = instruction.entry.content.value; 95 - continue; 96 - } else if (instruction.entry?.content?.cursorType === 'Top') { 97 - topCursor = instruction.entry.content.value; 98 - continue; 99 - } 100 - 101 - const entries = instruction.entries ?? []; 102 - for (const entry of entries) { 103 - const itemContent = entry.content?.itemContent; 104 - if (itemContent?.userDisplayType === 'User') { 105 - const userResultRaw = itemContent.user_results?.result; 106 - 107 - if (userResultRaw?.legacy) { 108 - const profile = parseProfile( 109 - userResultRaw.legacy, 110 - userResultRaw.is_blue_verified, 111 - ); 112 - 113 - if (!profile.userId) { 114 - profile.userId = userResultRaw.rest_id; 115 - } 116 - 117 - profiles.push(profile); 118 - } 119 - } else if (entry.content?.cursorType === 'Bottom') { 120 - bottomCursor = entry.content.value; 121 - } else if (entry.content?.cursorType === 'Top') { 122 - topCursor = entry.content.value; 123 - } 124 - } 125 - } 126 - } 127 - 128 - return { profiles, next: bottomCursor, previous: topCursor }; 129 - }
-165
twitter-scraper/src/timeline-tweet-util.ts
··· 1 - import { LegacyTweetRaw, TimelineMediaExtendedRaw } from './timeline-v1'; 2 - import { Photo, Video } from './tweets'; 3 - import { isFieldDefined, NonNullableField } from './type-util'; 4 - 5 - const reHashtag = /\B(\#\S+\b)/g; 6 - const reCashtag = /\B(\$\S+\b)/g; 7 - const reTwitterUrl = /https:(\/\/t\.co\/([A-Za-z0-9]|[A-Za-z]){10})/g; 8 - const reUsername = /\B(\@\S{1,15}\b)/g; 9 - 10 - export function parseMediaGroups(media: TimelineMediaExtendedRaw[]): { 11 - sensitiveContent?: boolean; 12 - photos: Photo[]; 13 - videos: Video[]; 14 - } { 15 - const photos: Photo[] = []; 16 - const videos: Video[] = []; 17 - let sensitiveContent: boolean | undefined = undefined; 18 - 19 - for (const m of media 20 - .filter(isFieldDefined('id_str')) 21 - .filter(isFieldDefined('media_url_https'))) { 22 - if (m.type === 'photo') { 23 - photos.push({ 24 - id: m.id_str, 25 - url: m.media_url_https, 26 - alt_text: m.ext_alt_text, 27 - }); 28 - } else if (m.type === 'video') { 29 - videos.push(parseVideo(m)); 30 - } else if (m.type === 'animated_gif') { 31 - videos.push(parseGif(m)); 32 - } 33 - 34 - const sensitive = m.ext_sensitive_media_warning; 35 - if (sensitive != null) { 36 - sensitiveContent = 37 - sensitive.adult_content || 38 - sensitive.graphic_violence || 39 - sensitive.other; 40 - } 41 - } 42 - 43 - return { sensitiveContent, photos, videos }; 44 - } 45 - 46 - function parseGif( 47 - m: NonNullableField<TimelineMediaExtendedRaw, 'id_str' | 'media_url_https'>, 48 - ): Video { 49 - const gif: Video = { 50 - id: m.id_str, 51 - preview: m.media_url_https, 52 - }; 53 - 54 - const variants = m.video_info?.variants ?? []; 55 - 56 - const url = variants.find((v) => v.content_type === 'video/mp4')?.url; 57 - 58 - if (url) { 59 - gif.preview = url; 60 - gif.url = url; 61 - } 62 - 63 - return gif; 64 - } 65 - 66 - function parseVideo( 67 - m: NonNullableField<TimelineMediaExtendedRaw, 'id_str' | 'media_url_https'>, 68 - ): Video { 69 - const video: Video = { 70 - id: m.id_str, 71 - preview: m.media_url_https, 72 - }; 73 - 74 - let maxBitrate = 0; 75 - const variants = m.video_info?.variants ?? []; 76 - for (const variant of variants) { 77 - const bitrate = variant.bitrate; 78 - if (bitrate != null && bitrate > maxBitrate && variant.url != null) { 79 - let variantUrl = variant.url; 80 - const stringStart = 0; 81 - const tagSuffixIdx = variantUrl.indexOf('?tag=10'); 82 - if (tagSuffixIdx !== -1) { 83 - variantUrl = variantUrl.substring(stringStart, tagSuffixIdx + 1); 84 - } 85 - 86 - video.url = variantUrl; 87 - maxBitrate = bitrate; 88 - } 89 - } 90 - 91 - return video; 92 - } 93 - 94 - export function reconstructTweetHtml( 95 - tweet: LegacyTweetRaw, 96 - photos: Photo[], 97 - videos: Video[], 98 - ): string { 99 - const media: string[] = []; 100 - 101 - // HTML parsing with regex :) 102 - let html = tweet.full_text ?? ''; 103 - 104 - html = html.replace(reHashtag, linkHashtagHtml); 105 - html = html.replace(reCashtag, linkCashtagHtml); 106 - html = html.replace(reUsername, linkUsernameHtml); 107 - html = html.replace(reTwitterUrl, unwrapTcoUrlHtml(tweet, media)); 108 - 109 - for (const { url } of photos) { 110 - if (media.indexOf(url) !== -1) { 111 - continue; 112 - } 113 - 114 - html += `<br><img src="${url}"/>`; 115 - } 116 - 117 - for (const { preview: url } of videos) { 118 - if (media.indexOf(url) !== -1) { 119 - continue; 120 - } 121 - 122 - html += `<br><img src="${url}"/>`; 123 - } 124 - 125 - html = html.replace(/\n/g, '<br>'); 126 - 127 - return html; 128 - } 129 - 130 - function linkHashtagHtml(hashtag: string) { 131 - return `<a href="https://x.com/hashtag/${hashtag.replace( 132 - '#', 133 - '', 134 - )}">${hashtag}</a>`; 135 - } 136 - 137 - function linkCashtagHtml(cashtag: string) { 138 - return `<a href="https://x.com/search?q=%24${cashtag.replace( 139 - '$', 140 - '', 141 - )}">${cashtag}</a>`; 142 - } 143 - 144 - function linkUsernameHtml(username: string) { 145 - return `<a href="https://x.com/${username.replace('@', '')}">${username}</a>`; 146 - } 147 - 148 - function unwrapTcoUrlHtml(tweet: LegacyTweetRaw, foundedMedia: string[]) { 149 - return function (tco: string) { 150 - for (const entity of tweet.entities?.urls ?? []) { 151 - if (tco === entity.url && entity.expanded_url != null) { 152 - return `<a href="${entity.expanded_url}">${tco}</a>`; 153 - } 154 - } 155 - 156 - for (const entity of tweet.extended_entities?.media ?? []) { 157 - if (tco === entity.url && entity.media_url_https != null) { 158 - foundedMedia.push(entity.media_url_https); 159 - return `<br><a href="${tco}"><img src="${entity.media_url_https}"/></a>`; 160 - } 161 - } 162 - 163 - return tco; 164 - }; 165 - }
-499
twitter-scraper/src/timeline-v1.ts
··· 1 - import { CoreUserRaw, LegacyUserRaw, parseProfile, Profile } from './profile'; 2 - import { parseMediaGroups, reconstructTweetHtml } from './timeline-tweet-util'; 3 - import { PlaceRaw, Tweet } from './tweets'; 4 - import { isFieldDefined } from './type-util'; 5 - 6 - export interface Hashtag { 7 - text?: string; 8 - } 9 - 10 - export interface TimelineUserMentionBasicRaw { 11 - id_str?: string; 12 - name?: string; 13 - screen_name?: string; 14 - } 15 - 16 - export interface TimelineMediaBasicRaw { 17 - media_url_https?: string; 18 - type?: string; 19 - url?: string; 20 - } 21 - 22 - export interface TimelineUrlBasicRaw { 23 - expanded_url?: string; 24 - url?: string; 25 - } 26 - 27 - export interface ExtSensitiveMediaWarningRaw { 28 - adult_content?: boolean; 29 - graphic_violence?: boolean; 30 - other?: boolean; 31 - } 32 - 33 - export interface VideoVariant { 34 - bitrate?: number; 35 - content_type?: string; 36 - url?: string; 37 - } 38 - 39 - export interface VideoInfo { 40 - variants?: VideoVariant[]; 41 - } 42 - 43 - export interface TimelineMediaExtendedRaw { 44 - id_str?: string; 45 - media_url_https?: string; 46 - ext_sensitive_media_warning?: ExtSensitiveMediaWarningRaw; 47 - type?: string; 48 - url?: string; 49 - video_info?: VideoInfo; 50 - ext_alt_text: string | undefined; 51 - } 52 - 53 - export interface EditControlInitialRaw { 54 - edit_tweet_ids?: string[]; 55 - editable_until_msecs?: `${number}`; 56 - edits_remaining?: `${number}`; 57 - is_edit_eligible?: boolean; 58 - } 59 - 60 - export interface SearchResultRaw { 61 - rest_id?: string; 62 - __typename?: string; 63 - core?: { 64 - user_results?: { 65 - result?: { 66 - is_blue_verified?: boolean; 67 - core?: CoreUserRaw; 68 - legacy?: LegacyUserRaw; 69 - }; 70 - }; 71 - }; 72 - edit_control?: { 73 - edit_control_initial?: EditControlInitialRaw; 74 - }; 75 - views?: { 76 - count?: string; 77 - }; 78 - note_tweet?: { 79 - note_tweet_results?: { 80 - result?: { 81 - text?: string; 82 - }; 83 - }; 84 - }; 85 - quoted_status_result?: { 86 - result?: SearchResultRaw; 87 - }; 88 - legacy?: LegacyTweetRaw; 89 - } 90 - 91 - export interface TimelineResultRaw { 92 - rest_id?: string; 93 - __typename?: string; 94 - edit_control?: { 95 - edit_control_initial?: EditControlInitialRaw; 96 - }; 97 - core?: { 98 - user_results?: { 99 - result?: { 100 - __typename?: string; 101 - is_blue_verified?: boolean; 102 - core?: CoreUserRaw; 103 - legacy?: LegacyUserRaw; 104 - }; 105 - }; 106 - }; 107 - views?: { 108 - count?: string; 109 - }; 110 - note_tweet?: { 111 - note_tweet_results?: { 112 - result?: { 113 - text?: string; 114 - }; 115 - }; 116 - }; 117 - quoted_status_result?: { 118 - result?: TimelineResultRaw; 119 - }; 120 - legacy?: LegacyTweetRaw; 121 - tweet?: TimelineResultRaw; 122 - } 123 - 124 - export interface LegacyTweetRaw { 125 - bookmark_count?: number; 126 - conversation_id_str?: string; 127 - created_at?: string; 128 - favorite_count?: number; 129 - full_text?: string; 130 - entities?: { 131 - hashtags?: Hashtag[]; 132 - media?: TimelineMediaBasicRaw[]; 133 - urls?: TimelineUrlBasicRaw[]; 134 - user_mentions?: TimelineUserMentionBasicRaw[]; 135 - }; 136 - extended_entities?: { 137 - media?: TimelineMediaExtendedRaw[]; 138 - }; 139 - id_str?: string; 140 - in_reply_to_status_id_str?: string; 141 - place?: PlaceRaw; 142 - reply_count?: number; 143 - retweet_count?: number; 144 - retweeted_status_id_str?: string; 145 - retweeted_status_result?: { 146 - result?: TimelineResultRaw; 147 - }; 148 - quoted_status_id_str?: string; 149 - time?: string; 150 - user_id_str?: string; 151 - ext_views?: { 152 - state?: string; 153 - count?: string; 154 - }; 155 - } 156 - 157 - export interface TimelineGlobalObjectsRaw { 158 - tweets?: { [key: string]: LegacyTweetRaw | undefined }; 159 - users?: { [key: string]: LegacyUserRaw | undefined }; 160 - } 161 - 162 - export interface TimelineDataRawCursor { 163 - value?: string; 164 - cursorType?: string; 165 - } 166 - 167 - export interface TimelineDataRawEntity { 168 - id?: string; 169 - } 170 - 171 - export interface TimelineDataRawModuleItem { 172 - clientEventInfo?: { 173 - details?: { 174 - guideDetails?: { 175 - transparentGuideDetails?: { 176 - trendMetadata?: { 177 - trendName?: string; 178 - }; 179 - }; 180 - }; 181 - }; 182 - }; 183 - } 184 - 185 - export interface TimelineDataRawAddEntry { 186 - content?: { 187 - item?: { 188 - content?: { 189 - tweet?: TimelineDataRawEntity; 190 - user?: TimelineDataRawEntity; 191 - }; 192 - }; 193 - operation?: { 194 - cursor?: TimelineDataRawCursor; 195 - }; 196 - timelineModule?: { 197 - items?: { 198 - item?: TimelineDataRawModuleItem; 199 - }[]; 200 - }; 201 - }; 202 - } 203 - 204 - export interface TimelineDataRawPinEntry { 205 - content?: { 206 - item?: { 207 - content?: { 208 - tweet?: TimelineDataRawEntity; 209 - }; 210 - }; 211 - }; 212 - } 213 - 214 - export interface TimelineDataRawReplaceEntry { 215 - content?: { 216 - operation?: { 217 - cursor?: TimelineDataRawCursor; 218 - }; 219 - }; 220 - } 221 - 222 - export interface TimelineDataRawInstruction { 223 - addEntries?: { 224 - entries?: TimelineDataRawAddEntry[]; 225 - }; 226 - pinEntry?: { 227 - entry?: TimelineDataRawPinEntry; 228 - }; 229 - replaceEntry?: { 230 - entry?: TimelineDataRawReplaceEntry; 231 - }; 232 - } 233 - 234 - export interface TimelineDataRaw { 235 - instructions?: TimelineDataRawInstruction[]; 236 - } 237 - 238 - export interface TimelineV1 { 239 - globalObjects?: TimelineGlobalObjectsRaw; 240 - timeline?: TimelineDataRaw; 241 - } 242 - 243 - export type ParseTweetResult = 244 - | { success: true; tweet: Tweet } 245 - | { success: false; err: Error }; 246 - 247 - function parseTimelineTweet( 248 - timeline: TimelineV1, 249 - tweetId: string, 250 - ): ParseTweetResult { 251 - const tweets = timeline.globalObjects?.tweets ?? {}; 252 - const tweet: Readonly<LegacyTweetRaw> | undefined = tweets[tweetId]; 253 - if (tweet?.user_id_str == null) { 254 - return { 255 - success: false, 256 - err: new Error( 257 - `Tweet "${tweetId}" was not found in the timeline object.`, 258 - ), 259 - }; 260 - } 261 - 262 - const users = timeline.globalObjects?.users ?? {}; 263 - const user: Readonly<LegacyUserRaw> | undefined = users[tweet.user_id_str]; 264 - if (user?.screen_name == null) { 265 - return { 266 - success: false, 267 - err: new Error(`User "${tweet.user_id_str}" has no username data.`), 268 - }; 269 - } 270 - 271 - const hashtags = tweet.entities?.hashtags ?? []; 272 - const mentions = tweet.entities?.user_mentions ?? []; 273 - const media = tweet.extended_entities?.media ?? []; 274 - const pinnedTweets = new Set<string | undefined>( 275 - user.pinned_tweet_ids_str ?? [], 276 - ); 277 - const urls = tweet.entities?.urls ?? []; 278 - const { photos, videos, sensitiveContent } = parseMediaGroups(media); 279 - 280 - const tw: Tweet = { 281 - __raw_UNSTABLE: tweet, 282 - conversationId: tweet.conversation_id_str, 283 - id: tweetId, 284 - hashtags: hashtags 285 - .filter(isFieldDefined('text')) 286 - .map((hashtag) => hashtag.text), 287 - likes: tweet.favorite_count, 288 - mentions: mentions.filter(isFieldDefined('id_str')).map((mention) => ({ 289 - id: mention.id_str, 290 - username: mention.screen_name, 291 - name: mention.name, 292 - })), 293 - name: user.name, 294 - permanentUrl: `https://x.com/${user.screen_name}/status/${tweetId}`, 295 - photos, 296 - replies: tweet.reply_count, 297 - retweets: tweet.retweet_count, 298 - text: tweet.full_text, 299 - thread: [], 300 - urls: urls 301 - .filter(isFieldDefined('expanded_url')) 302 - .map((url) => url.expanded_url), 303 - userId: tweet.user_id_str, 304 - username: user.screen_name, 305 - videos, 306 - }; 307 - 308 - if (tweet.created_at) { 309 - tw.timeParsed = new Date(Date.parse(tweet.created_at)); 310 - tw.timestamp = Math.floor(tw.timeParsed.valueOf() / 1000); 311 - } 312 - 313 - if (tweet.place?.id) { 314 - tw.place = tweet.place; 315 - } 316 - 317 - if (tweet.quoted_status_id_str) { 318 - tw.isQuoted = true; 319 - tw.quotedStatusId = tweet.quoted_status_id_str; 320 - 321 - const quotedStatusResult = parseTimelineTweet( 322 - timeline, 323 - tweet.quoted_status_id_str, 324 - ); 325 - if (quotedStatusResult.success) { 326 - tw.quotedStatus = quotedStatusResult.tweet; 327 - } 328 - } 329 - 330 - if (tweet.in_reply_to_status_id_str) { 331 - tw.isReply = true; 332 - tw.inReplyToStatusId = tweet.in_reply_to_status_id_str; 333 - 334 - const replyStatusResult = parseTimelineTweet( 335 - timeline, 336 - tweet.in_reply_to_status_id_str, 337 - ); 338 - if (replyStatusResult.success) { 339 - tw.inReplyToStatus = replyStatusResult.tweet; 340 - } 341 - } 342 - 343 - if (tweet.retweeted_status_id_str != null) { 344 - tw.isRetweet = true; 345 - tw.retweetedStatusId = tweet.retweeted_status_id_str; 346 - 347 - const retweetedStatusResult = parseTimelineTweet( 348 - timeline, 349 - tweet.retweeted_status_id_str, 350 - ); 351 - if (retweetedStatusResult.success) { 352 - tw.retweetedStatus = retweetedStatusResult.tweet; 353 - } 354 - } 355 - 356 - const views = parseInt(tweet.ext_views?.count ?? ''); 357 - if (!isNaN(views)) { 358 - tw.views = views; 359 - } 360 - 361 - if (pinnedTweets.has(tweet.id_str)) { 362 - // TODO: Update tests so this can be assigned at the tweet declaration 363 - tw.isPin = true; 364 - } 365 - 366 - if (sensitiveContent) { 367 - // TODO: Update tests so this can be assigned at the tweet declaration 368 - tw.sensitiveContent = true; 369 - } 370 - 371 - tw.html = reconstructTweetHtml(tweet, tw.photos, tw.videos); 372 - 373 - return { success: true, tweet: tw }; 374 - } 375 - 376 - /** 377 - * A paginated tweets API response. The `next` field can be used to fetch the next page of results, 378 - * and the `previous` can be used to fetch the previous results (or results created after the 379 - * inital request) 380 - */ 381 - export interface QueryTweetsResponse { 382 - tweets: Tweet[]; 383 - next?: string; 384 - previous?: string; 385 - } 386 - 387 - export function parseTimelineTweetsV1( 388 - timeline: TimelineV1, 389 - ): QueryTweetsResponse { 390 - let bottomCursor: string | undefined; 391 - let topCursor: string | undefined; 392 - let pinnedTweet: Tweet | undefined; 393 - let orderedTweets: Tweet[] = []; 394 - for (const instruction of timeline.timeline?.instructions ?? []) { 395 - const { pinEntry, addEntries, replaceEntry } = instruction; 396 - 397 - // Handle pin instruction 398 - const pinnedTweetId = pinEntry?.entry?.content?.item?.content?.tweet?.id; 399 - if (pinnedTweetId != null) { 400 - const tweetResult = parseTimelineTweet(timeline, pinnedTweetId); 401 - if (tweetResult.success) { 402 - pinnedTweet = tweetResult.tweet; 403 - } 404 - } 405 - 406 - // Handle add instructions 407 - for (const { content } of addEntries?.entries ?? []) { 408 - const tweetId = content?.item?.content?.tweet?.id; 409 - if (tweetId != null) { 410 - const tweetResult = parseTimelineTweet(timeline, tweetId); 411 - if (tweetResult.success) { 412 - orderedTweets.push(tweetResult.tweet); 413 - } 414 - } 415 - 416 - const operation = content?.operation; 417 - if (operation?.cursor?.cursorType === 'Bottom') { 418 - bottomCursor = operation?.cursor?.value; 419 - } else if (operation?.cursor?.cursorType === 'Top') { 420 - topCursor = operation?.cursor?.value; 421 - } 422 - } 423 - 424 - // Handle replace instruction 425 - const operation = replaceEntry?.entry?.content?.operation; 426 - if (operation?.cursor?.cursorType === 'Bottom') { 427 - bottomCursor = operation.cursor.value; 428 - } else if (operation?.cursor?.cursorType === 'Top') { 429 - topCursor = operation.cursor.value; 430 - } 431 - } 432 - 433 - if (pinnedTweet != null && orderedTweets.length > 0) { 434 - orderedTweets = [pinnedTweet, ...orderedTweets]; 435 - } 436 - 437 - return { 438 - tweets: orderedTweets, 439 - next: bottomCursor, 440 - previous: topCursor, 441 - }; 442 - } 443 - 444 - /** 445 - * A paginated profiles API response. The `next` field can be used to fetch the next page of results. 446 - */ 447 - export interface QueryProfilesResponse { 448 - profiles: Profile[]; 449 - next?: string; 450 - previous?: string; 451 - } 452 - 453 - export function parseUsers(timeline: TimelineV1): QueryProfilesResponse { 454 - const users = new Map<string | undefined, Profile>(); 455 - 456 - const userObjects = timeline.globalObjects?.users ?? {}; 457 - for (const id in userObjects) { 458 - const legacy = userObjects[id]; 459 - if (legacy == null) { 460 - continue; 461 - } 462 - 463 - const user = parseProfile(legacy); 464 - users.set(id, user); 465 - } 466 - 467 - let bottomCursor: string | undefined; 468 - let topCursor: string | undefined; 469 - const orderedProfiles: Profile[] = []; 470 - for (const instruction of timeline.timeline?.instructions ?? []) { 471 - for (const entry of instruction.addEntries?.entries ?? []) { 472 - const userId = entry.content?.item?.content?.user?.id; 473 - const profile = users.get(userId); 474 - if (profile != null) { 475 - orderedProfiles.push(profile); 476 - } 477 - 478 - const operation = entry.content?.operation; 479 - if (operation?.cursor?.cursorType === 'Bottom') { 480 - bottomCursor = operation?.cursor?.value; 481 - } else if (operation?.cursor?.cursorType === 'Top') { 482 - topCursor = operation?.cursor?.value; 483 - } 484 - } 485 - 486 - const operation = instruction.replaceEntry?.entry?.content?.operation; 487 - if (operation?.cursor?.cursorType === 'Bottom') { 488 - bottomCursor = operation.cursor.value; 489 - } else if (operation?.cursor?.cursorType === 'Top') { 490 - topCursor = operation.cursor.value; 491 - } 492 - } 493 - 494 - return { 495 - profiles: orderedProfiles, 496 - next: bottomCursor, 497 - previous: topCursor, 498 - }; 499 - }
-97
twitter-scraper/src/timeline-v2.test.ts
··· 1 - import { TimelineV2, parseTimelineTweetsV2 } from './timeline-v2'; 2 - 3 - test('parseTimelineTweetsV2 handles pinned tweets correctly', async () => { 4 - const data: TimelineV2 = { 5 - data: { 6 - user: { 7 - result: { 8 - __typename: 'User', 9 - timeline: { 10 - timeline: { 11 - instructions: [ 12 - { 13 - type: 'TimelinePinEntry', 14 - entry: { 15 - entryId: 'tweet-1', 16 - content: { 17 - entryType: 'TimelineTimelineItem', 18 - __typename: 'TimelineTimelineItem', 19 - itemContent: { 20 - itemType: 'TimelineTweet', 21 - __typename: 'TimelineTweet', 22 - tweet_results: { 23 - result: { 24 - __typename: 'Tweet', 25 - rest_id: '1', 26 - core: { 27 - user_results: { 28 - result: { 29 - core: { 30 - created_at: 31 - 'Tue Oct 13 15:48:33 +0000 2015', 32 - name: 'DOFUS Touch', 33 - screen_name: 'DofusTouch', 34 - }, 35 - legacy: { 36 - pinned_tweet_ids_str: ['1'], 37 - }, 38 - }, 39 - }, 40 - }, 41 - legacy: { 42 - created_at: 'Mon Jan 1 12:00:00 +0000 2025', 43 - conversation_id_str: '1', 44 - entities: {}, 45 - favorite_count: 32, 46 - full_text: 'test', 47 - reply_count: 21, 48 - retweet_count: 4, 49 - user_id_str: '1', 50 - id_str: '1', 51 - }, 52 - }, 53 - }, 54 - tweetDisplayType: 'Tweet', 55 - }, 56 - }, 57 - }, 58 - }, 59 - { 60 - type: 'TimelineAddEntries', 61 - entries: [ 62 - { 63 - entryId: 'cursor-top-2', 64 - content: { 65 - entryType: 'TimelineTimelineCursor', 66 - __typename: 'TimelineTimelineCursor', 67 - value: 'A', 68 - cursorType: 'Top', 69 - }, 70 - }, 71 - { 72 - entryId: 'cursor-bottom-3', 73 - content: { 74 - entryType: 'TimelineTimelineCursor', 75 - __typename: 'TimelineTimelineCursor', 76 - value: 'B', 77 - cursorType: 'Bottom', 78 - }, 79 - }, 80 - ], 81 - }, 82 - ], 83 - }, 84 - }, 85 - }, 86 - }, 87 - }, 88 - }; 89 - 90 - const result = parseTimelineTweetsV2(data); 91 - expect(result.tweets.length).toBe(1); 92 - expect(result.tweets[0].id).toBe('1'); 93 - expect(result.tweets[0].isPin).toBe(true); 94 - expect(result.previous).toBe('A'); 95 - expect(result.next).toBe('B'); 96 - expect(result.tweets[0].text).toBe('test'); 97 - });
-458
twitter-scraper/src/timeline-v2.ts
··· 1 - import { CoreUserRaw, LegacyUserRaw } from './profile'; 2 - import { parseMediaGroups, reconstructTweetHtml } from './timeline-tweet-util'; 3 - import { 4 - EditControlInitialRaw, 5 - LegacyTweetRaw, 6 - ParseTweetResult, 7 - QueryTweetsResponse, 8 - SearchResultRaw, 9 - TimelineResultRaw, 10 - } from './timeline-v1'; 11 - import { Tweet } from './tweets'; 12 - import { isFieldDefined } from './type-util'; 13 - 14 - export interface TimelineUserResultRaw { 15 - rest_id?: string; 16 - legacy?: LegacyUserRaw; 17 - is_blue_verified?: boolean; 18 - } 19 - 20 - export interface TimelineEntryItemContentRaw { 21 - itemType?: string; 22 - __typename?: string; 23 - tweetDisplayType?: string; 24 - tweetResult?: { 25 - result?: TimelineResultRaw; 26 - }; 27 - tweet_results?: { 28 - result?: TimelineResultRaw; 29 - }; 30 - userDisplayType?: string; 31 - user_results?: { 32 - result?: TimelineUserResultRaw; 33 - }; 34 - } 35 - 36 - export interface TimelineEntryRaw { 37 - entryId: string; 38 - content?: { 39 - entryType?: string; 40 - __typename?: string; 41 - cursorType?: string; 42 - value?: string; 43 - items?: { 44 - entryId?: string; 45 - item?: { 46 - content?: TimelineEntryItemContentRaw; 47 - itemContent?: SearchEntryItemContentRaw; 48 - }; 49 - }[]; 50 - itemContent?: TimelineEntryItemContentRaw; 51 - }; 52 - } 53 - 54 - export interface SearchEntryItemContentRaw { 55 - tweetDisplayType?: string; 56 - tweet_results?: { 57 - result?: SearchResultRaw; 58 - }; 59 - userDisplayType?: string; 60 - user_results?: { 61 - result?: TimelineUserResultRaw; 62 - }; 63 - } 64 - 65 - export interface SearchEntryRaw { 66 - entryId: string; 67 - sortIndex: string; 68 - content?: { 69 - cursorType?: string; 70 - entryType?: string; 71 - __typename?: string; 72 - value?: string; 73 - items?: { 74 - item?: { 75 - content?: SearchEntryItemContentRaw; 76 - }; 77 - }[]; 78 - itemContent?: SearchEntryItemContentRaw; 79 - }; 80 - } 81 - 82 - export interface TimelineInstruction { 83 - entries?: TimelineEntryRaw[]; 84 - entry?: TimelineEntryRaw; 85 - type?: string; 86 - } 87 - 88 - export interface TimelineV2 { 89 - data?: { 90 - user?: { 91 - result?: { 92 - __typename?: string; 93 - timeline?: { 94 - timeline?: { 95 - instructions?: TimelineInstruction[]; 96 - }; 97 - }; 98 - }; 99 - }; 100 - }; 101 - } 102 - 103 - export interface ThreadedConversation { 104 - data?: { 105 - threaded_conversation_with_injections_v2?: { 106 - instructions?: TimelineInstruction[]; 107 - }; 108 - }; 109 - } 110 - 111 - function getLegacyTweetId(tweet: Readonly<LegacyTweetRaw>): string | undefined { 112 - if (tweet.id_str) { 113 - return tweet.id_str; 114 - } 115 - 116 - return tweet.conversation_id_str; 117 - } 118 - 119 - export function parseLegacyTweet( 120 - coreUser?: Readonly<CoreUserRaw>, 121 - user?: Readonly<LegacyUserRaw>, 122 - tweet?: Readonly<LegacyTweetRaw>, 123 - editControl?: Readonly<EditControlInitialRaw>, 124 - ): ParseTweetResult { 125 - if (tweet == null) { 126 - return { 127 - success: false, 128 - err: new Error('Tweet was not found in the timeline object.'), 129 - }; 130 - } 131 - 132 - if (user == null) { 133 - return { 134 - success: false, 135 - err: new Error('User was not found in the timeline object.'), 136 - }; 137 - } 138 - 139 - const tweetId = getLegacyTweetId(tweet); 140 - if (!tweetId) { 141 - return { 142 - success: false, 143 - err: new Error('Tweet ID was not found in object.'), 144 - }; 145 - } 146 - 147 - const hashtags = tweet.entities?.hashtags ?? []; 148 - const mentions = tweet.entities?.user_mentions ?? []; 149 - const media = tweet.extended_entities?.media ?? []; 150 - const pinnedTweets = new Set<string | undefined>( 151 - user.pinned_tweet_ids_str ?? [], 152 - ); 153 - const urls = tweet.entities?.urls ?? []; 154 - const { photos, videos, sensitiveContent } = parseMediaGroups(media); 155 - 156 - // The edit tweets array always contains the original tweet, even if it has not been edited 157 - const tweetVersions = editControl?.edit_tweet_ids ?? [tweetId]; 158 - 159 - const name = user.name ?? coreUser?.name; 160 - const username = user.screen_name ?? coreUser?.screen_name; 161 - const tw: Tweet = { 162 - __raw_UNSTABLE: tweet, 163 - bookmarkCount: tweet.bookmark_count, 164 - conversationId: tweet.conversation_id_str, 165 - id: tweetId, 166 - hashtags: hashtags 167 - .filter(isFieldDefined('text')) 168 - .map((hashtag) => hashtag.text), 169 - likes: tweet.favorite_count, 170 - mentions: mentions.filter(isFieldDefined('id_str')).map((mention) => ({ 171 - id: mention.id_str, 172 - username: mention.screen_name, 173 - name: mention.name, 174 - })), 175 - name: name, 176 - permanentUrl: `https://x.com/${username}/status/${tweetId}`, 177 - photos, 178 - replies: tweet.reply_count, 179 - retweets: tweet.retweet_count, 180 - text: tweet.full_text, 181 - thread: [], 182 - urls: urls 183 - .filter(isFieldDefined('expanded_url')) 184 - .map((url) => url.expanded_url), 185 - userId: tweet.user_id_str, 186 - username: username, 187 - videos, 188 - isQuoted: false, 189 - isReply: false, 190 - isEdited: tweetVersions.length > 1, 191 - versions: tweetVersions, 192 - isRetweet: false, 193 - isPin: false, 194 - sensitiveContent: false, 195 - }; 196 - 197 - if (tweet.created_at) { 198 - tw.timeParsed = new Date(Date.parse(tweet.created_at)); 199 - tw.timestamp = Math.floor(tw.timeParsed.valueOf() / 1000); 200 - } 201 - 202 - if (tweet.place?.id) { 203 - tw.place = tweet.place; 204 - } 205 - 206 - const quotedStatusIdStr = tweet.quoted_status_id_str; 207 - const inReplyToStatusIdStr = tweet.in_reply_to_status_id_str; 208 - const retweetedStatusIdStr = tweet.retweeted_status_id_str; 209 - const retweetedStatusResult = tweet.retweeted_status_result?.result; 210 - 211 - if (quotedStatusIdStr) { 212 - tw.isQuoted = true; 213 - tw.quotedStatusId = quotedStatusIdStr; 214 - } 215 - 216 - if (inReplyToStatusIdStr) { 217 - tw.isReply = true; 218 - tw.inReplyToStatusId = inReplyToStatusIdStr; 219 - } 220 - 221 - if (retweetedStatusIdStr || retweetedStatusResult) { 222 - tw.isRetweet = true; 223 - tw.retweetedStatusId = retweetedStatusIdStr; 224 - 225 - if (retweetedStatusResult) { 226 - const parsedResult = parseLegacyTweet( 227 - retweetedStatusResult?.core?.user_results?.result?.core, 228 - retweetedStatusResult?.core?.user_results?.result?.legacy, 229 - retweetedStatusResult?.legacy, 230 - retweetedStatusResult?.edit_control?.edit_control_initial, 231 - ); 232 - 233 - if (parsedResult.success) { 234 - tw.retweetedStatus = parsedResult.tweet; 235 - } 236 - } 237 - } 238 - 239 - const views = parseInt(tweet.ext_views?.count ?? ''); 240 - if (!isNaN(views)) { 241 - tw.views = views; 242 - } 243 - 244 - if (pinnedTweets.has(tweetId)) { 245 - // TODO: Update tests so this can be assigned at the tweet declaration 246 - tw.isPin = true; 247 - } 248 - 249 - if (sensitiveContent) { 250 - // TODO: Update tests so this can be assigned at the tweet declaration 251 - tw.sensitiveContent = true; 252 - } 253 - 254 - tw.html = reconstructTweetHtml(tweet, tw.photos, tw.videos); 255 - 256 - return { success: true, tweet: tw }; 257 - } 258 - 259 - function parseResult(result?: TimelineResultRaw): ParseTweetResult { 260 - const noteTweetResultText = 261 - result?.note_tweet?.note_tweet_results?.result?.text; 262 - 263 - if (result?.legacy && noteTweetResultText) { 264 - result.legacy.full_text = noteTweetResultText; 265 - } 266 - 267 - const tweetResult = parseLegacyTweet( 268 - result?.core?.user_results?.result?.core, 269 - result?.core?.user_results?.result?.legacy, 270 - result?.legacy, 271 - result?.edit_control?.edit_control_initial, 272 - ); 273 - if (!tweetResult.success) { 274 - return tweetResult; 275 - } 276 - 277 - if (!tweetResult.tweet.views && result?.views?.count) { 278 - const views = parseInt(result.views.count); 279 - if (!isNaN(views)) { 280 - tweetResult.tweet.views = views; 281 - } 282 - } 283 - 284 - const quotedResult = result?.quoted_status_result?.result; 285 - if (quotedResult) { 286 - if (quotedResult.legacy && quotedResult.rest_id) { 287 - quotedResult.legacy.id_str = quotedResult.rest_id; 288 - } 289 - 290 - const quotedTweetResult = parseResult(quotedResult); 291 - if (quotedTweetResult.success) { 292 - tweetResult.tweet.quotedStatus = quotedTweetResult.tweet; 293 - } 294 - } 295 - 296 - return tweetResult; 297 - } 298 - 299 - const expectedEntryTypes = ['tweet', 'profile-conversation']; 300 - 301 - function getTimelineInstructionEntries( 302 - instruction: TimelineInstruction, 303 - ): TimelineEntryRaw[] { 304 - const entries = instruction.entries ?? []; 305 - if (instruction.entry) { 306 - entries.push(instruction.entry); 307 - } 308 - return entries; 309 - } 310 - 311 - export function parseTimelineTweetsV2( 312 - timeline: TimelineV2, 313 - ): QueryTweetsResponse { 314 - let bottomCursor: string | undefined; 315 - let topCursor: string | undefined; 316 - const tweets: Tweet[] = []; 317 - const instructions = 318 - timeline.data?.user?.result?.timeline?.timeline?.instructions ?? []; 319 - for (const instruction of instructions) { 320 - const entries = getTimelineInstructionEntries(instruction); 321 - for (const entry of entries) { 322 - const entryContent = entry.content; 323 - if (!entryContent) continue; 324 - 325 - // Handle pagination 326 - if (entryContent.cursorType === 'Bottom') { 327 - bottomCursor = entryContent.value; 328 - continue; 329 - } else if (entryContent.cursorType === 'Top') { 330 - topCursor = entryContent.value; 331 - continue; 332 - } 333 - 334 - const idStr = entry.entryId; 335 - if ( 336 - !expectedEntryTypes.some((entryType) => idStr.startsWith(entryType)) 337 - ) { 338 - continue; 339 - } 340 - 341 - if (entryContent.itemContent) { 342 - // Typically TimelineTimelineTweet entries 343 - parseAndPush(tweets, entryContent.itemContent, idStr); 344 - } else if (entryContent.items) { 345 - // Typically TimelineTimelineModule entries 346 - for (const item of entryContent.items) { 347 - if (item.item?.itemContent) { 348 - parseAndPush(tweets, item.item.itemContent, idStr); 349 - } 350 - } 351 - } 352 - } 353 - } 354 - 355 - return { tweets, next: bottomCursor, previous: topCursor }; 356 - } 357 - 358 - export function parseTimelineEntryItemContentRaw( 359 - content: TimelineEntryItemContentRaw, 360 - entryId: string, 361 - isConversation = false, 362 - ) { 363 - let result = content.tweet_results?.result ?? content.tweetResult?.result; 364 - if ( 365 - result?.__typename === 'Tweet' || 366 - (result?.__typename === 'TweetWithVisibilityResults' && result?.tweet) 367 - ) { 368 - if (result?.__typename === 'TweetWithVisibilityResults') 369 - result = result.tweet; 370 - 371 - if (result?.legacy) { 372 - result.legacy.id_str = 373 - result.rest_id ?? 374 - entryId.replace('conversation-', '').replace('tweet-', ''); 375 - } 376 - 377 - const tweetResult = parseResult(result); 378 - if (tweetResult.success) { 379 - if (isConversation) { 380 - if (content?.tweetDisplayType === 'SelfThread') { 381 - tweetResult.tweet.isSelfThread = true; 382 - } 383 - } 384 - 385 - return tweetResult.tweet; 386 - } 387 - } 388 - 389 - return null; 390 - } 391 - 392 - export function parseAndPush( 393 - tweets: Tweet[], 394 - content: TimelineEntryItemContentRaw, 395 - entryId: string, 396 - isConversation = false, 397 - ) { 398 - const tweet = parseTimelineEntryItemContentRaw( 399 - content, 400 - entryId, 401 - isConversation, 402 - ); 403 - 404 - if (tweet) { 405 - tweets.push(tweet); 406 - } 407 - } 408 - 409 - export function parseThreadedConversation( 410 - conversation: ThreadedConversation, 411 - ): Tweet[] { 412 - const tweets: Tweet[] = []; 413 - const instructions = 414 - conversation.data?.threaded_conversation_with_injections_v2?.instructions ?? 415 - []; 416 - 417 - for (const instruction of instructions) { 418 - const entries = getTimelineInstructionEntries(instruction); 419 - for (const entry of entries) { 420 - const entryContent = entry.content?.itemContent; 421 - if (entryContent) { 422 - parseAndPush(tweets, entryContent, entry.entryId, true); 423 - } 424 - 425 - for (const item of entry.content?.items ?? []) { 426 - const itemContent = item.item?.itemContent; 427 - if (itemContent) { 428 - parseAndPush(tweets, itemContent, entry.entryId, true); 429 - } 430 - } 431 - } 432 - } 433 - 434 - for (const tweet of tweets) { 435 - if (tweet.inReplyToStatusId) { 436 - for (const parentTweet of tweets) { 437 - if (parentTweet.id === tweet.inReplyToStatusId) { 438 - tweet.inReplyToStatus = parentTweet; 439 - break; 440 - } 441 - } 442 - } 443 - 444 - if (tweet.isSelfThread && tweet.conversationId === tweet.id) { 445 - for (const childTweet of tweets) { 446 - if (childTweet.isSelfThread && childTweet.id !== tweet.id) { 447 - tweet.thread.push(childTweet); 448 - } 449 - } 450 - 451 - if (tweet.thread.length === 0) { 452 - tweet.isSelfThread = false; 453 - } 454 - } 455 - } 456 - 457 - return tweets; 458 - }
-8
twitter-scraper/src/trends.test.ts
··· 1 - import { getScraper } from './test-utils'; 2 - 3 - test('scraper can get trends', async () => { 4 - const scraper = await getScraper(); 5 - const trends = await scraper.getTrends(); 6 - expect(trends).toHaveLength(20); 7 - trends.forEach((trend) => expect(trend).not.toBeFalsy()); 8 - }, 15000);
-52
twitter-scraper/src/trends.ts
··· 1 - import { addApiParams, requestApi, bearerToken2 } from './api'; 2 - import { TwitterAuth } from './auth'; 3 - import { TimelineV1 } from './timeline-v1'; 4 - 5 - export async function getTrends(auth: TwitterAuth): Promise<string[]> { 6 - const params = new URLSearchParams(); 7 - addApiParams(params, false); 8 - 9 - params.set('count', '20'); 10 - params.set('candidate_source', 'trends'); 11 - params.set('include_page_configuration', 'false'); 12 - params.set('entity_tokens', 'false'); 13 - 14 - // Use bearerToken2 for trends endpoint 15 - const res = await requestApi<TimelineV1>( 16 - `https://api.x.com/2/guide.json?${params.toString()}`, 17 - auth, 18 - 'GET', 19 - undefined, 20 - undefined, 21 - bearerToken2, 22 - ); 23 - if (!res.success) { 24 - throw res.err; 25 - } 26 - 27 - const instructions = res.value.timeline?.instructions ?? []; 28 - if (instructions.length < 2) { 29 - throw new Error('No trend entries found.'); 30 - } 31 - 32 - // Some of this is silly, but for now we're assuming we know nothing about the 33 - // data, and that anything can be missing. Go has non-nilable strings and empty 34 - // slices are nil, so it largely doesn't need to worry about this. 35 - const entries = instructions[1].addEntries?.entries ?? []; 36 - if (entries.length < 2) { 37 - throw new Error('No trend entries found.'); 38 - } 39 - 40 - const items = entries[1].content?.timelineModule?.items ?? []; 41 - const trends: string[] = []; 42 - for (const item of items) { 43 - const trend = 44 - item.item?.clientEventInfo?.details?.guideDetails?.transparentGuideDetails 45 - ?.trendMetadata?.trendName; 46 - if (trend != null) { 47 - trends.push(trend); 48 - } 49 - } 50 - 51 - return trends; 52 - }
-408
twitter-scraper/src/tweets.test.ts
··· 1 - import { getScraper } from './test-utils'; 2 - import { Mention, Tweet } from './tweets'; 3 - import { QueryTweetsResponse } from './timeline-v1'; 4 - 5 - test('scraper can get tweet', async () => { 6 - const expected: Tweet = { 7 - conversationId: '1585338303800578049', 8 - html: `We’re updating Twitter’s sounds to help make them pleasing to more people, including those with sensory sensitivities. Here’s more on how we did it:<br><a href=\"https://blog.twitter.com/en_us/topics/product/2022/designing-accessible-sounds-story-behind-our-new-chirps\">https://t.co/7FKWk7NzHM</a>`, 9 - id: '1585338303800578049', 10 - hashtags: [], 11 - mentions: [], 12 - name: 'A11y', 13 - permanentUrl: 'https://x.com/XA11y/status/1585338303800578049', 14 - photos: [], 15 - text: 'We’re updating Twitter’s sounds to help make them pleasing to more people, including those with sensory sensitivities. Here’s more on how we did it:\nhttps://t.co/7FKWk7NzHM', 16 - thread: [], 17 - timeParsed: new Date(Date.UTC(2022, 9, 26, 18, 31, 20, 0)), 18 - timestamp: 1666809080, 19 - urls: [ 20 - 'https://blog.twitter.com/en_us/topics/product/2022/designing-accessible-sounds-story-behind-our-new-chirps', 21 - ], 22 - userId: '1631299117', 23 - username: 'XA11y', 24 - videos: [], 25 - isQuoted: false, 26 - isReply: false, 27 - isEdited: false, 28 - versions: ['1585338303800578049'], 29 - isRetweet: false, 30 - isPin: false, 31 - sensitiveContent: false, 32 - }; 33 - 34 - const scraper = await getScraper(); 35 - const actual = await scraper.getTweet('1585338303800578049'); 36 - delete actual?.__raw_UNSTABLE; 37 - delete actual?.likes; 38 - delete actual?.replies; 39 - delete actual?.retweets; 40 - delete actual?.views; 41 - delete actual?.bookmarkCount; 42 - expect(actual).toEqual(expected); 43 - }); 44 - 45 - test('scraper can get tweets without logging in', async () => { 46 - const scraper = await getScraper({ authMethod: 'anonymous' }); 47 - 48 - let counter = 0; 49 - for await (const tweet of scraper.getTweets('elonmusk', 10)) { 50 - if (tweet) { 51 - counter++; 52 - } 53 - } 54 - 55 - expect(counter).toBeGreaterThanOrEqual(1); 56 - }); 57 - 58 - test('scraper can get tweets by user', async () => { 59 - const scraper = await getScraper(); 60 - 61 - let counter = 0; 62 - for await (const tweet of scraper.getTweets('GeminiApp', 10)) { 63 - if (tweet) { 64 - counter++; 65 - } 66 - } 67 - 68 - expect(counter).toBeGreaterThanOrEqual(1); 69 - }); 70 - 71 - test('scraper can get tweets by user ID', async () => { 72 - const scraper = await getScraper(); 73 - 74 - let counter = 0; 75 - for await (const tweet of scraper.getTweetsByUserId( 76 - '1016333328083910656', 77 - 10, 78 - )) { 79 - if (tweet) { 80 - counter++; 81 - } 82 - } 83 - 84 - expect(counter).toBeGreaterThanOrEqual(1); 85 - }); 86 - 87 - test('scraper can get tweets and replies by user', async () => { 88 - const scraper = await getScraper(); 89 - 90 - let counter = 0; 91 - for await (const tweet of scraper.getTweetsAndReplies('GeminiApp', 10)) { 92 - if (tweet) { 93 - counter++; 94 - } 95 - } 96 - 97 - expect(counter).toBeGreaterThanOrEqual(1); 98 - }); 99 - 100 - test('scraper can get tweets and replies by user ID', async () => { 101 - const scraper = await getScraper(); 102 - 103 - let counter = 0; 104 - for await (const tweet of scraper.getTweetsAndRepliesByUserId( 105 - '1016333328083910656', 106 - 10, 107 - )) { 108 - if (tweet) { 109 - counter++; 110 - } 111 - } 112 - 113 - expect(counter).toBeGreaterThanOrEqual(1); 114 - }); 115 - 116 - test('scraper can get tweets from list', async () => { 117 - const scraper = await getScraper(); 118 - 119 - let cursor: string | undefined = undefined; 120 - const maxTweets = 30; 121 - let nTweets = 0; 122 - while (nTweets < maxTweets) { 123 - const res: QueryTweetsResponse = await scraper.fetchListTweets( 124 - '1736495155002106192', 125 - maxTweets, 126 - cursor, 127 - ); 128 - 129 - expect(res.next).toBeTruthy(); 130 - 131 - nTweets += res.tweets.length; 132 - cursor = res.next; 133 - } 134 - }); 135 - 136 - test('scraper can get first tweet matching query', async () => { 137 - const scraper = await getScraper(); 138 - 139 - const timeline = scraper.getTweets('elonmusk'); 140 - const latestQuote = await scraper.getTweetWhere(timeline, { isQuoted: true }); 141 - 142 - expect(latestQuote?.isQuoted).toBeTruthy(); 143 - }); 144 - 145 - test('scraper can get all tweets matching query', async () => { 146 - const scraper = await getScraper(); 147 - 148 - // Sample size of 20 should be enough without taking long. 149 - const timeline = scraper.getTweets('elonmusk', 20); 150 - const retweets = await scraper.getTweetsWhere( 151 - timeline, 152 - (tweet) => tweet.isRetweet === true, 153 - ); 154 - 155 - expect(retweets).toBeTruthy(); 156 - 157 - for (const tweet of retweets) { 158 - expect(tweet.isRetweet).toBe(true); 159 - } 160 - }, 20000); 161 - 162 - test('scraper can get latest tweet', async () => { 163 - const scraper = await getScraper(); 164 - 165 - // OLD APPROACH (without retweet filtering) 166 - const tweets = scraper.getTweets('elonmusk', 1); 167 - const expected = (await tweets.next()).value; 168 - 169 - // NEW APPROACH 170 - const latest = (await scraper.getLatestTweet( 171 - 'elonmusk', 172 - expected?.isRetweet || false, 173 - )) as Tweet; 174 - 175 - expect(latest?.permanentUrl).toEqual(expected?.permanentUrl); 176 - }, 30000); 177 - 178 - test('scraper can get user mentions in tweets', async () => { 179 - const expected: Mention[] = [ 180 - { 181 - id: '7018222', 182 - username: 'davidmcraney', 183 - name: 'David McRaney', 184 - }, 185 - ]; 186 - 187 - const scraper = await getScraper(); 188 - const tweet = await scraper.getTweet('1554522888904101890'); 189 - expect(tweet?.mentions).toEqual(expected); 190 - }); 191 - 192 - test('scraper can get tweet quotes without logging in', async () => { 193 - const expected: Tweet = { 194 - conversationId: '1237110546383724547', 195 - html: `The Easiest Problem Everyone Gets Wrong <br><br>[new video] --&gt; <a href=\"https://youtu.be/ytfCdqWhmdg\">https://t.co/YdaeDYmPAU</a> <br><a href=\"https://t.co/iKu4Xs6o2V\"><img src=\"https://pbs.twimg.com/media/ESsZa9AXgAIAYnF.jpg\"/></a>`, 196 - id: '1237110546383724547', 197 - hashtags: [], 198 - mentions: [], 199 - name: 'Vsauce2', 200 - permanentUrl: 'https://x.com/VsauceTwo/status/1237110546383724547', 201 - photos: [ 202 - { 203 - id: '1237110473486729218', 204 - url: 'https://pbs.twimg.com/media/ESsZa9AXgAIAYnF.jpg', 205 - alt_text: undefined, 206 - }, 207 - ], 208 - text: 'The Easiest Problem Everyone Gets Wrong \n\n[new video] --&gt; https://t.co/YdaeDYmPAU https://t.co/iKu4Xs6o2V', 209 - thread: [], 210 - timeParsed: new Date(Date.UTC(2020, 2, 9, 20, 18, 33, 0)), 211 - timestamp: 1583785113, 212 - urls: ['https://youtu.be/ytfCdqWhmdg'], 213 - userId: '978944851', 214 - username: 'VsauceTwo', 215 - videos: [], 216 - isQuoted: false, 217 - isReply: false, 218 - isEdited: false, 219 - versions: ['1237110546383724547'], 220 - isRetweet: false, 221 - isPin: false, 222 - sensitiveContent: false, 223 - }; 224 - 225 - const scraper = await getScraper({ authMethod: 'anonymous' }); 226 - const quote = await scraper.getTweet('1237110897597976576'); 227 - expect(quote?.isQuoted).toBeTruthy(); 228 - delete quote?.quotedStatus?.__raw_UNSTABLE; 229 - delete quote?.quotedStatus?.likes; 230 - delete quote?.quotedStatus?.replies; 231 - delete quote?.quotedStatus?.retweets; 232 - delete quote?.quotedStatus?.views; 233 - delete quote?.quotedStatus?.bookmarkCount; 234 - expect(quote?.quotedStatus).toEqual(expected); 235 - }); 236 - 237 - test('scraper can get tweet quotes and replies', async () => { 238 - const expected: Tweet = { 239 - conversationId: '1237110546383724547', 240 - html: `The Easiest Problem Everyone Gets Wrong <br><br>[new video] --&gt; <a href=\"https://youtu.be/ytfCdqWhmdg\">https://t.co/YdaeDYmPAU</a> <br><a href=\"https://t.co/iKu4Xs6o2V\"><img src=\"https://pbs.twimg.com/media/ESsZa9AXgAIAYnF.jpg\"/></a>`, 241 - id: '1237110546383724547', 242 - hashtags: [], 243 - mentions: [], 244 - name: 'Vsauce2', 245 - permanentUrl: 'https://x.com/VsauceTwo/status/1237110546383724547', 246 - photos: [ 247 - { 248 - id: '1237110473486729218', 249 - url: 'https://pbs.twimg.com/media/ESsZa9AXgAIAYnF.jpg', 250 - alt_text: undefined, 251 - }, 252 - ], 253 - text: 'The Easiest Problem Everyone Gets Wrong \n\n[new video] --&gt; https://t.co/YdaeDYmPAU https://t.co/iKu4Xs6o2V', 254 - thread: [], 255 - timeParsed: new Date(Date.UTC(2020, 2, 9, 20, 18, 33, 0)), 256 - timestamp: 1583785113, 257 - urls: ['https://youtu.be/ytfCdqWhmdg'], 258 - userId: '978944851', 259 - username: 'VsauceTwo', 260 - videos: [], 261 - isQuoted: false, 262 - isReply: false, 263 - isEdited: false, 264 - versions: ['1237110546383724547'], 265 - isRetweet: false, 266 - isPin: false, 267 - sensitiveContent: false, 268 - }; 269 - 270 - const scraper = await getScraper(); 271 - const quote = await scraper.getTweet('1237110897597976576'); 272 - expect(quote?.isQuoted).toBeTruthy(); 273 - delete quote?.quotedStatus?.__raw_UNSTABLE; 274 - delete quote?.quotedStatus?.likes; 275 - delete quote?.quotedStatus?.replies; 276 - delete quote?.quotedStatus?.retweets; 277 - delete quote?.quotedStatus?.views; 278 - delete quote?.quotedStatus?.bookmarkCount; 279 - expect(quote?.quotedStatus).toEqual(expected); 280 - 281 - const reply = await scraper.getTweet('1237111868445134850'); 282 - expect(reply?.isReply).toBeTruthy(); 283 - if (reply != null) { 284 - reply.isReply = false; 285 - } 286 - delete reply?.inReplyToStatus?.__raw_UNSTABLE; 287 - delete reply?.inReplyToStatus?.likes; 288 - delete reply?.inReplyToStatus?.replies; 289 - delete reply?.inReplyToStatus?.retweets; 290 - delete reply?.inReplyToStatus?.views; 291 - delete reply?.inReplyToStatus?.bookmarkCount; 292 - expect(reply?.inReplyToStatus).toEqual(expected); 293 - }); 294 - 295 - test('scraper can get retweet', async () => { 296 - const expected: Tweet = { 297 - conversationId: '1776276954435481937', 298 - html: `<br><a href=\"https://t.co/qqiu5ntffp\"><img src=\"https://pbs.twimg.com/amplify_video_thumb/1776276900580622336/img/UknAtyWSZ286nCD3.jpg\"/></a>`, 299 - id: '1776276954435481937', 300 - hashtags: [], 301 - mentions: [], 302 - name: 'federico.', 303 - permanentUrl: 'https://x.com/federicosmos/status/1776276954435481937', 304 - photos: [], 305 - text: 'https://t.co/qqiu5ntffp', 306 - thread: [], 307 - timeParsed: new Date(Date.UTC(2024, 3, 5, 15, 53, 22, 0)), 308 - timestamp: 1712332402, 309 - urls: [], 310 - userId: '2376017065', 311 - username: 'federicosmos', 312 - videos: [ 313 - { 314 - id: '1776276900580622336', 315 - preview: 316 - 'https://pbs.twimg.com/amplify_video_thumb/1776276900580622336/img/UknAtyWSZ286nCD3.jpg', 317 - url: 'https://video.twimg.com/amplify_video/1776276900580622336/vid/avc1/640x360/uACt_egp_hmvPOZF.mp4?tag=14', 318 - }, 319 - ], 320 - isQuoted: false, 321 - isReply: false, 322 - isEdited: false, 323 - versions: ['1776276954435481937'], 324 - isRetweet: false, 325 - isPin: false, 326 - sensitiveContent: false, 327 - }; 328 - 329 - const scraper = await getScraper(); 330 - const retweet = await scraper.getTweet('1776285549566808397'); 331 - expect(retweet?.isRetweet).toBeTruthy(); 332 - delete retweet?.retweetedStatus?.__raw_UNSTABLE; 333 - delete retweet?.retweetedStatus?.likes; 334 - delete retweet?.retweetedStatus?.replies; 335 - delete retweet?.retweetedStatus?.retweets; 336 - delete retweet?.retweetedStatus?.views; 337 - delete retweet?.retweetedStatus?.bookmarkCount; 338 - expect(retweet?.retweetedStatus).toEqual(expected); 339 - }); 340 - 341 - test('scraper can get tweet views', async () => { 342 - const expected: Tweet = { 343 - conversationId: '1606055187348688896', 344 - html: `Replies and likes don’t tell the whole story. We’re making it easier to tell *just* how many people have seen your Tweets with the addition of view counts, shown right next to likes. Now on iOS and Android, web coming soon.<br><br><a href=\"https://help.twitter.com/using-twitter/view-counts\">https://t.co/hrlMQyXJfx</a>`, 345 - id: '1606055187348688896', 346 - hashtags: [], 347 - mentions: [], 348 - name: 'Support', 349 - permanentUrl: 'https://x.com/Support/status/1606055187348688896', 350 - photos: [], 351 - text: 'Replies and likes don’t tell the whole story. We’re making it easier to tell *just* how many people have seen your Tweets with the addition of view counts, shown right next to likes. Now on iOS and Android, web coming soon.\n\nhttps://t.co/hrlMQyXJfx', 352 - thread: [], 353 - timeParsed: new Date(Date.UTC(2022, 11, 22, 22, 32, 50, 0)), 354 - timestamp: 1671748370, 355 - urls: ['https://help.twitter.com/using-twitter/view-counts'], 356 - userId: '17874544', 357 - username: 'Support', 358 - videos: [], 359 - isQuoted: false, 360 - isReply: false, 361 - isEdited: false, 362 - versions: ['1606055187348688896'], 363 - isRetweet: false, 364 - isPin: false, 365 - sensitiveContent: false, 366 - }; 367 - 368 - const scraper = await getScraper(); 369 - const actual = await scraper.getTweet('1606055187348688896'); 370 - expect(actual?.views).toBeTruthy(); 371 - delete actual?.__raw_UNSTABLE; 372 - delete actual?.likes; 373 - delete actual?.replies; 374 - delete actual?.retweets; 375 - delete actual?.views; 376 - delete actual?.bookmarkCount; 377 - expect(actual).toEqual(expected); 378 - }); 379 - 380 - test('scraper can get tweet thread', async () => { 381 - const scraper = await getScraper(); 382 - const tweet = await scraper.getTweet('1665602315745673217'); 383 - expect(tweet).not.toBeNull(); 384 - expect(tweet?.isSelfThread).toBeTruthy(); 385 - expect(tweet?.thread.length).toStrictEqual(7); 386 - }); 387 - 388 - test('scraper can get liked tweets', async () => { 389 - const scraper = await getScraper(); 390 - const liked = scraper.getLikedTweets('elonmusk', 10); 391 - const tweet = await liked.next(); 392 - expect(tweet.value).not.toBeUndefined(); 393 - expect(tweet.done).toBeFalsy(); 394 - expect(tweet.value?.id).not.toBeUndefined(); 395 - }); 396 - 397 - test('scraper can get animated image as video', async () => { 398 - const scraper = await getScraper({ authMethod: 'anonymous' }); 399 - const tweet = await scraper.getTweet('1947627689285673423'); 400 - 401 - const expectedURL = 'https://video.twimg.com/tweet_video/GwdbuOGX0AEuVrj.mp4'; 402 - 403 - expect(tweet?.videos).toContainEqual({ 404 - id: '1947626213477961729', 405 - preview: expectedURL, 406 - url: expectedURL, 407 - }); 408 - });
-449
twitter-scraper/src/tweets.ts
··· 1 - import { addApiFeatures, requestApi, bearerToken2 } from './api'; 2 - import { TwitterAuth } from './auth'; 3 - import { getUserIdByScreenName } from './profile'; 4 - import { LegacyTweetRaw, QueryTweetsResponse } from './timeline-v1'; 5 - import { 6 - parseTimelineTweetsV2, 7 - TimelineV2, 8 - TimelineEntryItemContentRaw, 9 - parseTimelineEntryItemContentRaw, 10 - ThreadedConversation, 11 - parseThreadedConversation, 12 - } from './timeline-v2'; 13 - import { getTweetTimeline } from './timeline-async'; 14 - import { apiRequestFactory } from './api-data'; 15 - import { ListTimeline, parseListTimelineTweets } from './timeline-list'; 16 - import { AuthenticationError } from './errors'; 17 - 18 - export interface Mention { 19 - id: string; 20 - username?: string; 21 - name?: string; 22 - } 23 - 24 - export interface Photo { 25 - id: string; 26 - url: string; 27 - alt_text: string | undefined; 28 - } 29 - 30 - export interface Video { 31 - id: string; 32 - preview: string; 33 - url?: string; 34 - } 35 - 36 - export interface PlaceRaw { 37 - id?: string; 38 - place_type?: string; 39 - name?: string; 40 - full_name?: string; 41 - country_code?: string; 42 - country?: string; 43 - bounding_box?: { 44 - type?: string; 45 - coordinates?: number[][][]; 46 - }; 47 - } 48 - 49 - /** 50 - * A parsed Tweet object. 51 - */ 52 - export interface Tweet { 53 - __raw_UNSTABLE?: LegacyTweetRaw; 54 - bookmarkCount?: number; 55 - conversationId?: string; 56 - hashtags: string[]; 57 - html?: string; 58 - id?: string; 59 - inReplyToStatus?: Tweet; 60 - inReplyToStatusId?: string; 61 - isEdited?: boolean; 62 - versions?: string[]; 63 - isQuoted?: boolean; 64 - isPin?: boolean; 65 - isReply?: boolean; 66 - isRetweet?: boolean; 67 - isSelfThread?: boolean; 68 - likes?: number; 69 - name?: string; 70 - mentions: Mention[]; 71 - permanentUrl?: string; 72 - photos: Photo[]; 73 - place?: PlaceRaw; 74 - quotedStatus?: Tweet; 75 - quotedStatusId?: string; 76 - replies?: number; 77 - retweets?: number; 78 - retweetedStatus?: Tweet; 79 - retweetedStatusId?: string; 80 - text?: string; 81 - thread: Tweet[]; 82 - timeParsed?: Date; 83 - timestamp?: number; 84 - urls: string[]; 85 - userId?: string; 86 - username?: string; 87 - videos: Video[]; 88 - views?: number; 89 - sensitiveContent?: boolean; 90 - } 91 - 92 - export type TweetQuery = 93 - | Partial<Tweet> 94 - | ((tweet: Tweet) => boolean | Promise<boolean>); 95 - 96 - export const features = addApiFeatures({ 97 - interactive_text_enabled: true, 98 - longform_notetweets_inline_media_enabled: false, 99 - responsive_web_text_conversations_enabled: false, 100 - tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: 101 - false, 102 - vibe_api_enabled: false, 103 - }); 104 - 105 - export async function fetchTweets( 106 - userId: string, 107 - maxTweets: number, 108 - cursor: string | undefined, 109 - auth: TwitterAuth, 110 - ): Promise<QueryTweetsResponse> { 111 - if (maxTweets > 200) { 112 - maxTweets = 200; 113 - } 114 - 115 - const userTweetsRequest = apiRequestFactory.createUserTweetsRequest(); 116 - userTweetsRequest.variables.userId = userId; 117 - userTweetsRequest.variables.count = maxTweets; 118 - userTweetsRequest.variables.includePromotedContent = false; // true on the website 119 - 120 - if (cursor != null && cursor != '') { 121 - userTweetsRequest.variables['cursor'] = cursor; 122 - } 123 - 124 - // Use bearerToken2 for UserTweets endpoint 125 - const res = await requestApi<TimelineV2>( 126 - userTweetsRequest.toRequestUrl(), 127 - auth, 128 - 'GET', 129 - undefined, 130 - undefined, 131 - bearerToken2, 132 - ); 133 - 134 - if (!res.success) { 135 - throw res.err; 136 - } 137 - 138 - return parseTimelineTweetsV2(res.value); 139 - } 140 - 141 - export async function fetchTweetsAndReplies( 142 - userId: string, 143 - maxTweets: number, 144 - cursor: string | undefined, 145 - auth: TwitterAuth, 146 - ): Promise<QueryTweetsResponse> { 147 - if (maxTweets > 40) { 148 - maxTweets = 40; 149 - } 150 - 151 - const userTweetsRequest = 152 - apiRequestFactory.createUserTweetsAndRepliesRequest(); 153 - userTweetsRequest.variables.userId = userId; 154 - userTweetsRequest.variables.count = maxTweets; 155 - userTweetsRequest.variables.includePromotedContent = false; // true on the website 156 - 157 - if (cursor != null && cursor != '') { 158 - userTweetsRequest.variables['cursor'] = cursor; 159 - } 160 - 161 - // Use bearerToken2 for UserTweetsAndReplies endpoint 162 - const res = await requestApi<TimelineV2>( 163 - userTweetsRequest.toRequestUrl(), 164 - auth, 165 - 'GET', 166 - undefined, 167 - undefined, 168 - bearerToken2, 169 - ); 170 - 171 - if (!res.success) { 172 - throw res.err; 173 - } 174 - 175 - return parseTimelineTweetsV2(res.value); 176 - } 177 - 178 - export async function fetchListTweets( 179 - listId: string, 180 - maxTweets: number, 181 - cursor: string | undefined, 182 - auth: TwitterAuth, 183 - ): Promise<QueryTweetsResponse> { 184 - if (maxTweets > 200) { 185 - maxTweets = 200; 186 - } 187 - 188 - const listTweetsRequest = apiRequestFactory.createListTweetsRequest(); 189 - listTweetsRequest.variables.listId = listId; 190 - listTweetsRequest.variables.count = maxTweets; 191 - 192 - if (cursor != null && cursor != '') { 193 - listTweetsRequest.variables['cursor'] = cursor; 194 - } 195 - 196 - // Use bearerToken2 for ListTweet endpoint 197 - const res = await requestApi<ListTimeline>( 198 - listTweetsRequest.toRequestUrl(), 199 - auth, 200 - 'GET', 201 - undefined, 202 - undefined, 203 - bearerToken2, 204 - ); 205 - 206 - if (!res.success) { 207 - throw res.err; 208 - } 209 - 210 - return parseListTimelineTweets(res.value); 211 - } 212 - 213 - export function getTweets( 214 - user: string, 215 - maxTweets: number, 216 - auth: TwitterAuth, 217 - ): AsyncGenerator<Tweet, void> { 218 - return getTweetTimeline(user, maxTweets, async (q, mt, c) => { 219 - const userIdRes = await getUserIdByScreenName(q, auth); 220 - 221 - if (!userIdRes.success) { 222 - throw userIdRes.err; 223 - } 224 - 225 - const { value: userId } = userIdRes; 226 - 227 - return fetchTweets(userId, mt, c, auth); 228 - }); 229 - } 230 - 231 - export function getTweetsByUserId( 232 - userId: string, 233 - maxTweets: number, 234 - auth: TwitterAuth, 235 - ): AsyncGenerator<Tweet, void> { 236 - return getTweetTimeline(userId, maxTweets, (q, mt, c) => { 237 - return fetchTweets(q, mt, c, auth); 238 - }); 239 - } 240 - 241 - export function getTweetsAndReplies( 242 - user: string, 243 - maxTweets: number, 244 - auth: TwitterAuth, 245 - ): AsyncGenerator<Tweet, void> { 246 - return getTweetTimeline(user, maxTweets, async (q, mt, c) => { 247 - const userIdRes = await getUserIdByScreenName(q, auth); 248 - 249 - if (!userIdRes.success) { 250 - throw userIdRes.err; 251 - } 252 - 253 - const { value: userId } = userIdRes; 254 - 255 - return fetchTweetsAndReplies(userId, mt, c, auth); 256 - }); 257 - } 258 - 259 - export function getTweetsAndRepliesByUserId( 260 - userId: string, 261 - maxTweets: number, 262 - auth: TwitterAuth, 263 - ): AsyncGenerator<Tweet, void> { 264 - return getTweetTimeline(userId, maxTweets, (q, mt, c) => { 265 - return fetchTweetsAndReplies(q, mt, c, auth); 266 - }); 267 - } 268 - 269 - export async function fetchLikedTweets( 270 - userId: string, 271 - maxTweets: number, 272 - cursor: string | undefined, 273 - auth: TwitterAuth, 274 - ): Promise<QueryTweetsResponse> { 275 - if (!(await auth.isLoggedIn())) { 276 - throw new AuthenticationError( 277 - 'Scraper is not logged-in for fetching liked tweets.', 278 - ); 279 - } 280 - 281 - if (maxTweets > 200) { 282 - maxTweets = 200; 283 - } 284 - 285 - const userTweetsRequest = apiRequestFactory.createUserLikedTweetsRequest(); 286 - userTweetsRequest.variables.userId = userId; 287 - userTweetsRequest.variables.count = maxTweets; 288 - userTweetsRequest.variables.includePromotedContent = false; // true on the website 289 - 290 - if (cursor != null && cursor != '') { 291 - userTweetsRequest.variables['cursor'] = cursor; 292 - } 293 - 294 - // Use bearerToken2 for UserLikedTweets endpoint 295 - const res = await requestApi<TimelineV2>( 296 - userTweetsRequest.toRequestUrl(), 297 - auth, 298 - 'GET', 299 - undefined, 300 - undefined, 301 - bearerToken2, 302 - ); 303 - 304 - if (!res.success) { 305 - throw res.err; 306 - } 307 - 308 - return parseTimelineTweetsV2(res.value); 309 - } 310 - 311 - export function getLikedTweets( 312 - user: string, 313 - maxTweets: number, 314 - auth: TwitterAuth, 315 - ): AsyncGenerator<Tweet, void> { 316 - return getTweetTimeline(user, maxTweets, async (q, mt, c) => { 317 - const userIdRes = await getUserIdByScreenName(q, auth); 318 - 319 - if (!userIdRes.success) { 320 - throw userIdRes.err; 321 - } 322 - 323 - const { value: userId } = userIdRes; 324 - 325 - return fetchLikedTweets(userId, mt, c, auth); 326 - }); 327 - } 328 - 329 - export async function getTweetWhere( 330 - tweets: AsyncIterable<Tweet>, 331 - query: TweetQuery, 332 - ): Promise<Tweet | null> { 333 - const isCallback = typeof query === 'function'; 334 - 335 - for await (const tweet of tweets) { 336 - const matches = isCallback 337 - ? await query(tweet) 338 - : checkTweetMatches(tweet, query); 339 - 340 - if (matches) { 341 - return tweet; 342 - } 343 - } 344 - 345 - return null; 346 - } 347 - 348 - export async function getTweetsWhere( 349 - tweets: AsyncIterable<Tweet>, 350 - query: TweetQuery, 351 - ): Promise<Tweet[]> { 352 - const isCallback = typeof query === 'function'; 353 - const filtered = []; 354 - 355 - for await (const tweet of tweets) { 356 - const matches = isCallback ? query(tweet) : checkTweetMatches(tweet, query); 357 - 358 - if (!matches) continue; 359 - filtered.push(tweet); 360 - } 361 - 362 - return filtered; 363 - } 364 - 365 - function checkTweetMatches(tweet: Tweet, options: Partial<Tweet>): boolean { 366 - return Object.keys(options).every((k) => { 367 - const key = k as keyof Tweet; 368 - return tweet[key] === options[key]; 369 - }); 370 - } 371 - 372 - export async function getLatestTweet( 373 - user: string, 374 - includeRetweets: boolean, 375 - max: number, 376 - auth: TwitterAuth, 377 - ): Promise<Tweet | null | void> { 378 - const timeline = getTweets(user, max, auth); 379 - 380 - // No point looping if max is 1, just use first entry. 381 - return max === 1 382 - ? (await timeline.next()).value 383 - : await getTweetWhere(timeline, { isRetweet: includeRetweets }); 384 - } 385 - 386 - export interface TweetResultByRestId { 387 - data?: TimelineEntryItemContentRaw; 388 - } 389 - 390 - export async function getTweet( 391 - id: string, 392 - auth: TwitterAuth, 393 - ): Promise<Tweet | null> { 394 - const tweetDetailRequest = apiRequestFactory.createTweetDetailRequest(); 395 - tweetDetailRequest.variables.focalTweetId = id; 396 - 397 - // Use bearerToken2 for this specific endpoint (TweetDetail) 398 - // This is required for animated GIFs to appear in tweets with mixed media 399 - const res = await requestApi<ThreadedConversation>( 400 - tweetDetailRequest.toRequestUrl(), 401 - auth, 402 - 'GET', 403 - undefined, 404 - undefined, 405 - bearerToken2, 406 - ); 407 - 408 - if (!res.success) { 409 - throw res.err; 410 - } 411 - 412 - if (!res.value) { 413 - return null; 414 - } 415 - 416 - const tweets = parseThreadedConversation(res.value); 417 - return tweets.find((tweet) => tweet.id === id) ?? null; 418 - } 419 - 420 - export async function getTweetAnonymous( 421 - id: string, 422 - auth: TwitterAuth, 423 - ): Promise<Tweet | null> { 424 - const tweetResultByRestIdRequest = 425 - apiRequestFactory.createTweetResultByRestIdRequest(); 426 - tweetResultByRestIdRequest.variables.tweetId = id; 427 - 428 - // Use bearerToken2 for this specific endpoint (TweetResultByRestId) 429 - // This matches the behavior observed in the Twitter web client and Go library 430 - // We pass it as an override to avoid mutating shared state (concurrency-safe) 431 - const res = await requestApi<TweetResultByRestId>( 432 - tweetResultByRestIdRequest.toRequestUrl(), 433 - auth, 434 - 'GET', 435 - undefined, 436 - undefined, 437 - bearerToken2, 438 - ); 439 - 440 - if (!res.success) { 441 - throw res.err; 442 - } 443 - 444 - if (!res.value.data) { 445 - return null; 446 - } 447 - 448 - return parseTimelineEntryItemContentRaw(res.value.data, id); 449 - }
-13
twitter-scraper/src/type-util.ts
··· 1 - export type NonNullableField<T, K extends keyof T> = { 2 - [P in K]-?: T[P]; 3 - } & T; 4 - 5 - export function isFieldDefined<T, K extends keyof T>(key: K) { 6 - return function (value: T): value is NonNullableField<T, K> { 7 - return isDefined(value[key]); 8 - }; 9 - } 10 - 11 - export function isDefined<T>(value: T | null | undefined): value is T { 12 - return value != null; 13 - }
-176
twitter-scraper/src/xctxid.ts
··· 1 - import fetch from 'cross-fetch'; 2 - import debug from 'debug'; 3 - 4 - const log = debug('twitter-scraper:xctxid'); 5 - 6 - // @ts-expect-error import type annotation ("the current file is a CommonJS module") 7 - type LinkeDOM = typeof import('linkedom'); 8 - 9 - let linkedom: LinkeDOM | null = null; 10 - async function linkedomImport(): Promise<LinkeDOM> { 11 - if (!linkedom) { 12 - const mod = await import('linkedom'); 13 - linkedom = mod; 14 - return mod; 15 - } 16 - return linkedom; 17 - } 18 - 19 - async function parseHTML(html: string): Promise<Window & typeof globalThis> { 20 - if (typeof window !== 'undefined') { 21 - const { defaultView } = new DOMParser().parseFromString(html, 'text/html'); 22 - if (!defaultView) { 23 - throw new Error('Failed to get defaultView from parsed HTML.'); 24 - } 25 - return defaultView; 26 - } else { 27 - const { DOMParser } = await linkedomImport(); 28 - return new DOMParser().parseFromString(html, 'text/html').defaultView; 29 - } 30 - } 31 - 32 - // Copied from https://github.com/Lqm1/x-client-transaction-id/blob/main/utils.ts with minor tweaks to support us passing a custom fetch function 33 - async function handleXMigration(fetchFn: typeof fetch): Promise<Document> { 34 - // Set headers to mimic a browser request 35 - const headers = { 36 - accept: 37 - 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', 38 - 'accept-language': 'ja', 39 - 'cache-control': 'no-cache', 40 - pragma: 'no-cache', 41 - priority: 'u=0, i', 42 - 'sec-ch-ua': 43 - '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"', 44 - 'sec-ch-ua-mobile': '?0', 45 - 'sec-ch-ua-platform': '"Windows"', 46 - 'sec-fetch-dest': 'document', 47 - 'sec-fetch-mode': 'navigate', 48 - 'sec-fetch-site': 'none', 49 - 'sec-fetch-user': '?1', 50 - 'upgrade-insecure-requests': '1', 51 - 'user-agent': 52 - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36', 53 - }; 54 - 55 - // Fetch X.com homepage 56 - const response = await fetchFn('https://x.com', { 57 - headers, 58 - }); 59 - 60 - if (!response.ok) { 61 - throw new Error(`Failed to fetch X homepage: ${response.statusText}`); 62 - } 63 - 64 - const htmlText = await response.text(); 65 - 66 - // Parse HTML using linkedom 67 - let dom = await parseHTML(htmlText); 68 - let document = dom.window.document; 69 - 70 - // Check for migration redirection links 71 - const migrationRedirectionRegex = new RegExp( 72 - '(http(?:s)?://(?:www\\.)?(twitter|x){1}\\.com(/x)?/migrate([/?])?tok=[a-zA-Z0-9%\\-_]+)+', 73 - 'i', 74 - ); 75 - 76 - const metaRefresh = document.querySelector("meta[http-equiv='refresh']"); 77 - const metaContent = metaRefresh 78 - ? metaRefresh.getAttribute('content') || '' 79 - : ''; 80 - 81 - const migrationRedirectionUrl = 82 - migrationRedirectionRegex.exec(metaContent) || 83 - migrationRedirectionRegex.exec(htmlText); 84 - 85 - if (migrationRedirectionUrl) { 86 - // Follow redirection URL 87 - const redirectResponse = await fetch(migrationRedirectionUrl[0]); 88 - 89 - if (!redirectResponse.ok) { 90 - throw new Error( 91 - `Failed to follow migration redirection: ${redirectResponse.statusText}`, 92 - ); 93 - } 94 - 95 - const redirectHtml = await redirectResponse.text(); 96 - dom = await parseHTML(redirectHtml); 97 - document = dom.window.document; 98 - } 99 - 100 - // Handle migration form if present 101 - const migrationForm = 102 - document.querySelector("form[name='f']") || 103 - document.querySelector("form[action='https://x.com/x/migrate']"); 104 - 105 - if (migrationForm) { 106 - const url = 107 - migrationForm.getAttribute('action') || 'https://x.com/x/migrate'; 108 - const method = migrationForm.getAttribute('method') || 'POST'; 109 - 110 - // Collect form input fields 111 - const requestPayload = new FormData(); 112 - 113 - const inputFields = migrationForm.querySelectorAll('input'); 114 - for (const element of Array.from(inputFields)) { 115 - const name = element.getAttribute('name'); 116 - const value = element.getAttribute('value'); 117 - if (name && value) { 118 - requestPayload.append(name, value); 119 - } 120 - } 121 - 122 - // Submit form using POST request 123 - const formResponse = await fetch(url, { 124 - method: method, 125 - body: requestPayload, 126 - headers, 127 - }); 128 - 129 - if (!formResponse.ok) { 130 - throw new Error( 131 - `Failed to submit migration form: ${formResponse.statusText}`, 132 - ); 133 - } 134 - 135 - const formHtml = await formResponse.text(); 136 - dom = await parseHTML(formHtml); 137 - document = dom.window.document; 138 - } 139 - 140 - // Return final DOM document 141 - return document; 142 - } 143 - 144 - let ClientTransaction: 145 - | typeof import('x-client-transaction-id')['ClientTransaction'] 146 - | null = null; 147 - async function clientTransaction(): Promise< 148 - typeof import('x-client-transaction-id')['ClientTransaction'] 149 - > { 150 - if (!ClientTransaction) { 151 - const mod = await import('x-client-transaction-id'); 152 - // eslint-disable-next-line @typescript-eslint/no-explicit-any 153 - ClientTransaction = mod.ClientTransaction as any; 154 - // eslint-disable-next-line @typescript-eslint/no-explicit-any 155 - return mod.ClientTransaction as any; 156 - } 157 - return ClientTransaction; 158 - } 159 - 160 - export async function generateTransactionId( 161 - url: string, 162 - fetchFn: typeof fetch, 163 - method: 'GET' | 'POST', 164 - ) { 165 - const parsedUrl = new URL(url); 166 - const path = parsedUrl.pathname; 167 - 168 - log(`Generating transaction ID for ${method} ${path}`); 169 - const document = await handleXMigration(fetchFn); 170 - const ClientTransactionClass = await clientTransaction(); 171 - const transaction = await ClientTransactionClass.create(document); 172 - const transactionId = await transaction.generateTransactionId(method, path); 173 - log(`Transaction ID: ${transactionId}`); 174 - 175 - return transactionId; 176 - }
-103
twitter-scraper/src/xpff.ts
··· 1 - import debug from 'debug'; 2 - 3 - const log = debug('twitter-scraper:xpff'); 4 - 5 - let isoCrypto: Crypto | null = null; 6 - 7 - async function getCrypto(): Promise<Crypto> { 8 - if (isoCrypto != null) { 9 - return isoCrypto; 10 - } 11 - 12 - // In Node.js, the global `crypto` object is only available from v19.0.0 onwards. 13 - // For earlier versions, we need to import the 'crypto' module. 14 - if (typeof crypto === 'undefined') { 15 - log('Global crypto is undefined, importing from crypto module...'); 16 - const { webcrypto } = await import('crypto'); 17 - // eslint-disable-next-line @typescript-eslint/no-explicit-any 18 - isoCrypto = webcrypto as any; 19 - // eslint-disable-next-line @typescript-eslint/no-explicit-any 20 - return webcrypto as any; 21 - } 22 - isoCrypto = crypto; 23 - return crypto; 24 - } 25 - 26 - async function sha256(message: string): Promise<Uint8Array> { 27 - const msgBuffer = new TextEncoder().encode(message); 28 - const crypto = await getCrypto(); 29 - const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer); 30 - return new Uint8Array(hashBuffer); 31 - } 32 - 33 - // https://stackoverflow.com/a/40031979 34 - function buf2hex(buffer: ArrayBuffer): string { 35 - return [...new Uint8Array(buffer)] 36 - .map((x) => x.toString(16).padStart(2, '0')) 37 - .join(''); 38 - } 39 - 40 - // Adapted from https://github.com/dsekz/twitter-x-xp-forwarded-for-header 41 - export class XPFFHeaderGenerator { 42 - constructor(private readonly seed: string) {} 43 - 44 - private async deriveKey(guestId: string): Promise<Uint8Array> { 45 - const combined = `${this.seed}${guestId}`; 46 - const result = await sha256(combined); 47 - return result; 48 - } 49 - 50 - async generateHeader(plaintext: string, guestId: string): Promise<string> { 51 - log(`Generating XPFF key for guest ID: ${guestId}`); 52 - const key = await this.deriveKey(guestId); 53 - const crypto = await getCrypto(); 54 - const nonce = crypto.getRandomValues(new Uint8Array(12)); 55 - const cipher = await crypto.subtle.importKey( 56 - 'raw', 57 - key as BufferSource, 58 - { name: 'AES-GCM' }, 59 - false, 60 - ['encrypt'], 61 - ); 62 - const encrypted = await crypto.subtle.encrypt( 63 - { 64 - name: 'AES-GCM', 65 - iv: nonce, 66 - }, 67 - cipher, 68 - new TextEncoder().encode(plaintext), 69 - ); 70 - 71 - // Combine nonce and encrypted data 72 - const combined = new Uint8Array(nonce.length + encrypted.byteLength); 73 - combined.set(nonce); 74 - combined.set(new Uint8Array(encrypted), nonce.length); 75 - const result = buf2hex(combined.buffer); 76 - 77 - log(`XPFF header generated for guest ID ${guestId}: ${result}`); 78 - 79 - return result; 80 - } 81 - } 82 - 83 - const xpffBaseKey = 84 - '0e6be1f1e21ffc33590b888fd4dc81b19713e570e805d4e5df80a493c9571a05'; 85 - 86 - function xpffPlain(): string { 87 - const timestamp = Date.now(); 88 - return JSON.stringify({ 89 - navigator_properties: { 90 - hasBeenActive: 'true', 91 - userAgent: 92 - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36', 93 - webdriver: 'false', 94 - }, 95 - created_at: timestamp, 96 - }); 97 - } 98 - 99 - export async function generateXPFFHeader(guestId: string): Promise<string> { 100 - const generator = new XPFFHeaderGenerator(xpffBaseKey); 101 - const plaintext = xpffPlain(); 102 - return generator.generateHeader(plaintext, guestId); 103 - }
-1
twitter-scraper/test-setup.js
··· 1 - globalThis.PLATFORM_NODE = true;
-22
twitter-scraper/tsconfig.json
··· 1 - { 2 - "extends": "@tsconfig/node16/tsconfig.json", 3 - "exclude": ["node_modules", "dist", "examples", "**/*.test.ts", "src/test-utils.ts"], 4 - "compilerOptions": { 5 - // TODO: Remove "dom" from this when support for Node 16 is dropped 6 - "lib": ["es2021", "dom"], 7 - "outDir": "./dist", 8 - "rootDir": "./src", 9 - "sourceMap": true, 10 - "declaration": true, 11 - "declarationMap": true, 12 - "declarationDir": "./dist", 13 - "strict": true, 14 - "noImplicitAny": true, 15 - "esModuleInterop": true, 16 - "forceConsistentCasingInFileNames": true, 17 - "skipLibCheck": true, 18 - "stripInternal": true, 19 - "isolatedModules": true, 20 - "types": ["jest"] 21 - } 22 - }
-6
twitter-scraper/typedoc.json
··· 1 - { 2 - "entryPointStrategy": "expand", 3 - "entryPoints": ["src/_module.ts"], 4 - "exclude": ["**/*.test.ts"], 5 - "hideGenerator": true 6 - }
-5223
twitter-scraper/yarn.lock
··· 1 - # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 - # yarn lockfile v1 3 - 4 - 5 - "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.24.2", "@babel/code-frame@^7.27.1": 6 - version "7.27.1" 7 - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz" 8 - integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== 9 - dependencies: 10 - "@babel/helper-validator-identifier" "^7.27.1" 11 - js-tokens "^4.0.0" 12 - picocolors "^1.1.1" 13 - 14 - "@babel/compat-data@^7.27.2": 15 - version "7.28.4" 16 - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz" 17 - integrity sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw== 18 - 19 - "@babel/core@^7.0.0", "@babel/core@^7.0.0 || ^8.0.0-0", "@babel/core@^7.0.0-0", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9", "@babel/core@^7.8.0", "@babel/core@>=7.0.0-beta.0 <8": 20 - version "7.28.4" 21 - resolved "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz" 22 - integrity sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA== 23 - dependencies: 24 - "@babel/code-frame" "^7.27.1" 25 - "@babel/generator" "^7.28.3" 26 - "@babel/helper-compilation-targets" "^7.27.2" 27 - "@babel/helper-module-transforms" "^7.28.3" 28 - "@babel/helpers" "^7.28.4" 29 - "@babel/parser" "^7.28.4" 30 - "@babel/template" "^7.27.2" 31 - "@babel/traverse" "^7.28.4" 32 - "@babel/types" "^7.28.4" 33 - "@jridgewell/remapping" "^2.3.5" 34 - convert-source-map "^2.0.0" 35 - debug "^4.1.0" 36 - gensync "^1.0.0-beta.2" 37 - json5 "^2.2.3" 38 - semver "^6.3.1" 39 - 40 - "@babel/generator@^7.28.3", "@babel/generator@^7.7.2": 41 - version "7.28.3" 42 - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz" 43 - integrity sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw== 44 - dependencies: 45 - "@babel/parser" "^7.28.3" 46 - "@babel/types" "^7.28.2" 47 - "@jridgewell/gen-mapping" "^0.3.12" 48 - "@jridgewell/trace-mapping" "^0.3.28" 49 - jsesc "^3.0.2" 50 - 51 - "@babel/helper-compilation-targets@^7.27.2": 52 - version "7.27.2" 53 - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz" 54 - integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ== 55 - dependencies: 56 - "@babel/compat-data" "^7.27.2" 57 - "@babel/helper-validator-option" "^7.27.1" 58 - browserslist "^4.24.0" 59 - lru-cache "^5.1.1" 60 - semver "^6.3.1" 61 - 62 - "@babel/helper-globals@^7.28.0": 63 - version "7.28.0" 64 - resolved "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz" 65 - integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== 66 - 67 - "@babel/helper-module-imports@^7.27.1": 68 - version "7.27.1" 69 - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz" 70 - integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== 71 - dependencies: 72 - "@babel/traverse" "^7.27.1" 73 - "@babel/types" "^7.27.1" 74 - 75 - "@babel/helper-module-transforms@^7.28.3": 76 - version "7.28.3" 77 - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz" 78 - integrity sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw== 79 - dependencies: 80 - "@babel/helper-module-imports" "^7.27.1" 81 - "@babel/helper-validator-identifier" "^7.27.1" 82 - "@babel/traverse" "^7.28.3" 83 - 84 - "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.27.1", "@babel/helper-plugin-utils@^7.8.0": 85 - version "7.27.1" 86 - resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz" 87 - integrity sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw== 88 - 89 - "@babel/helper-string-parser@^7.27.1": 90 - version "7.27.1" 91 - resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz" 92 - integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== 93 - 94 - "@babel/helper-validator-identifier@^7.27.1": 95 - version "7.27.1" 96 - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz" 97 - integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== 98 - 99 - "@babel/helper-validator-option@^7.27.1": 100 - version "7.27.1" 101 - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz" 102 - integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== 103 - 104 - "@babel/helpers@^7.28.4": 105 - version "7.28.4" 106 - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz" 107 - integrity sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w== 108 - dependencies: 109 - "@babel/template" "^7.27.2" 110 - "@babel/types" "^7.28.4" 111 - 112 - "@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.27.2", "@babel/parser@^7.28.3", "@babel/parser@^7.28.4": 113 - version "7.28.4" 114 - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz" 115 - integrity sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg== 116 - dependencies: 117 - "@babel/types" "^7.28.4" 118 - 119 - "@babel/plugin-syntax-async-generators@^7.8.4": 120 - version "7.8.4" 121 - resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" 122 - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== 123 - dependencies: 124 - "@babel/helper-plugin-utils" "^7.8.0" 125 - 126 - "@babel/plugin-syntax-bigint@^7.8.3": 127 - version "7.8.3" 128 - resolved "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz" 129 - integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== 130 - dependencies: 131 - "@babel/helper-plugin-utils" "^7.8.0" 132 - 133 - "@babel/plugin-syntax-class-properties@^7.12.13": 134 - version "7.12.13" 135 - resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" 136 - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== 137 - dependencies: 138 - "@babel/helper-plugin-utils" "^7.12.13" 139 - 140 - "@babel/plugin-syntax-class-static-block@^7.14.5": 141 - version "7.14.5" 142 - resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz" 143 - integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== 144 - dependencies: 145 - "@babel/helper-plugin-utils" "^7.14.5" 146 - 147 - "@babel/plugin-syntax-import-attributes@^7.24.7": 148 - version "7.27.1" 149 - resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz" 150 - integrity sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww== 151 - dependencies: 152 - "@babel/helper-plugin-utils" "^7.27.1" 153 - 154 - "@babel/plugin-syntax-import-meta@^7.10.4": 155 - version "7.10.4" 156 - resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz" 157 - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== 158 - dependencies: 159 - "@babel/helper-plugin-utils" "^7.10.4" 160 - 161 - "@babel/plugin-syntax-json-strings@^7.8.3": 162 - version "7.8.3" 163 - resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" 164 - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== 165 - dependencies: 166 - "@babel/helper-plugin-utils" "^7.8.0" 167 - 168 - "@babel/plugin-syntax-jsx@^7.7.2": 169 - version "7.27.1" 170 - resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz" 171 - integrity sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w== 172 - dependencies: 173 - "@babel/helper-plugin-utils" "^7.27.1" 174 - 175 - "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": 176 - version "7.10.4" 177 - resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" 178 - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== 179 - dependencies: 180 - "@babel/helper-plugin-utils" "^7.10.4" 181 - 182 - "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": 183 - version "7.8.3" 184 - resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" 185 - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== 186 - dependencies: 187 - "@babel/helper-plugin-utils" "^7.8.0" 188 - 189 - "@babel/plugin-syntax-numeric-separator@^7.10.4": 190 - version "7.10.4" 191 - resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" 192 - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== 193 - dependencies: 194 - "@babel/helper-plugin-utils" "^7.10.4" 195 - 196 - "@babel/plugin-syntax-object-rest-spread@^7.8.3": 197 - version "7.8.3" 198 - resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" 199 - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== 200 - dependencies: 201 - "@babel/helper-plugin-utils" "^7.8.0" 202 - 203 - "@babel/plugin-syntax-optional-catch-binding@^7.8.3": 204 - version "7.8.3" 205 - resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" 206 - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== 207 - dependencies: 208 - "@babel/helper-plugin-utils" "^7.8.0" 209 - 210 - "@babel/plugin-syntax-optional-chaining@^7.8.3": 211 - version "7.8.3" 212 - resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" 213 - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== 214 - dependencies: 215 - "@babel/helper-plugin-utils" "^7.8.0" 216 - 217 - "@babel/plugin-syntax-private-property-in-object@^7.14.5": 218 - version "7.14.5" 219 - resolved "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz" 220 - integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== 221 - dependencies: 222 - "@babel/helper-plugin-utils" "^7.14.5" 223 - 224 - "@babel/plugin-syntax-top-level-await@^7.14.5": 225 - version "7.14.5" 226 - resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" 227 - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== 228 - dependencies: 229 - "@babel/helper-plugin-utils" "^7.14.5" 230 - 231 - "@babel/plugin-syntax-typescript@^7.7.2": 232 - version "7.27.1" 233 - resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz" 234 - integrity sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ== 235 - dependencies: 236 - "@babel/helper-plugin-utils" "^7.27.1" 237 - 238 - "@babel/template@^7.27.2", "@babel/template@^7.3.3": 239 - version "7.27.2" 240 - resolved "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz" 241 - integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== 242 - dependencies: 243 - "@babel/code-frame" "^7.27.1" 244 - "@babel/parser" "^7.27.2" 245 - "@babel/types" "^7.27.1" 246 - 247 - "@babel/traverse@^7.27.1", "@babel/traverse@^7.28.3", "@babel/traverse@^7.28.4": 248 - version "7.28.4" 249 - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz" 250 - integrity sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ== 251 - dependencies: 252 - "@babel/code-frame" "^7.27.1" 253 - "@babel/generator" "^7.28.3" 254 - "@babel/helper-globals" "^7.28.0" 255 - "@babel/parser" "^7.28.4" 256 - "@babel/template" "^7.27.2" 257 - "@babel/types" "^7.28.4" 258 - debug "^4.3.1" 259 - 260 - "@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.1", "@babel/types@^7.28.2", "@babel/types@^7.28.4", "@babel/types@^7.3.3": 261 - version "7.28.4" 262 - resolved "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz" 263 - integrity sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q== 264 - dependencies: 265 - "@babel/helper-string-parser" "^7.27.1" 266 - "@babel/helper-validator-identifier" "^7.27.1" 267 - 268 - "@bcoe/v8-coverage@^0.2.3": 269 - version "0.2.3" 270 - resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz" 271 - integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== 272 - 273 - "@commitlint/cli@^17.6.3": 274 - version "17.8.1" 275 - resolved "https://registry.npmjs.org/@commitlint/cli/-/cli-17.8.1.tgz" 276 - integrity sha512-ay+WbzQesE0Rv4EQKfNbSMiJJ12KdKTDzIt0tcK4k11FdsWmtwP0Kp1NWMOUswfIWo6Eb7p7Ln721Nx9FLNBjg== 277 - dependencies: 278 - "@commitlint/format" "^17.8.1" 279 - "@commitlint/lint" "^17.8.1" 280 - "@commitlint/load" "^17.8.1" 281 - "@commitlint/read" "^17.8.1" 282 - "@commitlint/types" "^17.8.1" 283 - execa "^5.0.0" 284 - lodash.isfunction "^3.0.9" 285 - resolve-from "5.0.0" 286 - resolve-global "1.0.0" 287 - yargs "^17.0.0" 288 - 289 - "@commitlint/config-conventional@^17.6.3": 290 - version "17.8.1" 291 - resolved "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-17.8.1.tgz" 292 - integrity sha512-NxCOHx1kgneig3VLauWJcDWS40DVjg7nKOpBEEK9E5fjJpQqLCilcnKkIIjdBH98kEO1q3NpE5NSrZ2kl/QGJg== 293 - dependencies: 294 - conventional-changelog-conventionalcommits "^6.1.0" 295 - 296 - "@commitlint/config-validator@^17.8.1": 297 - version "17.8.1" 298 - resolved "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.8.1.tgz" 299 - integrity sha512-UUgUC+sNiiMwkyiuIFR7JG2cfd9t/7MV8VB4TZ+q02ZFkHoduUS4tJGsCBWvBOGD9Btev6IecPMvlWUfJorkEA== 300 - dependencies: 301 - "@commitlint/types" "^17.8.1" 302 - ajv "^8.11.0" 303 - 304 - "@commitlint/ensure@^17.8.1": 305 - version "17.8.1" 306 - resolved "https://registry.npmjs.org/@commitlint/ensure/-/ensure-17.8.1.tgz" 307 - integrity sha512-xjafwKxid8s1K23NFpL8JNo6JnY/ysetKo8kegVM7c8vs+kWLP8VrQq+NbhgVlmCojhEDbzQKp4eRXSjVOGsow== 308 - dependencies: 309 - "@commitlint/types" "^17.8.1" 310 - lodash.camelcase "^4.3.0" 311 - lodash.kebabcase "^4.1.1" 312 - lodash.snakecase "^4.1.1" 313 - lodash.startcase "^4.4.0" 314 - lodash.upperfirst "^4.3.1" 315 - 316 - "@commitlint/execute-rule@^17.8.1": 317 - version "17.8.1" 318 - resolved "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-17.8.1.tgz" 319 - integrity sha512-JHVupQeSdNI6xzA9SqMF+p/JjrHTcrJdI02PwesQIDCIGUrv04hicJgCcws5nzaoZbROapPs0s6zeVHoxpMwFQ== 320 - 321 - "@commitlint/format@^17.8.1": 322 - version "17.8.1" 323 - resolved "https://registry.npmjs.org/@commitlint/format/-/format-17.8.1.tgz" 324 - integrity sha512-f3oMTyZ84M9ht7fb93wbCKmWxO5/kKSbwuYvS867duVomoOsgrgljkGGIztmT/srZnaiGbaK8+Wf8Ik2tSr5eg== 325 - dependencies: 326 - "@commitlint/types" "^17.8.1" 327 - chalk "^4.1.0" 328 - 329 - "@commitlint/is-ignored@^17.8.1": 330 - version "17.8.1" 331 - resolved "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-17.8.1.tgz" 332 - integrity sha512-UshMi4Ltb4ZlNn4F7WtSEugFDZmctzFpmbqvpyxD3la510J+PLcnyhf9chs7EryaRFJMdAKwsEKfNK0jL/QM4g== 333 - dependencies: 334 - "@commitlint/types" "^17.8.1" 335 - semver "7.5.4" 336 - 337 - "@commitlint/lint@^17.8.1": 338 - version "17.8.1" 339 - resolved "https://registry.npmjs.org/@commitlint/lint/-/lint-17.8.1.tgz" 340 - integrity sha512-aQUlwIR1/VMv2D4GXSk7PfL5hIaFSfy6hSHV94O8Y27T5q+DlDEgd/cZ4KmVI+MWKzFfCTiTuWqjfRSfdRllCA== 341 - dependencies: 342 - "@commitlint/is-ignored" "^17.8.1" 343 - "@commitlint/parse" "^17.8.1" 344 - "@commitlint/rules" "^17.8.1" 345 - "@commitlint/types" "^17.8.1" 346 - 347 - "@commitlint/load@^17.8.1", "@commitlint/load@>6.1.1": 348 - version "17.8.1" 349 - resolved "https://registry.npmjs.org/@commitlint/load/-/load-17.8.1.tgz" 350 - integrity sha512-iF4CL7KDFstP1kpVUkT8K2Wl17h2yx9VaR1ztTc8vzByWWcbO/WaKwxsnCOqow9tVAlzPfo1ywk9m2oJ9ucMqA== 351 - dependencies: 352 - "@commitlint/config-validator" "^17.8.1" 353 - "@commitlint/execute-rule" "^17.8.1" 354 - "@commitlint/resolve-extends" "^17.8.1" 355 - "@commitlint/types" "^17.8.1" 356 - "@types/node" "20.5.1" 357 - chalk "^4.1.0" 358 - cosmiconfig "^8.0.0" 359 - cosmiconfig-typescript-loader "^4.0.0" 360 - lodash.isplainobject "^4.0.6" 361 - lodash.merge "^4.6.2" 362 - lodash.uniq "^4.5.0" 363 - resolve-from "^5.0.0" 364 - ts-node "^10.8.1" 365 - typescript "^4.6.4 || ^5.2.2" 366 - 367 - "@commitlint/message@^17.8.1": 368 - version "17.8.1" 369 - resolved "https://registry.npmjs.org/@commitlint/message/-/message-17.8.1.tgz" 370 - integrity sha512-6bYL1GUQsD6bLhTH3QQty8pVFoETfFQlMn2Nzmz3AOLqRVfNNtXBaSY0dhZ0dM6A2MEq4+2d7L/2LP8TjqGRkA== 371 - 372 - "@commitlint/parse@^17.8.1": 373 - version "17.8.1" 374 - resolved "https://registry.npmjs.org/@commitlint/parse/-/parse-17.8.1.tgz" 375 - integrity sha512-/wLUickTo0rNpQgWwLPavTm7WbwkZoBy3X8PpkUmlSmQJyWQTj0m6bDjiykMaDt41qcUbfeFfaCvXfiR4EGnfw== 376 - dependencies: 377 - "@commitlint/types" "^17.8.1" 378 - conventional-changelog-angular "^6.0.0" 379 - conventional-commits-parser "^4.0.0" 380 - 381 - "@commitlint/read@^17.8.1": 382 - version "17.8.1" 383 - resolved "https://registry.npmjs.org/@commitlint/read/-/read-17.8.1.tgz" 384 - integrity sha512-Fd55Oaz9irzBESPCdMd8vWWgxsW3OWR99wOntBDHgf9h7Y6OOHjWEdS9Xzen1GFndqgyoaFplQS5y7KZe0kO2w== 385 - dependencies: 386 - "@commitlint/top-level" "^17.8.1" 387 - "@commitlint/types" "^17.8.1" 388 - fs-extra "^11.0.0" 389 - git-raw-commits "^2.0.11" 390 - minimist "^1.2.6" 391 - 392 - "@commitlint/resolve-extends@^17.8.1": 393 - version "17.8.1" 394 - resolved "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.8.1.tgz" 395 - integrity sha512-W/ryRoQ0TSVXqJrx5SGkaYuAaE/BUontL1j1HsKckvM6e5ZaG0M9126zcwL6peKSuIetJi7E87PRQF8O86EW0Q== 396 - dependencies: 397 - "@commitlint/config-validator" "^17.8.1" 398 - "@commitlint/types" "^17.8.1" 399 - import-fresh "^3.0.0" 400 - lodash.mergewith "^4.6.2" 401 - resolve-from "^5.0.0" 402 - resolve-global "^1.0.0" 403 - 404 - "@commitlint/rules@^17.8.1": 405 - version "17.8.1" 406 - resolved "https://registry.npmjs.org/@commitlint/rules/-/rules-17.8.1.tgz" 407 - integrity sha512-2b7OdVbN7MTAt9U0vKOYKCDsOvESVXxQmrvuVUZ0rGFMCrCPJWWP1GJ7f0lAypbDAhaGb8zqtdOr47192LBrIA== 408 - dependencies: 409 - "@commitlint/ensure" "^17.8.1" 410 - "@commitlint/message" "^17.8.1" 411 - "@commitlint/to-lines" "^17.8.1" 412 - "@commitlint/types" "^17.8.1" 413 - execa "^5.0.0" 414 - 415 - "@commitlint/to-lines@^17.8.1": 416 - version "17.8.1" 417 - resolved "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-17.8.1.tgz" 418 - integrity sha512-LE0jb8CuR/mj6xJyrIk8VLz03OEzXFgLdivBytoooKO5xLt5yalc8Ma5guTWobw998sbR3ogDd+2jed03CFmJA== 419 - 420 - "@commitlint/top-level@^17.8.1": 421 - version "17.8.1" 422 - resolved "https://registry.npmjs.org/@commitlint/top-level/-/top-level-17.8.1.tgz" 423 - integrity sha512-l6+Z6rrNf5p333SHfEte6r+WkOxGlWK4bLuZKbtf/2TXRN+qhrvn1XE63VhD8Oe9oIHQ7F7W1nG2k/TJFhx2yA== 424 - dependencies: 425 - find-up "^5.0.0" 426 - 427 - "@commitlint/types@^17.8.1": 428 - version "17.8.1" 429 - resolved "https://registry.npmjs.org/@commitlint/types/-/types-17.8.1.tgz" 430 - integrity sha512-PXDQXkAmiMEG162Bqdh9ChML/GJZo6vU+7F03ALKDK8zYc6SuAr47LjG7hGYRqUOz+WK0dU7bQ0xzuqFMdxzeQ== 431 - dependencies: 432 - chalk "^4.1.0" 433 - 434 - "@cspotcode/source-map-support@^0.8.0": 435 - version "0.8.1" 436 - resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" 437 - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== 438 - dependencies: 439 - "@jridgewell/trace-mapping" "0.3.9" 440 - 441 - "@esbuild/linux-x64@0.21.5": 442 - version "0.21.5" 443 - resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz" 444 - integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== 445 - 446 - "@eslint-community/eslint-utils@^4.2.0": 447 - version "4.4.0" 448 - resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz" 449 - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== 450 - dependencies: 451 - eslint-visitor-keys "^3.3.0" 452 - 453 - "@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": 454 - version "4.10.1" 455 - resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz" 456 - integrity sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA== 457 - 458 - "@eslint/eslintrc@^2.1.4": 459 - version "2.1.4" 460 - resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz" 461 - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== 462 - dependencies: 463 - ajv "^6.12.4" 464 - debug "^4.3.2" 465 - espree "^9.6.0" 466 - globals "^13.19.0" 467 - ignore "^5.2.0" 468 - import-fresh "^3.2.1" 469 - js-yaml "^4.1.0" 470 - minimatch "^3.1.2" 471 - strip-json-comments "^3.1.1" 472 - 473 - "@eslint/js@8.57.0": 474 - version "8.57.0" 475 - resolved "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz" 476 - integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== 477 - 478 - "@gerrit0/mini-shiki@^1.24.0": 479 - version "1.27.2" 480 - resolved "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-1.27.2.tgz" 481 - integrity sha512-GeWyHz8ao2gBiUW4OJnQDxXQnFgZQwwQk05t/CVVgNBN7/rK8XZ7xY6YhLVv9tH3VppWWmr9DCl3MwemB/i+Og== 482 - dependencies: 483 - "@shikijs/engine-oniguruma" "^1.27.2" 484 - "@shikijs/types" "^1.27.2" 485 - "@shikijs/vscode-textmate" "^10.0.1" 486 - 487 - "@humanwhocodes/config-array@^0.11.14": 488 - version "0.11.14" 489 - resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz" 490 - integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== 491 - dependencies: 492 - "@humanwhocodes/object-schema" "^2.0.2" 493 - debug "^4.3.1" 494 - minimatch "^3.0.5" 495 - 496 - "@humanwhocodes/module-importer@^1.0.1": 497 - version "1.0.1" 498 - resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz" 499 - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== 500 - 501 - "@humanwhocodes/object-schema@^2.0.2": 502 - version "2.0.3" 503 - resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz" 504 - integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== 505 - 506 - "@isaacs/cliui@^8.0.2": 507 - version "8.0.2" 508 - resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz" 509 - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== 510 - dependencies: 511 - string-width "^5.1.2" 512 - string-width-cjs "npm:string-width@^4.2.0" 513 - strip-ansi "^7.0.1" 514 - strip-ansi-cjs "npm:strip-ansi@^6.0.1" 515 - wrap-ansi "^8.1.0" 516 - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" 517 - 518 - "@istanbuljs/load-nyc-config@^1.0.0": 519 - version "1.1.0" 520 - resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz" 521 - integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== 522 - dependencies: 523 - camelcase "^5.3.1" 524 - find-up "^4.1.0" 525 - get-package-type "^0.1.0" 526 - js-yaml "^3.13.1" 527 - resolve-from "^5.0.0" 528 - 529 - "@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": 530 - version "0.1.3" 531 - resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz" 532 - integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== 533 - 534 - "@jest/console@^29.7.0": 535 - version "29.7.0" 536 - resolved "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz" 537 - integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== 538 - dependencies: 539 - "@jest/types" "^29.6.3" 540 - "@types/node" "*" 541 - chalk "^4.0.0" 542 - jest-message-util "^29.7.0" 543 - jest-util "^29.7.0" 544 - slash "^3.0.0" 545 - 546 - "@jest/core@^29.7.0": 547 - version "29.7.0" 548 - resolved "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz" 549 - integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== 550 - dependencies: 551 - "@jest/console" "^29.7.0" 552 - "@jest/reporters" "^29.7.0" 553 - "@jest/test-result" "^29.7.0" 554 - "@jest/transform" "^29.7.0" 555 - "@jest/types" "^29.6.3" 556 - "@types/node" "*" 557 - ansi-escapes "^4.2.1" 558 - chalk "^4.0.0" 559 - ci-info "^3.2.0" 560 - exit "^0.1.2" 561 - graceful-fs "^4.2.9" 562 - jest-changed-files "^29.7.0" 563 - jest-config "^29.7.0" 564 - jest-haste-map "^29.7.0" 565 - jest-message-util "^29.7.0" 566 - jest-regex-util "^29.6.3" 567 - jest-resolve "^29.7.0" 568 - jest-resolve-dependencies "^29.7.0" 569 - jest-runner "^29.7.0" 570 - jest-runtime "^29.7.0" 571 - jest-snapshot "^29.7.0" 572 - jest-util "^29.7.0" 573 - jest-validate "^29.7.0" 574 - jest-watcher "^29.7.0" 575 - micromatch "^4.0.4" 576 - pretty-format "^29.7.0" 577 - slash "^3.0.0" 578 - strip-ansi "^6.0.0" 579 - 580 - "@jest/environment@^29.7.0": 581 - version "29.7.0" 582 - resolved "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz" 583 - integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== 584 - dependencies: 585 - "@jest/fake-timers" "^29.7.0" 586 - "@jest/types" "^29.6.3" 587 - "@types/node" "*" 588 - jest-mock "^29.7.0" 589 - 590 - "@jest/expect-utils@^29.7.0": 591 - version "29.7.0" 592 - resolved "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz" 593 - integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== 594 - dependencies: 595 - jest-get-type "^29.6.3" 596 - 597 - "@jest/expect@^29.7.0": 598 - version "29.7.0" 599 - resolved "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz" 600 - integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== 601 - dependencies: 602 - expect "^29.7.0" 603 - jest-snapshot "^29.7.0" 604 - 605 - "@jest/fake-timers@^29.7.0": 606 - version "29.7.0" 607 - resolved "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz" 608 - integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== 609 - dependencies: 610 - "@jest/types" "^29.6.3" 611 - "@sinonjs/fake-timers" "^10.0.2" 612 - "@types/node" "*" 613 - jest-message-util "^29.7.0" 614 - jest-mock "^29.7.0" 615 - jest-util "^29.7.0" 616 - 617 - "@jest/globals@^29.7.0": 618 - version "29.7.0" 619 - resolved "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz" 620 - integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== 621 - dependencies: 622 - "@jest/environment" "^29.7.0" 623 - "@jest/expect" "^29.7.0" 624 - "@jest/types" "^29.6.3" 625 - jest-mock "^29.7.0" 626 - 627 - "@jest/reporters@^29.7.0": 628 - version "29.7.0" 629 - resolved "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz" 630 - integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== 631 - dependencies: 632 - "@bcoe/v8-coverage" "^0.2.3" 633 - "@jest/console" "^29.7.0" 634 - "@jest/test-result" "^29.7.0" 635 - "@jest/transform" "^29.7.0" 636 - "@jest/types" "^29.6.3" 637 - "@jridgewell/trace-mapping" "^0.3.18" 638 - "@types/node" "*" 639 - chalk "^4.0.0" 640 - collect-v8-coverage "^1.0.0" 641 - exit "^0.1.2" 642 - glob "^7.1.3" 643 - graceful-fs "^4.2.9" 644 - istanbul-lib-coverage "^3.0.0" 645 - istanbul-lib-instrument "^6.0.0" 646 - istanbul-lib-report "^3.0.0" 647 - istanbul-lib-source-maps "^4.0.0" 648 - istanbul-reports "^3.1.3" 649 - jest-message-util "^29.7.0" 650 - jest-util "^29.7.0" 651 - jest-worker "^29.7.0" 652 - slash "^3.0.0" 653 - string-length "^4.0.1" 654 - strip-ansi "^6.0.0" 655 - v8-to-istanbul "^9.0.1" 656 - 657 - "@jest/schemas@^29.6.3": 658 - version "29.6.3" 659 - resolved "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz" 660 - integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== 661 - dependencies: 662 - "@sinclair/typebox" "^0.27.8" 663 - 664 - "@jest/source-map@^29.6.3": 665 - version "29.6.3" 666 - resolved "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz" 667 - integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== 668 - dependencies: 669 - "@jridgewell/trace-mapping" "^0.3.18" 670 - callsites "^3.0.0" 671 - graceful-fs "^4.2.9" 672 - 673 - "@jest/test-result@^29.7.0": 674 - version "29.7.0" 675 - resolved "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz" 676 - integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== 677 - dependencies: 678 - "@jest/console" "^29.7.0" 679 - "@jest/types" "^29.6.3" 680 - "@types/istanbul-lib-coverage" "^2.0.0" 681 - collect-v8-coverage "^1.0.0" 682 - 683 - "@jest/test-sequencer@^29.7.0": 684 - version "29.7.0" 685 - resolved "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz" 686 - integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== 687 - dependencies: 688 - "@jest/test-result" "^29.7.0" 689 - graceful-fs "^4.2.9" 690 - jest-haste-map "^29.7.0" 691 - slash "^3.0.0" 692 - 693 - "@jest/transform@^29.0.0", "@jest/transform@^29.7.0": 694 - version "29.7.0" 695 - resolved "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz" 696 - integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== 697 - dependencies: 698 - "@babel/core" "^7.11.6" 699 - "@jest/types" "^29.6.3" 700 - "@jridgewell/trace-mapping" "^0.3.18" 701 - babel-plugin-istanbul "^6.1.1" 702 - chalk "^4.0.0" 703 - convert-source-map "^2.0.0" 704 - fast-json-stable-stringify "^2.1.0" 705 - graceful-fs "^4.2.9" 706 - jest-haste-map "^29.7.0" 707 - jest-regex-util "^29.6.3" 708 - jest-util "^29.7.0" 709 - micromatch "^4.0.4" 710 - pirates "^4.0.4" 711 - slash "^3.0.0" 712 - write-file-atomic "^4.0.2" 713 - 714 - "@jest/types@^29.0.0", "@jest/types@^29.6.3": 715 - version "29.6.3" 716 - resolved "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz" 717 - integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== 718 - dependencies: 719 - "@jest/schemas" "^29.6.3" 720 - "@types/istanbul-lib-coverage" "^2.0.0" 721 - "@types/istanbul-reports" "^3.0.0" 722 - "@types/node" "*" 723 - "@types/yargs" "^17.0.8" 724 - chalk "^4.0.0" 725 - 726 - "@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5": 727 - version "0.3.13" 728 - resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz" 729 - integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== 730 - dependencies: 731 - "@jridgewell/sourcemap-codec" "^1.5.0" 732 - "@jridgewell/trace-mapping" "^0.3.24" 733 - 734 - "@jridgewell/remapping@^2.3.5": 735 - version "2.3.5" 736 - resolved "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz" 737 - integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== 738 - dependencies: 739 - "@jridgewell/gen-mapping" "^0.3.5" 740 - "@jridgewell/trace-mapping" "^0.3.24" 741 - 742 - "@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": 743 - version "3.1.2" 744 - resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" 745 - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== 746 - 747 - "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15", "@jridgewell/sourcemap-codec@^1.5.0": 748 - version "1.5.5" 749 - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz" 750 - integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== 751 - 752 - "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.28": 753 - version "0.3.31" 754 - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz" 755 - integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== 756 - dependencies: 757 - "@jridgewell/resolve-uri" "^3.1.0" 758 - "@jridgewell/sourcemap-codec" "^1.4.14" 759 - 760 - "@jridgewell/trace-mapping@0.3.9": 761 - version "0.3.9" 762 - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" 763 - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== 764 - dependencies: 765 - "@jridgewell/resolve-uri" "^3.0.3" 766 - "@jridgewell/sourcemap-codec" "^1.4.10" 767 - 768 - "@noble/hashes@1.4.0": 769 - version "1.4.0" 770 - resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz" 771 - integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== 772 - 773 - "@nodelib/fs.scandir@2.1.5": 774 - version "2.1.5" 775 - resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" 776 - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== 777 - dependencies: 778 - "@nodelib/fs.stat" "2.0.5" 779 - run-parallel "^1.1.9" 780 - 781 - "@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": 782 - version "2.0.5" 783 - resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" 784 - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== 785 - 786 - "@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": 787 - version "1.2.8" 788 - resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" 789 - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== 790 - dependencies: 791 - "@nodelib/fs.scandir" "2.1.5" 792 - fastq "^1.6.0" 793 - 794 - "@pkgjs/parseargs@^0.11.0": 795 - version "0.11.0" 796 - resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz" 797 - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== 798 - 799 - "@rollup/pluginutils@^5.0.5": 800 - version "5.1.0" 801 - resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz" 802 - integrity sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g== 803 - dependencies: 804 - "@types/estree" "^1.0.0" 805 - estree-walker "^2.0.2" 806 - picomatch "^2.3.1" 807 - 808 - "@rollup/rollup-linux-x64-gnu@4.18.0": 809 - version "4.18.0" 810 - resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz" 811 - integrity sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w== 812 - 813 - "@shikijs/engine-oniguruma@^1.27.2": 814 - version "1.27.2" 815 - resolved "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.27.2.tgz" 816 - integrity sha512-FZYKD1KN7srvpkz4lbGLOYWlyDU4Rd+2RtuKfABTkafAPOFr+J6umfIwY/TzOQqfNtWjL7SAwPAO0dcOraRLaQ== 817 - dependencies: 818 - "@shikijs/types" "1.27.2" 819 - "@shikijs/vscode-textmate" "^10.0.1" 820 - 821 - "@shikijs/types@^1.27.2", "@shikijs/types@1.27.2": 822 - version "1.27.2" 823 - resolved "https://registry.npmjs.org/@shikijs/types/-/types-1.27.2.tgz" 824 - integrity sha512-DM9OWUyjmdYdnKDpaGB/GEn9XkToyK1tqxuqbmc5PV+5K8WjjwfygL3+cIvbkSw2v1ySwHDgqATq/+98pJ4Kyg== 825 - dependencies: 826 - "@shikijs/vscode-textmate" "^10.0.1" 827 - "@types/hast" "^3.0.4" 828 - 829 - "@shikijs/vscode-textmate@^10.0.1": 830 - version "10.0.1" 831 - resolved "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.1.tgz" 832 - integrity sha512-fTIQwLF+Qhuws31iw7Ncl1R3HUDtGwIipiJ9iU+UsDUwMhegFcQKQHd51nZjb7CArq0MvON8rbgCGQYWHUKAdg== 833 - 834 - "@sinclair/typebox@^0.27.8": 835 - version "0.27.8" 836 - resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz" 837 - integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== 838 - 839 - "@sinclair/typebox@^0.32.20": 840 - version "0.32.32" 841 - resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.32.32.tgz" 842 - integrity sha512-m+A3zFSI87TCtoz6vQCSnd+t/kDKL78JmzhKYkON+7SnHSa+794qraIVpm6ozFGK+5svnVOt1LJ7BUEhGkIvgg== 843 - 844 - "@sinonjs/commons@^3.0.0": 845 - version "3.0.1" 846 - resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz" 847 - integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== 848 - dependencies: 849 - type-detect "4.0.8" 850 - 851 - "@sinonjs/fake-timers@^10.0.2": 852 - version "10.3.0" 853 - resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz" 854 - integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== 855 - dependencies: 856 - "@sinonjs/commons" "^3.0.0" 857 - 858 - "@tsconfig/node10@^1.0.7": 859 - version "1.0.11" 860 - resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz" 861 - integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== 862 - 863 - "@tsconfig/node12@^1.0.7": 864 - version "1.0.11" 865 - resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz" 866 - integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== 867 - 868 - "@tsconfig/node14@^1.0.0": 869 - version "1.0.3" 870 - resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz" 871 - integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== 872 - 873 - "@tsconfig/node16@^1.0.2": 874 - version "1.0.4" 875 - resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz" 876 - integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== 877 - 878 - "@tsconfig/node16@^16.1.0": 879 - version "16.1.3" 880 - resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-16.1.3.tgz" 881 - integrity sha512-9nTOUBn+EMKO6rtSZJk+DcqsfgtlERGT9XPJ5PRj/HNENPCBY1yu/JEj5wT6GLtbCLBO2k46SeXDaY0pjMqypw== 882 - 883 - "@types/babel__core@^7.1.14": 884 - version "7.20.5" 885 - resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz" 886 - integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== 887 - dependencies: 888 - "@babel/parser" "^7.20.7" 889 - "@babel/types" "^7.20.7" 890 - "@types/babel__generator" "*" 891 - "@types/babel__template" "*" 892 - "@types/babel__traverse" "*" 893 - 894 - "@types/babel__generator@*": 895 - version "7.6.8" 896 - resolved "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz" 897 - integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== 898 - dependencies: 899 - "@babel/types" "^7.0.0" 900 - 901 - "@types/babel__template@*": 902 - version "7.4.4" 903 - resolved "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz" 904 - integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== 905 - dependencies: 906 - "@babel/parser" "^7.1.0" 907 - "@babel/types" "^7.0.0" 908 - 909 - "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": 910 - version "7.20.6" 911 - resolved "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz" 912 - integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== 913 - dependencies: 914 - "@babel/types" "^7.20.7" 915 - 916 - "@types/debug@^4.1.12": 917 - version "4.1.12" 918 - resolved "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz" 919 - integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== 920 - dependencies: 921 - "@types/ms" "*" 922 - 923 - "@types/estree@^1.0.0", "@types/estree@1.0.5": 924 - version "1.0.5" 925 - resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz" 926 - integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== 927 - 928 - "@types/graceful-fs@^4.1.3": 929 - version "4.1.9" 930 - resolved "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz" 931 - integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== 932 - dependencies: 933 - "@types/node" "*" 934 - 935 - "@types/hast@^3.0.4": 936 - version "3.0.4" 937 - resolved "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz" 938 - integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ== 939 - dependencies: 940 - "@types/unist" "*" 941 - 942 - "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": 943 - version "2.0.6" 944 - resolved "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz" 945 - integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== 946 - 947 - "@types/istanbul-lib-report@*": 948 - version "3.0.3" 949 - resolved "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz" 950 - integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== 951 - dependencies: 952 - "@types/istanbul-lib-coverage" "*" 953 - 954 - "@types/istanbul-reports@^3.0.0": 955 - version "3.0.4" 956 - resolved "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz" 957 - integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== 958 - dependencies: 959 - "@types/istanbul-lib-report" "*" 960 - 961 - "@types/jest@^29.5.1": 962 - version "29.5.12" 963 - resolved "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz" 964 - integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw== 965 - dependencies: 966 - expect "^29.0.0" 967 - pretty-format "^29.0.0" 968 - 969 - "@types/json-schema@^7.0.9": 970 - version "7.0.15" 971 - resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz" 972 - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== 973 - 974 - "@types/json-stable-stringify@^1.0.34": 975 - version "1.0.36" 976 - resolved "https://registry.npmjs.org/@types/json-stable-stringify/-/json-stable-stringify-1.0.36.tgz" 977 - integrity sha512-b7bq23s4fgBB76n34m2b3RBf6M369B0Z9uRR8aHTMd8kZISRkmDEpPD8hhpYvDFzr3bJCPES96cm3Q6qRNDbQw== 978 - 979 - "@types/minimist@^1.2.0": 980 - version "1.2.5" 981 - resolved "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz" 982 - integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== 983 - 984 - "@types/ms@*": 985 - version "2.1.0" 986 - resolved "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz" 987 - integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== 988 - 989 - "@types/node@*", "@types/node@20.5.1": 990 - version "20.5.1" 991 - resolved "https://registry.npmjs.org/@types/node/-/node-20.5.1.tgz" 992 - integrity sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg== 993 - 994 - "@types/node@^20.14.0": 995 - version "20.19.18" 996 - resolved "https://registry.npmjs.org/@types/node/-/node-20.19.18.tgz" 997 - integrity sha512-KeYVbfnbsBCyKG8e3gmUqAfyZNcoj/qpEbHRkQkfZdKOBrU7QQ+BsTdfqLSWX9/m1ytYreMhpKvp+EZi3UFYAg== 998 - dependencies: 999 - undici-types "~6.21.0" 1000 - 1001 - "@types/normalize-package-data@^2.4.0": 1002 - version "2.4.4" 1003 - resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz" 1004 - integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== 1005 - 1006 - "@types/semver@^7.3.12": 1007 - version "7.5.8" 1008 - resolved "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz" 1009 - integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== 1010 - 1011 - "@types/set-cookie-parser@^2.4.2": 1012 - version "2.4.9" 1013 - resolved "https://registry.npmjs.org/@types/set-cookie-parser/-/set-cookie-parser-2.4.9.tgz" 1014 - integrity sha512-bCorlULvl0xTdjj4BPUHX4cqs9I+go2TfW/7Do1nnFYWS0CPP429Qr1AY42kiFhCwLpvAkWFr1XIBHd8j6/MCQ== 1015 - dependencies: 1016 - "@types/node" "*" 1017 - 1018 - "@types/stack-utils@^2.0.0": 1019 - version "2.0.3" 1020 - resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz" 1021 - integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== 1022 - 1023 - "@types/tough-cookie@^4.0.2": 1024 - version "4.0.5" 1025 - resolved "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz" 1026 - integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== 1027 - 1028 - "@types/unist@*": 1029 - version "3.0.3" 1030 - resolved "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz" 1031 - integrity sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q== 1032 - 1033 - "@types/yargs-parser@*": 1034 - version "21.0.3" 1035 - resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz" 1036 - integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== 1037 - 1038 - "@types/yargs@^17.0.8": 1039 - version "17.0.32" 1040 - resolved "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz" 1041 - integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== 1042 - dependencies: 1043 - "@types/yargs-parser" "*" 1044 - 1045 - "@typescript-eslint/eslint-plugin@^5.59.7": 1046 - version "5.62.0" 1047 - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz" 1048 - integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag== 1049 - dependencies: 1050 - "@eslint-community/regexpp" "^4.4.0" 1051 - "@typescript-eslint/scope-manager" "5.62.0" 1052 - "@typescript-eslint/type-utils" "5.62.0" 1053 - "@typescript-eslint/utils" "5.62.0" 1054 - debug "^4.3.4" 1055 - graphemer "^1.4.0" 1056 - ignore "^5.2.0" 1057 - natural-compare-lite "^1.4.0" 1058 - semver "^7.3.7" 1059 - tsutils "^3.21.0" 1060 - 1061 - "@typescript-eslint/parser@^5.0.0", "@typescript-eslint/parser@^5.59.7": 1062 - version "5.62.0" 1063 - resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz" 1064 - integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA== 1065 - dependencies: 1066 - "@typescript-eslint/scope-manager" "5.62.0" 1067 - "@typescript-eslint/types" "5.62.0" 1068 - "@typescript-eslint/typescript-estree" "5.62.0" 1069 - debug "^4.3.4" 1070 - 1071 - "@typescript-eslint/scope-manager@5.62.0": 1072 - version "5.62.0" 1073 - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz" 1074 - integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== 1075 - dependencies: 1076 - "@typescript-eslint/types" "5.62.0" 1077 - "@typescript-eslint/visitor-keys" "5.62.0" 1078 - 1079 - "@typescript-eslint/type-utils@5.62.0": 1080 - version "5.62.0" 1081 - resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz" 1082 - integrity sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew== 1083 - dependencies: 1084 - "@typescript-eslint/typescript-estree" "5.62.0" 1085 - "@typescript-eslint/utils" "5.62.0" 1086 - debug "^4.3.4" 1087 - tsutils "^3.21.0" 1088 - 1089 - "@typescript-eslint/types@5.62.0": 1090 - version "5.62.0" 1091 - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz" 1092 - integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== 1093 - 1094 - "@typescript-eslint/typescript-estree@5.62.0": 1095 - version "5.62.0" 1096 - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz" 1097 - integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== 1098 - dependencies: 1099 - "@typescript-eslint/types" "5.62.0" 1100 - "@typescript-eslint/visitor-keys" "5.62.0" 1101 - debug "^4.3.4" 1102 - globby "^11.1.0" 1103 - is-glob "^4.0.3" 1104 - semver "^7.3.7" 1105 - tsutils "^3.21.0" 1106 - 1107 - "@typescript-eslint/utils@5.62.0": 1108 - version "5.62.0" 1109 - resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz" 1110 - integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== 1111 - dependencies: 1112 - "@eslint-community/eslint-utils" "^4.2.0" 1113 - "@types/json-schema" "^7.0.9" 1114 - "@types/semver" "^7.3.12" 1115 - "@typescript-eslint/scope-manager" "5.62.0" 1116 - "@typescript-eslint/types" "5.62.0" 1117 - "@typescript-eslint/typescript-estree" "5.62.0" 1118 - eslint-scope "^5.1.1" 1119 - semver "^7.3.7" 1120 - 1121 - "@typescript-eslint/visitor-keys@5.62.0": 1122 - version "5.62.0" 1123 - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz" 1124 - integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== 1125 - dependencies: 1126 - "@typescript-eslint/types" "5.62.0" 1127 - eslint-visitor-keys "^3.3.0" 1128 - 1129 - "@ungap/structured-clone@^1.2.0": 1130 - version "1.2.0" 1131 - resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz" 1132 - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== 1133 - 1134 - acorn-jsx@^5.3.2: 1135 - version "5.3.2" 1136 - resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" 1137 - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== 1138 - 1139 - acorn-walk@^8.1.1: 1140 - version "8.3.3" 1141 - resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz" 1142 - integrity sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw== 1143 - dependencies: 1144 - acorn "^8.11.0" 1145 - 1146 - "acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.11.0, acorn@^8.4.1, acorn@^8.9.0: 1147 - version "8.12.0" 1148 - resolved "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz" 1149 - integrity sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw== 1150 - 1151 - agent-base@^7.0.2: 1152 - version "7.1.1" 1153 - resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz" 1154 - integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== 1155 - dependencies: 1156 - debug "^4.3.4" 1157 - 1158 - ajv@^6.12.4: 1159 - version "6.12.6" 1160 - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" 1161 - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 1162 - dependencies: 1163 - fast-deep-equal "^3.1.1" 1164 - fast-json-stable-stringify "^2.0.0" 1165 - json-schema-traverse "^0.4.1" 1166 - uri-js "^4.2.2" 1167 - 1168 - ajv@^8.11.0: 1169 - version "8.16.0" 1170 - resolved "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz" 1171 - integrity sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw== 1172 - dependencies: 1173 - fast-deep-equal "^3.1.3" 1174 - json-schema-traverse "^1.0.0" 1175 - require-from-string "^2.0.2" 1176 - uri-js "^4.4.1" 1177 - 1178 - ansi-escapes@^4.2.1: 1179 - version "4.3.2" 1180 - resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" 1181 - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== 1182 - dependencies: 1183 - type-fest "^0.21.3" 1184 - 1185 - ansi-escapes@^5.0.0: 1186 - version "5.0.0" 1187 - resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz" 1188 - integrity sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA== 1189 - dependencies: 1190 - type-fest "^1.0.2" 1191 - 1192 - ansi-regex@^5.0.1: 1193 - version "5.0.1" 1194 - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" 1195 - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 1196 - 1197 - ansi-regex@^6.0.1: 1198 - version "6.0.1" 1199 - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz" 1200 - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== 1201 - 1202 - ansi-styles@^3.2.1: 1203 - version "3.2.1" 1204 - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" 1205 - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 1206 - dependencies: 1207 - color-convert "^1.9.0" 1208 - 1209 - ansi-styles@^4.0.0, ansi-styles@^4.1.0: 1210 - version "4.3.0" 1211 - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" 1212 - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 1213 - dependencies: 1214 - color-convert "^2.0.1" 1215 - 1216 - ansi-styles@^5.0.0: 1217 - version "5.2.0" 1218 - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz" 1219 - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== 1220 - 1221 - ansi-styles@^6.0.0: 1222 - version "6.2.1" 1223 - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz" 1224 - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== 1225 - 1226 - ansi-styles@^6.1.0: 1227 - version "6.2.1" 1228 - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz" 1229 - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== 1230 - 1231 - anymatch@^3.0.3: 1232 - version "3.1.3" 1233 - resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" 1234 - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== 1235 - dependencies: 1236 - normalize-path "^3.0.0" 1237 - picomatch "^2.0.4" 1238 - 1239 - arg@^4.1.0: 1240 - version "4.1.3" 1241 - resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" 1242 - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== 1243 - 1244 - argparse@^1.0.7: 1245 - version "1.0.10" 1246 - resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" 1247 - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== 1248 - dependencies: 1249 - sprintf-js "~1.0.2" 1250 - 1251 - argparse@^2.0.1: 1252 - version "2.0.1" 1253 - resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" 1254 - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 1255 - 1256 - array-ify@^1.0.0: 1257 - version "1.0.0" 1258 - resolved "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz" 1259 - integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng== 1260 - 1261 - array-union@^1.0.1: 1262 - version "1.0.2" 1263 - resolved "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz" 1264 - integrity sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng== 1265 - dependencies: 1266 - array-uniq "^1.0.1" 1267 - 1268 - array-union@^2.1.0: 1269 - version "2.1.0" 1270 - resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" 1271 - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== 1272 - 1273 - array-uniq@^1.0.1: 1274 - version "1.0.3" 1275 - resolved "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz" 1276 - integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q== 1277 - 1278 - arrify@^1.0.1: 1279 - version "1.0.1" 1280 - resolved "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz" 1281 - integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== 1282 - 1283 - async-function@^1.0.0: 1284 - version "1.0.0" 1285 - resolved "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz" 1286 - integrity sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA== 1287 - 1288 - async-generator-function@^1.0.0: 1289 - version "1.0.0" 1290 - resolved "https://registry.npmjs.org/async-generator-function/-/async-generator-function-1.0.0.tgz" 1291 - integrity sha512-+NAXNqgCrB95ya4Sr66i1CL2hqLVckAk7xwRYWdcm39/ELQ6YNn1aw5r0bdQtqNZgQpEWzc5yc/igXc7aL5SLA== 1292 - 1293 - async@^3.2.4: 1294 - version "3.2.5" 1295 - resolved "https://registry.npmjs.org/async/-/async-3.2.5.tgz" 1296 - integrity sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg== 1297 - 1298 - asynckit@^0.4.0: 1299 - version "0.4.0" 1300 - resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" 1301 - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== 1302 - 1303 - at-least-node@^1.0.0: 1304 - version "1.0.0" 1305 - resolved "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz" 1306 - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== 1307 - 1308 - babel-jest@^29.0.0, babel-jest@^29.7.0: 1309 - version "29.7.0" 1310 - resolved "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz" 1311 - integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== 1312 - dependencies: 1313 - "@jest/transform" "^29.7.0" 1314 - "@types/babel__core" "^7.1.14" 1315 - babel-plugin-istanbul "^6.1.1" 1316 - babel-preset-jest "^29.6.3" 1317 - chalk "^4.0.0" 1318 - graceful-fs "^4.2.9" 1319 - slash "^3.0.0" 1320 - 1321 - babel-plugin-istanbul@^6.1.1: 1322 - version "6.1.1" 1323 - resolved "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz" 1324 - integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== 1325 - dependencies: 1326 - "@babel/helper-plugin-utils" "^7.0.0" 1327 - "@istanbuljs/load-nyc-config" "^1.0.0" 1328 - "@istanbuljs/schema" "^0.1.2" 1329 - istanbul-lib-instrument "^5.0.4" 1330 - test-exclude "^6.0.0" 1331 - 1332 - babel-plugin-jest-hoist@^29.6.3: 1333 - version "29.6.3" 1334 - resolved "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz" 1335 - integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== 1336 - dependencies: 1337 - "@babel/template" "^7.3.3" 1338 - "@babel/types" "^7.3.3" 1339 - "@types/babel__core" "^7.1.14" 1340 - "@types/babel__traverse" "^7.0.6" 1341 - 1342 - babel-preset-current-node-syntax@^1.0.0: 1343 - version "1.2.0" 1344 - resolved "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz" 1345 - integrity sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg== 1346 - dependencies: 1347 - "@babel/plugin-syntax-async-generators" "^7.8.4" 1348 - "@babel/plugin-syntax-bigint" "^7.8.3" 1349 - "@babel/plugin-syntax-class-properties" "^7.12.13" 1350 - "@babel/plugin-syntax-class-static-block" "^7.14.5" 1351 - "@babel/plugin-syntax-import-attributes" "^7.24.7" 1352 - "@babel/plugin-syntax-import-meta" "^7.10.4" 1353 - "@babel/plugin-syntax-json-strings" "^7.8.3" 1354 - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" 1355 - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" 1356 - "@babel/plugin-syntax-numeric-separator" "^7.10.4" 1357 - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" 1358 - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" 1359 - "@babel/plugin-syntax-optional-chaining" "^7.8.3" 1360 - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" 1361 - "@babel/plugin-syntax-top-level-await" "^7.14.5" 1362 - 1363 - babel-preset-jest@^29.6.3: 1364 - version "29.6.3" 1365 - resolved "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz" 1366 - integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== 1367 - dependencies: 1368 - babel-plugin-jest-hoist "^29.6.3" 1369 - babel-preset-current-node-syntax "^1.0.0" 1370 - 1371 - balanced-match@^1.0.0: 1372 - version "1.0.2" 1373 - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" 1374 - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 1375 - 1376 - base64-js@^1.3.1: 1377 - version "1.5.1" 1378 - resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" 1379 - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== 1380 - 1381 - baseline-browser-mapping@^2.8.3: 1382 - version "2.8.9" 1383 - resolved "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.9.tgz" 1384 - integrity sha512-hY/u2lxLrbecMEWSB0IpGzGyDyeoMFQhCvZd2jGFSE5I17Fh01sYUBPCJtkWERw7zrac9+cIghxm/ytJa2X8iA== 1385 - 1386 - bl@^4.1.0: 1387 - version "4.1.0" 1388 - resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz" 1389 - integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== 1390 - dependencies: 1391 - buffer "^5.5.0" 1392 - inherits "^2.0.4" 1393 - readable-stream "^3.4.0" 1394 - 1395 - boolbase@^1.0.0: 1396 - version "1.0.0" 1397 - resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" 1398 - integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== 1399 - 1400 - brace-expansion@^1.1.7: 1401 - version "1.1.11" 1402 - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" 1403 - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 1404 - dependencies: 1405 - balanced-match "^1.0.0" 1406 - concat-map "0.0.1" 1407 - 1408 - brace-expansion@^2.0.1: 1409 - version "2.0.1" 1410 - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" 1411 - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== 1412 - dependencies: 1413 - balanced-match "^1.0.0" 1414 - 1415 - braces@^3.0.2, braces@^3.0.3: 1416 - version "3.0.3" 1417 - resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" 1418 - integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== 1419 - dependencies: 1420 - fill-range "^7.1.1" 1421 - 1422 - browserslist@^4.24.0, "browserslist@>= 4.21.0": 1423 - version "4.26.2" 1424 - resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.26.2.tgz" 1425 - integrity sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A== 1426 - dependencies: 1427 - baseline-browser-mapping "^2.8.3" 1428 - caniuse-lite "^1.0.30001741" 1429 - electron-to-chromium "^1.5.218" 1430 - node-releases "^2.0.21" 1431 - update-browserslist-db "^1.1.3" 1432 - 1433 - bs-logger@0.x: 1434 - version "0.2.6" 1435 - resolved "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz" 1436 - integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== 1437 - dependencies: 1438 - fast-json-stable-stringify "2.x" 1439 - 1440 - bser@2.1.1: 1441 - version "2.1.1" 1442 - resolved "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz" 1443 - integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== 1444 - dependencies: 1445 - node-int64 "^0.4.0" 1446 - 1447 - buffer-from@^1.0.0: 1448 - version "1.1.2" 1449 - resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" 1450 - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== 1451 - 1452 - buffer@^5.5.0: 1453 - version "5.7.1" 1454 - resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" 1455 - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== 1456 - dependencies: 1457 - base64-js "^1.3.1" 1458 - ieee754 "^1.1.13" 1459 - 1460 - cachedir@2.3.0: 1461 - version "2.3.0" 1462 - resolved "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz" 1463 - integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw== 1464 - 1465 - call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: 1466 - version "1.0.2" 1467 - resolved "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz" 1468 - integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== 1469 - dependencies: 1470 - es-errors "^1.3.0" 1471 - function-bind "^1.1.2" 1472 - 1473 - call-bind@^1.0.5: 1474 - version "1.0.7" 1475 - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz" 1476 - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== 1477 - dependencies: 1478 - es-define-property "^1.0.0" 1479 - es-errors "^1.3.0" 1480 - function-bind "^1.1.2" 1481 - get-intrinsic "^1.2.4" 1482 - set-function-length "^1.2.1" 1483 - 1484 - callsites@^3.0.0: 1485 - version "3.1.0" 1486 - resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" 1487 - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 1488 - 1489 - camelcase-keys@^6.2.2: 1490 - version "6.2.2" 1491 - resolved "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz" 1492 - integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== 1493 - dependencies: 1494 - camelcase "^5.3.1" 1495 - map-obj "^4.0.0" 1496 - quick-lru "^4.0.1" 1497 - 1498 - camelcase@^5.3.1: 1499 - version "5.3.1" 1500 - resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" 1501 - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== 1502 - 1503 - camelcase@^6.2.0: 1504 - version "6.3.0" 1505 - resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" 1506 - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== 1507 - 1508 - caniuse-lite@^1.0.30001741: 1509 - version "1.0.30001745" 1510 - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001745.tgz" 1511 - integrity sha512-ywt6i8FzvdgrrrGbr1jZVObnVv6adj+0if2/omv9cmR2oiZs30zL4DIyaptKcbOrBdOIc74QTMoJvSE2QHh5UQ== 1512 - 1513 - chalk@^2.4.1: 1514 - version "2.4.2" 1515 - resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" 1516 - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 1517 - dependencies: 1518 - ansi-styles "^3.2.1" 1519 - escape-string-regexp "^1.0.5" 1520 - supports-color "^5.3.0" 1521 - 1522 - chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: 1523 - version "4.1.2" 1524 - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" 1525 - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 1526 - dependencies: 1527 - ansi-styles "^4.1.0" 1528 - supports-color "^7.1.0" 1529 - 1530 - chalk@5.3.0: 1531 - version "5.3.0" 1532 - resolved "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz" 1533 - integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== 1534 - 1535 - char-regex@^1.0.2: 1536 - version "1.0.2" 1537 - resolved "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz" 1538 - integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== 1539 - 1540 - chardet@^0.7.0: 1541 - version "0.7.0" 1542 - resolved "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz" 1543 - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== 1544 - 1545 - ci-info@^3.2.0: 1546 - version "3.9.0" 1547 - resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz" 1548 - integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== 1549 - 1550 - cjs-module-lexer@^1.0.0: 1551 - version "1.4.3" 1552 - resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz" 1553 - integrity sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q== 1554 - 1555 - cli-cursor@^3.1.0: 1556 - version "3.1.0" 1557 - resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz" 1558 - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== 1559 - dependencies: 1560 - restore-cursor "^3.1.0" 1561 - 1562 - cli-cursor@^4.0.0: 1563 - version "4.0.0" 1564 - resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz" 1565 - integrity sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg== 1566 - dependencies: 1567 - restore-cursor "^4.0.0" 1568 - 1569 - cli-spinners@^2.5.0: 1570 - version "2.9.2" 1571 - resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz" 1572 - integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== 1573 - 1574 - cli-truncate@^3.1.0: 1575 - version "3.1.0" 1576 - resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz" 1577 - integrity sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA== 1578 - dependencies: 1579 - slice-ansi "^5.0.0" 1580 - string-width "^5.0.0" 1581 - 1582 - cli-width@^3.0.0: 1583 - version "3.0.0" 1584 - resolved "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz" 1585 - integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== 1586 - 1587 - cliui@^8.0.1: 1588 - version "8.0.1" 1589 - resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" 1590 - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== 1591 - dependencies: 1592 - string-width "^4.2.0" 1593 - strip-ansi "^6.0.1" 1594 - wrap-ansi "^7.0.0" 1595 - 1596 - clone@^1.0.2: 1597 - version "1.0.4" 1598 - resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz" 1599 - integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== 1600 - 1601 - co@^4.6.0: 1602 - version "4.6.0" 1603 - resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz" 1604 - integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== 1605 - 1606 - collect-v8-coverage@^1.0.0: 1607 - version "1.0.2" 1608 - resolved "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz" 1609 - integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== 1610 - 1611 - color-convert@^1.9.0: 1612 - version "1.9.3" 1613 - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" 1614 - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 1615 - dependencies: 1616 - color-name "1.1.3" 1617 - 1618 - color-convert@^2.0.1: 1619 - version "2.0.1" 1620 - resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" 1621 - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 1622 - dependencies: 1623 - color-name "~1.1.4" 1624 - 1625 - color-name@~1.1.4: 1626 - version "1.1.4" 1627 - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" 1628 - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 1629 - 1630 - color-name@1.1.3: 1631 - version "1.1.3" 1632 - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" 1633 - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== 1634 - 1635 - colorette@^2.0.20: 1636 - version "2.0.20" 1637 - resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz" 1638 - integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== 1639 - 1640 - combined-stream@^1.0.8: 1641 - version "1.0.8" 1642 - resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" 1643 - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 1644 - dependencies: 1645 - delayed-stream "~1.0.0" 1646 - 1647 - commander@^2.18.0: 1648 - version "2.20.3" 1649 - resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" 1650 - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 1651 - 1652 - commander@11.0.0: 1653 - version "11.0.0" 1654 - resolved "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz" 1655 - integrity sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ== 1656 - 1657 - commitizen@^4.0.3: 1658 - version "4.3.0" 1659 - resolved "https://registry.npmjs.org/commitizen/-/commitizen-4.3.0.tgz" 1660 - integrity sha512-H0iNtClNEhT0fotHvGV3E9tDejDeS04sN1veIebsKYGMuGscFaswRoYJKmT3eW85eIJAs0F28bG2+a/9wCOfPw== 1661 - dependencies: 1662 - cachedir "2.3.0" 1663 - cz-conventional-changelog "3.3.0" 1664 - dedent "0.7.0" 1665 - detect-indent "6.1.0" 1666 - find-node-modules "^2.1.2" 1667 - find-root "1.1.0" 1668 - fs-extra "9.1.0" 1669 - glob "7.2.3" 1670 - inquirer "8.2.5" 1671 - is-utf8 "^0.2.1" 1672 - lodash "4.17.21" 1673 - minimist "1.2.7" 1674 - strip-bom "4.0.0" 1675 - strip-json-comments "3.1.1" 1676 - 1677 - commondir@^1.0.1: 1678 - version "1.0.1" 1679 - resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" 1680 - integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== 1681 - 1682 - compare-func@^2.0.0: 1683 - version "2.0.0" 1684 - resolved "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz" 1685 - integrity sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA== 1686 - dependencies: 1687 - array-ify "^1.0.0" 1688 - dot-prop "^5.1.0" 1689 - 1690 - concat-map@0.0.1: 1691 - version "0.0.1" 1692 - resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" 1693 - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== 1694 - 1695 - conventional-changelog-angular@^6.0.0: 1696 - version "6.0.0" 1697 - resolved "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz" 1698 - integrity sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg== 1699 - dependencies: 1700 - compare-func "^2.0.0" 1701 - 1702 - conventional-changelog-conventionalcommits@^6.1.0: 1703 - version "6.1.0" 1704 - resolved "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-6.1.0.tgz" 1705 - integrity sha512-3cS3GEtR78zTfMzk0AizXKKIdN4OvSh7ibNz6/DPbhWWQu7LqE/8+/GqSodV+sywUR2gpJAdP/1JFf4XtN7Zpw== 1706 - dependencies: 1707 - compare-func "^2.0.0" 1708 - 1709 - conventional-commit-types@^3.0.0: 1710 - version "3.0.0" 1711 - resolved "https://registry.npmjs.org/conventional-commit-types/-/conventional-commit-types-3.0.0.tgz" 1712 - integrity sha512-SmmCYnOniSsAa9GqWOeLqc179lfr5TRu5b4QFDkbsrJ5TZjPJx85wtOr3zn+1dbeNiXDKGPbZ72IKbPhLXh/Lg== 1713 - 1714 - conventional-commits-parser@^4.0.0: 1715 - version "4.0.0" 1716 - resolved "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-4.0.0.tgz" 1717 - integrity sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg== 1718 - dependencies: 1719 - is-text-path "^1.0.1" 1720 - JSONStream "^1.3.5" 1721 - meow "^8.1.2" 1722 - split2 "^3.2.2" 1723 - 1724 - convert-source-map@^2.0.0: 1725 - version "2.0.0" 1726 - resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz" 1727 - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== 1728 - 1729 - cosmiconfig-typescript-loader@^4.0.0: 1730 - version "4.4.0" 1731 - resolved "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.4.0.tgz" 1732 - integrity sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw== 1733 - 1734 - cosmiconfig@^8.0.0, cosmiconfig@>=7: 1735 - version "8.3.6" 1736 - resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz" 1737 - integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== 1738 - dependencies: 1739 - import-fresh "^3.3.0" 1740 - js-yaml "^4.1.0" 1741 - parse-json "^5.2.0" 1742 - path-type "^4.0.0" 1743 - 1744 - create-jest@^29.7.0: 1745 - version "29.7.0" 1746 - resolved "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz" 1747 - integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== 1748 - dependencies: 1749 - "@jest/types" "^29.6.3" 1750 - chalk "^4.0.0" 1751 - exit "^0.1.2" 1752 - graceful-fs "^4.2.9" 1753 - jest-config "^29.7.0" 1754 - jest-util "^29.7.0" 1755 - prompts "^2.0.1" 1756 - 1757 - create-require@^1.1.0: 1758 - version "1.1.1" 1759 - resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" 1760 - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== 1761 - 1762 - cross-fetch@^4.0.0-alpha.5: 1763 - version "4.0.0" 1764 - resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz" 1765 - integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g== 1766 - dependencies: 1767 - node-fetch "^2.6.12" 1768 - 1769 - cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: 1770 - version "7.0.3" 1771 - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" 1772 - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== 1773 - dependencies: 1774 - path-key "^3.1.0" 1775 - shebang-command "^2.0.0" 1776 - which "^2.0.1" 1777 - 1778 - css-select@^5.1.0: 1779 - version "5.2.2" 1780 - resolved "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz" 1781 - integrity sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw== 1782 - dependencies: 1783 - boolbase "^1.0.0" 1784 - css-what "^6.1.0" 1785 - domhandler "^5.0.2" 1786 - domutils "^3.0.1" 1787 - nth-check "^2.0.1" 1788 - 1789 - css-what@^6.1.0: 1790 - version "6.2.2" 1791 - resolved "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz" 1792 - integrity sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA== 1793 - 1794 - cssom@^0.5.0: 1795 - version "0.5.0" 1796 - resolved "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz" 1797 - integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw== 1798 - 1799 - cycletls@^2.0.4: 1800 - version "2.0.4" 1801 - resolved "https://registry.npmjs.org/cycletls/-/cycletls-2.0.4.tgz" 1802 - integrity sha512-kyQewFdaKa+IiUd4sR0PmNP0+xXPTx+7eC8LPTmR0/F5Txv40Z7OSI46cQqWM8cgiCwOf6GsB3s9QK9TLizYog== 1803 - dependencies: 1804 - "@types/node" "^20.14.0" 1805 - form-data "^4.0.0" 1806 - ws "^8.17.0" 1807 - 1808 - cz-conventional-changelog@^3.3.0, cz-conventional-changelog@3.3.0: 1809 - version "3.3.0" 1810 - resolved "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.3.0.tgz" 1811 - integrity sha512-U466fIzU5U22eES5lTNiNbZ+d8dfcHcssH4o7QsdWaCcRs/feIPCxKYSWkYBNs5mny7MvEfwpTLWjvbm94hecw== 1812 - dependencies: 1813 - chalk "^2.4.1" 1814 - commitizen "^4.0.3" 1815 - conventional-commit-types "^3.0.0" 1816 - lodash.map "^4.5.1" 1817 - longest "^2.0.1" 1818 - word-wrap "^1.0.3" 1819 - optionalDependencies: 1820 - "@commitlint/load" ">6.1.1" 1821 - 1822 - dargs@^7.0.0: 1823 - version "7.0.0" 1824 - resolved "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz" 1825 - integrity sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg== 1826 - 1827 - debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.1, debug@4: 1828 - version "4.4.3" 1829 - resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz" 1830 - integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== 1831 - dependencies: 1832 - ms "^2.1.3" 1833 - 1834 - debug@4.3.4: 1835 - version "4.3.4" 1836 - resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" 1837 - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 1838 - dependencies: 1839 - ms "2.1.2" 1840 - 1841 - decamelize-keys@^1.1.0: 1842 - version "1.1.1" 1843 - resolved "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz" 1844 - integrity sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg== 1845 - dependencies: 1846 - decamelize "^1.1.0" 1847 - map-obj "^1.0.0" 1848 - 1849 - decamelize@^1.1.0: 1850 - version "1.2.0" 1851 - resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" 1852 - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== 1853 - 1854 - dedent@^1.0.0: 1855 - version "1.7.0" 1856 - resolved "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz" 1857 - integrity sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ== 1858 - 1859 - dedent@0.7.0: 1860 - version "0.7.0" 1861 - resolved "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz" 1862 - integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== 1863 - 1864 - deep-is@^0.1.3: 1865 - version "0.1.4" 1866 - resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" 1867 - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== 1868 - 1869 - deepmerge@^4.2.2: 1870 - version "4.3.1" 1871 - resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" 1872 - integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== 1873 - 1874 - defaults@^1.0.3: 1875 - version "1.0.4" 1876 - resolved "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz" 1877 - integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== 1878 - dependencies: 1879 - clone "^1.0.2" 1880 - 1881 - define-data-property@^1.1.4: 1882 - version "1.1.4" 1883 - resolved "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz" 1884 - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== 1885 - dependencies: 1886 - es-define-property "^1.0.0" 1887 - es-errors "^1.3.0" 1888 - gopd "^1.0.1" 1889 - 1890 - delayed-stream@~1.0.0: 1891 - version "1.0.0" 1892 - resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" 1893 - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== 1894 - 1895 - detect-file@^1.0.0: 1896 - version "1.0.0" 1897 - resolved "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz" 1898 - integrity sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q== 1899 - 1900 - detect-indent@6.1.0: 1901 - version "6.1.0" 1902 - resolved "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz" 1903 - integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== 1904 - 1905 - detect-newline@^3.0.0: 1906 - version "3.1.0" 1907 - resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz" 1908 - integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== 1909 - 1910 - diff-sequences@^29.6.3: 1911 - version "29.6.3" 1912 - resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz" 1913 - integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== 1914 - 1915 - diff@^4.0.1: 1916 - version "4.0.2" 1917 - resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" 1918 - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== 1919 - 1920 - dir-glob@^3.0.1: 1921 - version "3.0.1" 1922 - resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" 1923 - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== 1924 - dependencies: 1925 - path-type "^4.0.0" 1926 - 1927 - doctrine@^3.0.0: 1928 - version "3.0.0" 1929 - resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" 1930 - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== 1931 - dependencies: 1932 - esutils "^2.0.2" 1933 - 1934 - dom-serializer@^2.0.0: 1935 - version "2.0.0" 1936 - resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz" 1937 - integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== 1938 - dependencies: 1939 - domelementtype "^2.3.0" 1940 - domhandler "^5.0.2" 1941 - entities "^4.2.0" 1942 - 1943 - domelementtype@^2.3.0: 1944 - version "2.3.0" 1945 - resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz" 1946 - integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== 1947 - 1948 - domhandler@^5.0.2, domhandler@^5.0.3: 1949 - version "5.0.3" 1950 - resolved "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz" 1951 - integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== 1952 - dependencies: 1953 - domelementtype "^2.3.0" 1954 - 1955 - domutils@^3.0.1, domutils@^3.2.1: 1956 - version "3.2.2" 1957 - resolved "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz" 1958 - integrity sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw== 1959 - dependencies: 1960 - dom-serializer "^2.0.0" 1961 - domelementtype "^2.3.0" 1962 - domhandler "^5.0.3" 1963 - 1964 - dot-prop@^5.1.0: 1965 - version "5.3.0" 1966 - resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz" 1967 - integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== 1968 - dependencies: 1969 - is-obj "^2.0.0" 1970 - 1971 - dotenv@^16.3.1: 1972 - version "16.6.1" 1973 - resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz" 1974 - integrity sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow== 1975 - 1976 - dunder-proto@^1.0.1: 1977 - version "1.0.1" 1978 - resolved "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz" 1979 - integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== 1980 - dependencies: 1981 - call-bind-apply-helpers "^1.0.1" 1982 - es-errors "^1.3.0" 1983 - gopd "^1.2.0" 1984 - 1985 - eastasianwidth@^0.2.0: 1986 - version "0.2.0" 1987 - resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz" 1988 - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== 1989 - 1990 - electron-to-chromium@^1.5.218: 1991 - version "1.5.227" 1992 - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.227.tgz" 1993 - integrity sha512-ITxuoPfJu3lsNWUi2lBM2PaBPYgH3uqmxut5vmBxgYvyI4AlJ6P3Cai1O76mOrkJCBzq0IxWg/NtqOrpu/0gKA== 1994 - 1995 - email-addresses@^5.0.0: 1996 - version "5.0.0" 1997 - resolved "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz" 1998 - integrity sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw== 1999 - 2000 - emittery@^0.13.1: 2001 - version "0.13.1" 2002 - resolved "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz" 2003 - integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== 2004 - 2005 - emoji-regex@^8.0.0: 2006 - version "8.0.0" 2007 - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" 2008 - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 2009 - 2010 - emoji-regex@^9.2.2: 2011 - version "9.2.2" 2012 - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz" 2013 - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== 2014 - 2015 - entities@^4.2.0, entities@^4.4.0: 2016 - version "4.5.0" 2017 - resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz" 2018 - integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== 2019 - 2020 - entities@^6.0.0: 2021 - version "6.0.1" 2022 - resolved "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz" 2023 - integrity sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g== 2024 - 2025 - error-ex@^1.3.1: 2026 - version "1.3.2" 2027 - resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" 2028 - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== 2029 - dependencies: 2030 - is-arrayish "^0.2.1" 2031 - 2032 - es-define-property@^1.0.0, es-define-property@^1.0.1: 2033 - version "1.0.1" 2034 - resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz" 2035 - integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== 2036 - 2037 - es-errors@^1.3.0: 2038 - version "1.3.0" 2039 - resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz" 2040 - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== 2041 - 2042 - es-module-lexer@^1.3.1: 2043 - version "1.5.3" 2044 - resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.3.tgz" 2045 - integrity sha512-i1gCgmR9dCl6Vil6UKPI/trA69s08g/syhiDK9TG0Nf1RJjjFI+AzoWW7sPufzkgYAn861skuCwJa0pIIHYxvg== 2046 - 2047 - es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: 2048 - version "1.1.1" 2049 - resolved "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz" 2050 - integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== 2051 - dependencies: 2052 - es-errors "^1.3.0" 2053 - 2054 - es-set-tostringtag@^2.1.0: 2055 - version "2.1.0" 2056 - resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz" 2057 - integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== 2058 - dependencies: 2059 - es-errors "^1.3.0" 2060 - get-intrinsic "^1.2.6" 2061 - has-tostringtag "^1.0.2" 2062 - hasown "^2.0.2" 2063 - 2064 - esbuild@^0.21.5, esbuild@>=0.18.0: 2065 - version "0.21.5" 2066 - resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz" 2067 - integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== 2068 - optionalDependencies: 2069 - "@esbuild/aix-ppc64" "0.21.5" 2070 - "@esbuild/android-arm" "0.21.5" 2071 - "@esbuild/android-arm64" "0.21.5" 2072 - "@esbuild/android-x64" "0.21.5" 2073 - "@esbuild/darwin-arm64" "0.21.5" 2074 - "@esbuild/darwin-x64" "0.21.5" 2075 - "@esbuild/freebsd-arm64" "0.21.5" 2076 - "@esbuild/freebsd-x64" "0.21.5" 2077 - "@esbuild/linux-arm" "0.21.5" 2078 - "@esbuild/linux-arm64" "0.21.5" 2079 - "@esbuild/linux-ia32" "0.21.5" 2080 - "@esbuild/linux-loong64" "0.21.5" 2081 - "@esbuild/linux-mips64el" "0.21.5" 2082 - "@esbuild/linux-ppc64" "0.21.5" 2083 - "@esbuild/linux-riscv64" "0.21.5" 2084 - "@esbuild/linux-s390x" "0.21.5" 2085 - "@esbuild/linux-x64" "0.21.5" 2086 - "@esbuild/netbsd-x64" "0.21.5" 2087 - "@esbuild/openbsd-x64" "0.21.5" 2088 - "@esbuild/sunos-x64" "0.21.5" 2089 - "@esbuild/win32-arm64" "0.21.5" 2090 - "@esbuild/win32-ia32" "0.21.5" 2091 - "@esbuild/win32-x64" "0.21.5" 2092 - 2093 - escalade@^3.1.1, escalade@^3.2.0: 2094 - version "3.2.0" 2095 - resolved "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz" 2096 - integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== 2097 - 2098 - escape-string-regexp@^1.0.2: 2099 - version "1.0.5" 2100 - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" 2101 - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== 2102 - 2103 - escape-string-regexp@^1.0.5: 2104 - version "1.0.5" 2105 - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" 2106 - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== 2107 - 2108 - escape-string-regexp@^2.0.0: 2109 - version "2.0.0" 2110 - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz" 2111 - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== 2112 - 2113 - escape-string-regexp@^4.0.0: 2114 - version "4.0.0" 2115 - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" 2116 - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 2117 - 2118 - eslint-config-prettier@^8.8.0: 2119 - version "8.10.0" 2120 - resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz" 2121 - integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg== 2122 - 2123 - eslint-plugin-prettier@^4.2.1: 2124 - version "4.2.1" 2125 - resolved "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz" 2126 - integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== 2127 - dependencies: 2128 - prettier-linter-helpers "^1.0.0" 2129 - 2130 - eslint-scope@^5.1.1: 2131 - version "5.1.1" 2132 - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" 2133 - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== 2134 - dependencies: 2135 - esrecurse "^4.3.0" 2136 - estraverse "^4.1.1" 2137 - 2138 - eslint-scope@^7.2.2: 2139 - version "7.2.2" 2140 - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz" 2141 - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== 2142 - dependencies: 2143 - esrecurse "^4.3.0" 2144 - estraverse "^5.2.0" 2145 - 2146 - eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: 2147 - version "3.4.3" 2148 - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" 2149 - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== 2150 - 2151 - eslint@*, "eslint@^6.0.0 || ^7.0.0 || ^8.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", eslint@^8.41.0, eslint@>=7.0.0, eslint@>=7.28.0: 2152 - version "8.57.0" 2153 - resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz" 2154 - integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== 2155 - dependencies: 2156 - "@eslint-community/eslint-utils" "^4.2.0" 2157 - "@eslint-community/regexpp" "^4.6.1" 2158 - "@eslint/eslintrc" "^2.1.4" 2159 - "@eslint/js" "8.57.0" 2160 - "@humanwhocodes/config-array" "^0.11.14" 2161 - "@humanwhocodes/module-importer" "^1.0.1" 2162 - "@nodelib/fs.walk" "^1.2.8" 2163 - "@ungap/structured-clone" "^1.2.0" 2164 - ajv "^6.12.4" 2165 - chalk "^4.0.0" 2166 - cross-spawn "^7.0.2" 2167 - debug "^4.3.2" 2168 - doctrine "^3.0.0" 2169 - escape-string-regexp "^4.0.0" 2170 - eslint-scope "^7.2.2" 2171 - eslint-visitor-keys "^3.4.3" 2172 - espree "^9.6.1" 2173 - esquery "^1.4.2" 2174 - esutils "^2.0.2" 2175 - fast-deep-equal "^3.1.3" 2176 - file-entry-cache "^6.0.1" 2177 - find-up "^5.0.0" 2178 - glob-parent "^6.0.2" 2179 - globals "^13.19.0" 2180 - graphemer "^1.4.0" 2181 - ignore "^5.2.0" 2182 - imurmurhash "^0.1.4" 2183 - is-glob "^4.0.0" 2184 - is-path-inside "^3.0.3" 2185 - js-yaml "^4.1.0" 2186 - json-stable-stringify-without-jsonify "^1.0.1" 2187 - levn "^0.4.1" 2188 - lodash.merge "^4.6.2" 2189 - minimatch "^3.1.2" 2190 - natural-compare "^1.4.0" 2191 - optionator "^0.9.3" 2192 - strip-ansi "^6.0.1" 2193 - text-table "^0.2.0" 2194 - 2195 - espree@^9.6.0, espree@^9.6.1: 2196 - version "9.6.1" 2197 - resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz" 2198 - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== 2199 - dependencies: 2200 - acorn "^8.9.0" 2201 - acorn-jsx "^5.3.2" 2202 - eslint-visitor-keys "^3.4.1" 2203 - 2204 - esprima@^4.0.0: 2205 - version "4.0.1" 2206 - resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" 2207 - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 2208 - 2209 - esquery@^1.4.2: 2210 - version "1.5.0" 2211 - resolved "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz" 2212 - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== 2213 - dependencies: 2214 - estraverse "^5.1.0" 2215 - 2216 - esrecurse@^4.3.0: 2217 - version "4.3.0" 2218 - resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" 2219 - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== 2220 - dependencies: 2221 - estraverse "^5.2.0" 2222 - 2223 - estraverse@^4.1.1: 2224 - version "4.3.0" 2225 - resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" 2226 - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== 2227 - 2228 - estraverse@^5.1.0: 2229 - version "5.3.0" 2230 - resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" 2231 - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== 2232 - 2233 - estraverse@^5.2.0: 2234 - version "5.3.0" 2235 - resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" 2236 - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== 2237 - 2238 - estree-walker@^2.0.2: 2239 - version "2.0.2" 2240 - resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz" 2241 - integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== 2242 - 2243 - esutils@^2.0.2: 2244 - version "2.0.3" 2245 - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" 2246 - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 2247 - 2248 - eventemitter3@^5.0.1: 2249 - version "5.0.1" 2250 - resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz" 2251 - integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== 2252 - 2253 - execa@^5.0.0: 2254 - version "5.1.1" 2255 - resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" 2256 - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== 2257 - dependencies: 2258 - cross-spawn "^7.0.3" 2259 - get-stream "^6.0.0" 2260 - human-signals "^2.1.0" 2261 - is-stream "^2.0.0" 2262 - merge-stream "^2.0.0" 2263 - npm-run-path "^4.0.1" 2264 - onetime "^5.1.2" 2265 - signal-exit "^3.0.3" 2266 - strip-final-newline "^2.0.0" 2267 - 2268 - execa@7.2.0: 2269 - version "7.2.0" 2270 - resolved "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz" 2271 - integrity sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA== 2272 - dependencies: 2273 - cross-spawn "^7.0.3" 2274 - get-stream "^6.0.1" 2275 - human-signals "^4.3.0" 2276 - is-stream "^3.0.0" 2277 - merge-stream "^2.0.0" 2278 - npm-run-path "^5.1.0" 2279 - onetime "^6.0.0" 2280 - signal-exit "^3.0.7" 2281 - strip-final-newline "^3.0.0" 2282 - 2283 - exit@^0.1.2: 2284 - version "0.1.2" 2285 - resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" 2286 - integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== 2287 - 2288 - expand-tilde@^2.0.0, expand-tilde@^2.0.2: 2289 - version "2.0.2" 2290 - resolved "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz" 2291 - integrity sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw== 2292 - dependencies: 2293 - homedir-polyfill "^1.0.1" 2294 - 2295 - expect@^29.0.0, expect@^29.7.0: 2296 - version "29.7.0" 2297 - resolved "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz" 2298 - integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== 2299 - dependencies: 2300 - "@jest/expect-utils" "^29.7.0" 2301 - jest-get-type "^29.6.3" 2302 - jest-matcher-utils "^29.7.0" 2303 - jest-message-util "^29.7.0" 2304 - jest-util "^29.7.0" 2305 - 2306 - external-editor@^3.0.3: 2307 - version "3.1.0" 2308 - resolved "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz" 2309 - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== 2310 - dependencies: 2311 - chardet "^0.7.0" 2312 - iconv-lite "^0.4.24" 2313 - tmp "^0.0.33" 2314 - 2315 - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: 2316 - version "3.1.3" 2317 - resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" 2318 - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 2319 - 2320 - fast-diff@^1.1.2: 2321 - version "1.3.0" 2322 - resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz" 2323 - integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== 2324 - 2325 - fast-glob@^3.2.9: 2326 - version "3.3.2" 2327 - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz" 2328 - integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== 2329 - dependencies: 2330 - "@nodelib/fs.stat" "^2.0.2" 2331 - "@nodelib/fs.walk" "^1.2.3" 2332 - glob-parent "^5.1.2" 2333 - merge2 "^1.3.0" 2334 - micromatch "^4.0.4" 2335 - 2336 - fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0, fast-json-stable-stringify@2.x: 2337 - version "2.1.0" 2338 - resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" 2339 - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 2340 - 2341 - fast-levenshtein@^2.0.6: 2342 - version "2.0.6" 2343 - resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" 2344 - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== 2345 - 2346 - fastq@^1.6.0: 2347 - version "1.17.1" 2348 - resolved "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz" 2349 - integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== 2350 - dependencies: 2351 - reusify "^1.0.4" 2352 - 2353 - fb-watchman@^2.0.0: 2354 - version "2.0.2" 2355 - resolved "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz" 2356 - integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== 2357 - dependencies: 2358 - bser "2.1.1" 2359 - 2360 - figures@^3.0.0: 2361 - version "3.2.0" 2362 - resolved "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz" 2363 - integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== 2364 - dependencies: 2365 - escape-string-regexp "^1.0.5" 2366 - 2367 - file-entry-cache@^6.0.1: 2368 - version "6.0.1" 2369 - resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" 2370 - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== 2371 - dependencies: 2372 - flat-cache "^3.0.4" 2373 - 2374 - filename-reserved-regex@^2.0.0: 2375 - version "2.0.0" 2376 - resolved "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz" 2377 - integrity sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ== 2378 - 2379 - filenamify@^4.3.0: 2380 - version "4.3.0" 2381 - resolved "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz" 2382 - integrity sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg== 2383 - dependencies: 2384 - filename-reserved-regex "^2.0.0" 2385 - strip-outer "^1.0.1" 2386 - trim-repeated "^1.0.0" 2387 - 2388 - fill-range@^7.1.1: 2389 - version "7.1.1" 2390 - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz" 2391 - integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== 2392 - dependencies: 2393 - to-regex-range "^5.0.1" 2394 - 2395 - find-cache-dir@^3.3.1: 2396 - version "3.3.2" 2397 - resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz" 2398 - integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== 2399 - dependencies: 2400 - commondir "^1.0.1" 2401 - make-dir "^3.0.2" 2402 - pkg-dir "^4.1.0" 2403 - 2404 - find-node-modules@^2.1.2: 2405 - version "2.1.3" 2406 - resolved "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.3.tgz" 2407 - integrity sha512-UC2I2+nx1ZuOBclWVNdcnbDR5dlrOdVb7xNjmT/lHE+LsgztWks3dG7boJ37yTS/venXw84B/mAW9uHVoC5QRg== 2408 - dependencies: 2409 - findup-sync "^4.0.0" 2410 - merge "^2.1.1" 2411 - 2412 - find-root@1.1.0: 2413 - version "1.1.0" 2414 - resolved "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz" 2415 - integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== 2416 - 2417 - find-up@^4.0.0: 2418 - version "4.1.0" 2419 - resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" 2420 - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== 2421 - dependencies: 2422 - locate-path "^5.0.0" 2423 - path-exists "^4.0.0" 2424 - 2425 - find-up@^4.1.0: 2426 - version "4.1.0" 2427 - resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" 2428 - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== 2429 - dependencies: 2430 - locate-path "^5.0.0" 2431 - path-exists "^4.0.0" 2432 - 2433 - find-up@^5.0.0: 2434 - version "5.0.0" 2435 - resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" 2436 - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 2437 - dependencies: 2438 - locate-path "^6.0.0" 2439 - path-exists "^4.0.0" 2440 - 2441 - findup-sync@^4.0.0: 2442 - version "4.0.0" 2443 - resolved "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz" 2444 - integrity sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ== 2445 - dependencies: 2446 - detect-file "^1.0.0" 2447 - is-glob "^4.0.0" 2448 - micromatch "^4.0.2" 2449 - resolve-dir "^1.0.1" 2450 - 2451 - flat-cache@^3.0.4: 2452 - version "3.2.0" 2453 - resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz" 2454 - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== 2455 - dependencies: 2456 - flatted "^3.2.9" 2457 - keyv "^4.5.3" 2458 - rimraf "^3.0.2" 2459 - 2460 - flatted@^3.2.9: 2461 - version "3.3.1" 2462 - resolved "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz" 2463 - integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== 2464 - 2465 - foreground-child@^3.1.0: 2466 - version "3.2.1" 2467 - resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz" 2468 - integrity sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA== 2469 - dependencies: 2470 - cross-spawn "^7.0.0" 2471 - signal-exit "^4.0.1" 2472 - 2473 - form-data@^4.0.0: 2474 - version "4.0.4" 2475 - resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz" 2476 - integrity sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow== 2477 - dependencies: 2478 - asynckit "^0.4.0" 2479 - combined-stream "^1.0.8" 2480 - es-set-tostringtag "^2.1.0" 2481 - hasown "^2.0.2" 2482 - mime-types "^2.1.12" 2483 - 2484 - fs-extra@^11.0.0: 2485 - version "11.2.0" 2486 - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz" 2487 - integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== 2488 - dependencies: 2489 - graceful-fs "^4.2.0" 2490 - jsonfile "^6.0.1" 2491 - universalify "^2.0.0" 2492 - 2493 - fs-extra@^8.1.0: 2494 - version "8.1.0" 2495 - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz" 2496 - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== 2497 - dependencies: 2498 - graceful-fs "^4.2.0" 2499 - jsonfile "^4.0.0" 2500 - universalify "^0.1.0" 2501 - 2502 - fs-extra@9.1.0: 2503 - version "9.1.0" 2504 - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz" 2505 - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== 2506 - dependencies: 2507 - at-least-node "^1.0.0" 2508 - graceful-fs "^4.2.0" 2509 - jsonfile "^6.0.1" 2510 - universalify "^2.0.0" 2511 - 2512 - fs.realpath@^1.0.0: 2513 - version "1.0.0" 2514 - resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" 2515 - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== 2516 - 2517 - function-bind@^1.1.2: 2518 - version "1.1.2" 2519 - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" 2520 - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== 2521 - 2522 - generator-function@^2.0.0: 2523 - version "2.0.0" 2524 - resolved "https://registry.npmjs.org/generator-function/-/generator-function-2.0.0.tgz" 2525 - integrity sha512-xPypGGincdfyl/AiSGa7GjXLkvld9V7GjZlowup9SHIJnQnHLFiLODCd/DqKOp0PBagbHJ68r1KJI9Mut7m4sA== 2526 - 2527 - gensync@^1.0.0-beta.2: 2528 - version "1.0.0-beta.2" 2529 - resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" 2530 - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== 2531 - 2532 - get-caller-file@^2.0.5: 2533 - version "2.0.5" 2534 - resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" 2535 - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 2536 - 2537 - get-intrinsic@^1.2.4, get-intrinsic@^1.2.6: 2538 - version "1.3.1" 2539 - resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.1.tgz" 2540 - integrity sha512-fk1ZVEeOX9hVZ6QzoBNEC55+Ucqg4sTVwrVuigZhuRPESVFpMyXnd3sbXvPOwp7Y9riVyANiqhEuRF0G1aVSeQ== 2541 - dependencies: 2542 - async-function "^1.0.0" 2543 - async-generator-function "^1.0.0" 2544 - call-bind-apply-helpers "^1.0.2" 2545 - es-define-property "^1.0.1" 2546 - es-errors "^1.3.0" 2547 - es-object-atoms "^1.1.1" 2548 - function-bind "^1.1.2" 2549 - generator-function "^2.0.0" 2550 - get-proto "^1.0.1" 2551 - gopd "^1.2.0" 2552 - has-symbols "^1.1.0" 2553 - hasown "^2.0.2" 2554 - math-intrinsics "^1.1.0" 2555 - 2556 - get-package-type@^0.1.0: 2557 - version "0.1.0" 2558 - resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" 2559 - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== 2560 - 2561 - get-proto@^1.0.1: 2562 - version "1.0.1" 2563 - resolved "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz" 2564 - integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== 2565 - dependencies: 2566 - dunder-proto "^1.0.1" 2567 - es-object-atoms "^1.0.0" 2568 - 2569 - get-stream@^6.0.0, get-stream@^6.0.1: 2570 - version "6.0.1" 2571 - resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" 2572 - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== 2573 - 2574 - get-tsconfig@^4.7.2: 2575 - version "4.7.5" 2576 - resolved "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz" 2577 - integrity sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw== 2578 - dependencies: 2579 - resolve-pkg-maps "^1.0.0" 2580 - 2581 - gh-pages@^5.0.0: 2582 - version "5.0.0" 2583 - resolved "https://registry.npmjs.org/gh-pages/-/gh-pages-5.0.0.tgz" 2584 - integrity sha512-Nqp1SjkPIB94Xw/3yYNTUL+G2dxlhjvv1zeN/4kMC1jfViTEqhtVz/Ba1zSXHuvXCN9ADNS1dN4r5/J/nZWEQQ== 2585 - dependencies: 2586 - async "^3.2.4" 2587 - commander "^2.18.0" 2588 - email-addresses "^5.0.0" 2589 - filenamify "^4.3.0" 2590 - find-cache-dir "^3.3.1" 2591 - fs-extra "^8.1.0" 2592 - globby "^6.1.0" 2593 - 2594 - git-raw-commits@^2.0.11: 2595 - version "2.0.11" 2596 - resolved "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz" 2597 - integrity sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A== 2598 - dependencies: 2599 - dargs "^7.0.0" 2600 - lodash "^4.17.15" 2601 - meow "^8.0.0" 2602 - split2 "^3.0.0" 2603 - through2 "^4.0.0" 2604 - 2605 - glob-parent@^5.1.2: 2606 - version "5.1.2" 2607 - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" 2608 - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 2609 - dependencies: 2610 - is-glob "^4.0.1" 2611 - 2612 - glob-parent@^6.0.2: 2613 - version "6.0.2" 2614 - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" 2615 - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== 2616 - dependencies: 2617 - is-glob "^4.0.3" 2618 - 2619 - glob@^10.3.7: 2620 - version "10.4.1" 2621 - resolved "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz" 2622 - integrity sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw== 2623 - dependencies: 2624 - foreground-child "^3.1.0" 2625 - jackspeak "^3.1.2" 2626 - minimatch "^9.0.4" 2627 - minipass "^7.1.2" 2628 - path-scurry "^1.11.1" 2629 - 2630 - glob@^7.0.3, glob@^7.1.3, glob@^7.1.4, glob@7.2.3: 2631 - version "7.2.3" 2632 - resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" 2633 - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== 2634 - dependencies: 2635 - fs.realpath "^1.0.0" 2636 - inflight "^1.0.4" 2637 - inherits "2" 2638 - minimatch "^3.1.1" 2639 - once "^1.3.0" 2640 - path-is-absolute "^1.0.0" 2641 - 2642 - global-dirs@^0.1.1: 2643 - version "0.1.1" 2644 - resolved "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz" 2645 - integrity sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg== 2646 - dependencies: 2647 - ini "^1.3.4" 2648 - 2649 - global-modules@^1.0.0: 2650 - version "1.0.0" 2651 - resolved "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz" 2652 - integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== 2653 - dependencies: 2654 - global-prefix "^1.0.1" 2655 - is-windows "^1.0.1" 2656 - resolve-dir "^1.0.0" 2657 - 2658 - global-prefix@^1.0.1: 2659 - version "1.0.2" 2660 - resolved "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz" 2661 - integrity sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg== 2662 - dependencies: 2663 - expand-tilde "^2.0.2" 2664 - homedir-polyfill "^1.0.1" 2665 - ini "^1.3.4" 2666 - is-windows "^1.0.1" 2667 - which "^1.2.14" 2668 - 2669 - globals@^13.19.0: 2670 - version "13.24.0" 2671 - resolved "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz" 2672 - integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== 2673 - dependencies: 2674 - type-fest "^0.20.2" 2675 - 2676 - globby@^11.1.0: 2677 - version "11.1.0" 2678 - resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" 2679 - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== 2680 - dependencies: 2681 - array-union "^2.1.0" 2682 - dir-glob "^3.0.1" 2683 - fast-glob "^3.2.9" 2684 - ignore "^5.2.0" 2685 - merge2 "^1.4.1" 2686 - slash "^3.0.0" 2687 - 2688 - globby@^6.1.0: 2689 - version "6.1.0" 2690 - resolved "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz" 2691 - integrity sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw== 2692 - dependencies: 2693 - array-union "^1.0.1" 2694 - glob "^7.0.3" 2695 - object-assign "^4.0.1" 2696 - pify "^2.0.0" 2697 - pinkie-promise "^2.0.0" 2698 - 2699 - gopd@^1.0.1, gopd@^1.2.0: 2700 - version "1.2.0" 2701 - resolved "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz" 2702 - integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== 2703 - 2704 - graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.9: 2705 - version "4.2.11" 2706 - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" 2707 - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== 2708 - 2709 - graphemer@^1.4.0: 2710 - version "1.4.0" 2711 - resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz" 2712 - integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== 2713 - 2714 - hard-rejection@^2.1.0: 2715 - version "2.1.0" 2716 - resolved "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz" 2717 - integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== 2718 - 2719 - has-flag@^3.0.0: 2720 - version "3.0.0" 2721 - resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" 2722 - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== 2723 - 2724 - has-flag@^4.0.0: 2725 - version "4.0.0" 2726 - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" 2727 - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 2728 - 2729 - has-property-descriptors@^1.0.2: 2730 - version "1.0.2" 2731 - resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz" 2732 - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== 2733 - dependencies: 2734 - es-define-property "^1.0.0" 2735 - 2736 - has-symbols@^1.0.3, has-symbols@^1.1.0: 2737 - version "1.1.0" 2738 - resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz" 2739 - integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== 2740 - 2741 - has-tostringtag@^1.0.2: 2742 - version "1.0.2" 2743 - resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz" 2744 - integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== 2745 - dependencies: 2746 - has-symbols "^1.0.3" 2747 - 2748 - hasown@^2.0.2: 2749 - version "2.0.2" 2750 - resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz" 2751 - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== 2752 - dependencies: 2753 - function-bind "^1.1.2" 2754 - 2755 - headers-polyfill@^3.1.2: 2756 - version "3.3.0" 2757 - resolved "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-3.3.0.tgz" 2758 - integrity sha512-5e57etwBpNcDc0b6KCVWEh/Ro063OxPvzVimUdM0/tsYM/T7Hfy3kknIGj78SFTOhNd8AZY41U8mOHoO4LzmIQ== 2759 - 2760 - homedir-polyfill@^1.0.1: 2761 - version "1.0.3" 2762 - resolved "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz" 2763 - integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== 2764 - dependencies: 2765 - parse-passwd "^1.0.0" 2766 - 2767 - hosted-git-info@^2.1.4: 2768 - version "2.8.9" 2769 - resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz" 2770 - integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== 2771 - 2772 - hosted-git-info@^4.0.1: 2773 - version "4.1.0" 2774 - resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz" 2775 - integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== 2776 - dependencies: 2777 - lru-cache "^6.0.0" 2778 - 2779 - html-escaper@^2.0.0: 2780 - version "2.0.2" 2781 - resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" 2782 - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== 2783 - 2784 - html-escaper@^3.0.3: 2785 - version "3.0.3" 2786 - resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz" 2787 - integrity sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ== 2788 - 2789 - htmlparser2@^10.0.0: 2790 - version "10.0.0" 2791 - resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz" 2792 - integrity sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g== 2793 - dependencies: 2794 - domelementtype "^2.3.0" 2795 - domhandler "^5.0.3" 2796 - domutils "^3.2.1" 2797 - entities "^6.0.0" 2798 - 2799 - https-proxy-agent@^7.0.2: 2800 - version "7.0.4" 2801 - resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz" 2802 - integrity sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg== 2803 - dependencies: 2804 - agent-base "^7.0.2" 2805 - debug "4" 2806 - 2807 - human-signals@^2.1.0: 2808 - version "2.1.0" 2809 - resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" 2810 - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== 2811 - 2812 - human-signals@^4.3.0: 2813 - version "4.3.1" 2814 - resolved "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz" 2815 - integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== 2816 - 2817 - husky@^8.0.3: 2818 - version "8.0.3" 2819 - resolved "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz" 2820 - integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== 2821 - 2822 - iconv-lite@^0.4.24: 2823 - version "0.4.24" 2824 - resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" 2825 - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 2826 - dependencies: 2827 - safer-buffer ">= 2.1.2 < 3" 2828 - 2829 - ieee754@^1.1.13: 2830 - version "1.2.1" 2831 - resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" 2832 - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== 2833 - 2834 - ignore@^5.2.0: 2835 - version "5.3.1" 2836 - resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz" 2837 - integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== 2838 - 2839 - import-fresh@^3.0.0, import-fresh@^3.2.1, import-fresh@^3.3.0: 2840 - version "3.3.0" 2841 - resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" 2842 - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== 2843 - dependencies: 2844 - parent-module "^1.0.0" 2845 - resolve-from "^4.0.0" 2846 - 2847 - import-local@^3.0.2: 2848 - version "3.2.0" 2849 - resolved "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz" 2850 - integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== 2851 - dependencies: 2852 - pkg-dir "^4.2.0" 2853 - resolve-cwd "^3.0.0" 2854 - 2855 - imurmurhash@^0.1.4: 2856 - version "0.1.4" 2857 - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" 2858 - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== 2859 - 2860 - indent-string@^4.0.0: 2861 - version "4.0.0" 2862 - resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" 2863 - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== 2864 - 2865 - inflight@^1.0.4: 2866 - version "1.0.6" 2867 - resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" 2868 - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== 2869 - dependencies: 2870 - once "^1.3.0" 2871 - wrappy "1" 2872 - 2873 - inherits@^2.0.3, inherits@^2.0.4, inherits@2: 2874 - version "2.0.4" 2875 - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" 2876 - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 2877 - 2878 - ini@^1.3.4: 2879 - version "1.3.8" 2880 - resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" 2881 - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== 2882 - 2883 - inquirer@8.2.5: 2884 - version "8.2.5" 2885 - resolved "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz" 2886 - integrity sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ== 2887 - dependencies: 2888 - ansi-escapes "^4.2.1" 2889 - chalk "^4.1.1" 2890 - cli-cursor "^3.1.0" 2891 - cli-width "^3.0.0" 2892 - external-editor "^3.0.3" 2893 - figures "^3.0.0" 2894 - lodash "^4.17.21" 2895 - mute-stream "0.0.8" 2896 - ora "^5.4.1" 2897 - run-async "^2.4.0" 2898 - rxjs "^7.5.5" 2899 - string-width "^4.1.0" 2900 - strip-ansi "^6.0.0" 2901 - through "^2.3.6" 2902 - wrap-ansi "^7.0.0" 2903 - 2904 - is-arrayish@^0.2.1: 2905 - version "0.2.1" 2906 - resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" 2907 - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== 2908 - 2909 - is-core-module@^2.16.0, is-core-module@^2.5.0: 2910 - version "2.16.1" 2911 - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz" 2912 - integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== 2913 - dependencies: 2914 - hasown "^2.0.2" 2915 - 2916 - is-extglob@^2.1.1: 2917 - version "2.1.1" 2918 - resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" 2919 - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 2920 - 2921 - is-fullwidth-code-point@^3.0.0: 2922 - version "3.0.0" 2923 - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" 2924 - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 2925 - 2926 - is-fullwidth-code-point@^4.0.0: 2927 - version "4.0.0" 2928 - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz" 2929 - integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== 2930 - 2931 - is-generator-fn@^2.0.0: 2932 - version "2.1.0" 2933 - resolved "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz" 2934 - integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== 2935 - 2936 - is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: 2937 - version "4.0.3" 2938 - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" 2939 - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 2940 - dependencies: 2941 - is-extglob "^2.1.1" 2942 - 2943 - is-interactive@^1.0.0: 2944 - version "1.0.0" 2945 - resolved "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz" 2946 - integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== 2947 - 2948 - is-number@^7.0.0: 2949 - version "7.0.0" 2950 - resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" 2951 - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 2952 - 2953 - is-obj@^2.0.0: 2954 - version "2.0.0" 2955 - resolved "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz" 2956 - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== 2957 - 2958 - is-path-inside@^3.0.3: 2959 - version "3.0.3" 2960 - resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" 2961 - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== 2962 - 2963 - is-plain-obj@^1.1.0: 2964 - version "1.1.0" 2965 - resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz" 2966 - integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== 2967 - 2968 - is-stream@^2.0.0: 2969 - version "2.0.1" 2970 - resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" 2971 - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== 2972 - 2973 - is-stream@^3.0.0: 2974 - version "3.0.0" 2975 - resolved "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz" 2976 - integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== 2977 - 2978 - is-text-path@^1.0.1: 2979 - version "1.0.1" 2980 - resolved "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz" 2981 - integrity sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w== 2982 - dependencies: 2983 - text-extensions "^1.0.0" 2984 - 2985 - is-unicode-supported@^0.1.0: 2986 - version "0.1.0" 2987 - resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" 2988 - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== 2989 - 2990 - is-utf8@^0.2.1: 2991 - version "0.2.1" 2992 - resolved "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" 2993 - integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== 2994 - 2995 - is-windows@^1.0.1: 2996 - version "1.0.2" 2997 - resolved "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz" 2998 - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== 2999 - 3000 - isarray@^2.0.5: 3001 - version "2.0.5" 3002 - resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz" 3003 - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== 3004 - 3005 - isexe@^2.0.0: 3006 - version "2.0.0" 3007 - resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" 3008 - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== 3009 - 3010 - istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: 3011 - version "3.2.2" 3012 - resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz" 3013 - integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== 3014 - 3015 - istanbul-lib-instrument@^5.0.4: 3016 - version "5.2.1" 3017 - resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz" 3018 - integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== 3019 - dependencies: 3020 - "@babel/core" "^7.12.3" 3021 - "@babel/parser" "^7.14.7" 3022 - "@istanbuljs/schema" "^0.1.2" 3023 - istanbul-lib-coverage "^3.2.0" 3024 - semver "^6.3.0" 3025 - 3026 - istanbul-lib-instrument@^6.0.0: 3027 - version "6.0.2" 3028 - resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz" 3029 - integrity sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw== 3030 - dependencies: 3031 - "@babel/core" "^7.23.9" 3032 - "@babel/parser" "^7.23.9" 3033 - "@istanbuljs/schema" "^0.1.3" 3034 - istanbul-lib-coverage "^3.2.0" 3035 - semver "^7.5.4" 3036 - 3037 - istanbul-lib-report@^3.0.0: 3038 - version "3.0.1" 3039 - resolved "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz" 3040 - integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== 3041 - dependencies: 3042 - istanbul-lib-coverage "^3.0.0" 3043 - make-dir "^4.0.0" 3044 - supports-color "^7.1.0" 3045 - 3046 - istanbul-lib-source-maps@^4.0.0: 3047 - version "4.0.1" 3048 - resolved "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz" 3049 - integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== 3050 - dependencies: 3051 - debug "^4.1.1" 3052 - istanbul-lib-coverage "^3.0.0" 3053 - source-map "^0.6.1" 3054 - 3055 - istanbul-reports@^3.1.3: 3056 - version "3.1.7" 3057 - resolved "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz" 3058 - integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== 3059 - dependencies: 3060 - html-escaper "^2.0.0" 3061 - istanbul-lib-report "^3.0.0" 3062 - 3063 - jackspeak@^3.1.2: 3064 - version "3.4.0" 3065 - resolved "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz" 3066 - integrity sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw== 3067 - dependencies: 3068 - "@isaacs/cliui" "^8.0.2" 3069 - optionalDependencies: 3070 - "@pkgjs/parseargs" "^0.11.0" 3071 - 3072 - jest-changed-files@^29.7.0: 3073 - version "29.7.0" 3074 - resolved "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz" 3075 - integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== 3076 - dependencies: 3077 - execa "^5.0.0" 3078 - jest-util "^29.7.0" 3079 - p-limit "^3.1.0" 3080 - 3081 - jest-circus@^29.7.0: 3082 - version "29.7.0" 3083 - resolved "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz" 3084 - integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== 3085 - dependencies: 3086 - "@jest/environment" "^29.7.0" 3087 - "@jest/expect" "^29.7.0" 3088 - "@jest/test-result" "^29.7.0" 3089 - "@jest/types" "^29.6.3" 3090 - "@types/node" "*" 3091 - chalk "^4.0.0" 3092 - co "^4.6.0" 3093 - dedent "^1.0.0" 3094 - is-generator-fn "^2.0.0" 3095 - jest-each "^29.7.0" 3096 - jest-matcher-utils "^29.7.0" 3097 - jest-message-util "^29.7.0" 3098 - jest-runtime "^29.7.0" 3099 - jest-snapshot "^29.7.0" 3100 - jest-util "^29.7.0" 3101 - p-limit "^3.1.0" 3102 - pretty-format "^29.7.0" 3103 - pure-rand "^6.0.0" 3104 - slash "^3.0.0" 3105 - stack-utils "^2.0.3" 3106 - 3107 - jest-cli@^29.7.0: 3108 - version "29.7.0" 3109 - resolved "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz" 3110 - integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== 3111 - dependencies: 3112 - "@jest/core" "^29.7.0" 3113 - "@jest/test-result" "^29.7.0" 3114 - "@jest/types" "^29.6.3" 3115 - chalk "^4.0.0" 3116 - create-jest "^29.7.0" 3117 - exit "^0.1.2" 3118 - import-local "^3.0.2" 3119 - jest-config "^29.7.0" 3120 - jest-util "^29.7.0" 3121 - jest-validate "^29.7.0" 3122 - yargs "^17.3.1" 3123 - 3124 - jest-config@^29.7.0: 3125 - version "29.7.0" 3126 - resolved "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz" 3127 - integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== 3128 - dependencies: 3129 - "@babel/core" "^7.11.6" 3130 - "@jest/test-sequencer" "^29.7.0" 3131 - "@jest/types" "^29.6.3" 3132 - babel-jest "^29.7.0" 3133 - chalk "^4.0.0" 3134 - ci-info "^3.2.0" 3135 - deepmerge "^4.2.2" 3136 - glob "^7.1.3" 3137 - graceful-fs "^4.2.9" 3138 - jest-circus "^29.7.0" 3139 - jest-environment-node "^29.7.0" 3140 - jest-get-type "^29.6.3" 3141 - jest-regex-util "^29.6.3" 3142 - jest-resolve "^29.7.0" 3143 - jest-runner "^29.7.0" 3144 - jest-util "^29.7.0" 3145 - jest-validate "^29.7.0" 3146 - micromatch "^4.0.4" 3147 - parse-json "^5.2.0" 3148 - pretty-format "^29.7.0" 3149 - slash "^3.0.0" 3150 - strip-json-comments "^3.1.1" 3151 - 3152 - jest-diff@^29.7.0: 3153 - version "29.7.0" 3154 - resolved "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz" 3155 - integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== 3156 - dependencies: 3157 - chalk "^4.0.0" 3158 - diff-sequences "^29.6.3" 3159 - jest-get-type "^29.6.3" 3160 - pretty-format "^29.7.0" 3161 - 3162 - jest-docblock@^29.7.0: 3163 - version "29.7.0" 3164 - resolved "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz" 3165 - integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== 3166 - dependencies: 3167 - detect-newline "^3.0.0" 3168 - 3169 - jest-each@^29.7.0: 3170 - version "29.7.0" 3171 - resolved "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz" 3172 - integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== 3173 - dependencies: 3174 - "@jest/types" "^29.6.3" 3175 - chalk "^4.0.0" 3176 - jest-get-type "^29.6.3" 3177 - jest-util "^29.7.0" 3178 - pretty-format "^29.7.0" 3179 - 3180 - jest-environment-node@^29.7.0: 3181 - version "29.7.0" 3182 - resolved "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz" 3183 - integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== 3184 - dependencies: 3185 - "@jest/environment" "^29.7.0" 3186 - "@jest/fake-timers" "^29.7.0" 3187 - "@jest/types" "^29.6.3" 3188 - "@types/node" "*" 3189 - jest-mock "^29.7.0" 3190 - jest-util "^29.7.0" 3191 - 3192 - jest-get-type@^29.6.3: 3193 - version "29.6.3" 3194 - resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz" 3195 - integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== 3196 - 3197 - jest-haste-map@^29.7.0: 3198 - version "29.7.0" 3199 - resolved "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz" 3200 - integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== 3201 - dependencies: 3202 - "@jest/types" "^29.6.3" 3203 - "@types/graceful-fs" "^4.1.3" 3204 - "@types/node" "*" 3205 - anymatch "^3.0.3" 3206 - fb-watchman "^2.0.0" 3207 - graceful-fs "^4.2.9" 3208 - jest-regex-util "^29.6.3" 3209 - jest-util "^29.7.0" 3210 - jest-worker "^29.7.0" 3211 - micromatch "^4.0.4" 3212 - walker "^1.0.8" 3213 - optionalDependencies: 3214 - fsevents "^2.3.2" 3215 - 3216 - jest-leak-detector@^29.7.0: 3217 - version "29.7.0" 3218 - resolved "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz" 3219 - integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== 3220 - dependencies: 3221 - jest-get-type "^29.6.3" 3222 - pretty-format "^29.7.0" 3223 - 3224 - jest-matcher-utils@^29.7.0: 3225 - version "29.7.0" 3226 - resolved "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz" 3227 - integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== 3228 - dependencies: 3229 - chalk "^4.0.0" 3230 - jest-diff "^29.7.0" 3231 - jest-get-type "^29.6.3" 3232 - pretty-format "^29.7.0" 3233 - 3234 - jest-message-util@^29.7.0: 3235 - version "29.7.0" 3236 - resolved "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz" 3237 - integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== 3238 - dependencies: 3239 - "@babel/code-frame" "^7.12.13" 3240 - "@jest/types" "^29.6.3" 3241 - "@types/stack-utils" "^2.0.0" 3242 - chalk "^4.0.0" 3243 - graceful-fs "^4.2.9" 3244 - micromatch "^4.0.4" 3245 - pretty-format "^29.7.0" 3246 - slash "^3.0.0" 3247 - stack-utils "^2.0.3" 3248 - 3249 - jest-mock@^29.7.0: 3250 - version "29.7.0" 3251 - resolved "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz" 3252 - integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== 3253 - dependencies: 3254 - "@jest/types" "^29.6.3" 3255 - "@types/node" "*" 3256 - jest-util "^29.7.0" 3257 - 3258 - jest-pnp-resolver@^1.2.2: 3259 - version "1.2.3" 3260 - resolved "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz" 3261 - integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== 3262 - 3263 - jest-regex-util@^29.6.3: 3264 - version "29.6.3" 3265 - resolved "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz" 3266 - integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== 3267 - 3268 - jest-resolve-dependencies@^29.7.0: 3269 - version "29.7.0" 3270 - resolved "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz" 3271 - integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== 3272 - dependencies: 3273 - jest-regex-util "^29.6.3" 3274 - jest-snapshot "^29.7.0" 3275 - 3276 - jest-resolve@*, jest-resolve@^29.7.0: 3277 - version "29.7.0" 3278 - resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz" 3279 - integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== 3280 - dependencies: 3281 - chalk "^4.0.0" 3282 - graceful-fs "^4.2.9" 3283 - jest-haste-map "^29.7.0" 3284 - jest-pnp-resolver "^1.2.2" 3285 - jest-util "^29.7.0" 3286 - jest-validate "^29.7.0" 3287 - resolve "^1.20.0" 3288 - resolve.exports "^2.0.0" 3289 - slash "^3.0.0" 3290 - 3291 - jest-runner@^29.7.0: 3292 - version "29.7.0" 3293 - resolved "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz" 3294 - integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== 3295 - dependencies: 3296 - "@jest/console" "^29.7.0" 3297 - "@jest/environment" "^29.7.0" 3298 - "@jest/test-result" "^29.7.0" 3299 - "@jest/transform" "^29.7.0" 3300 - "@jest/types" "^29.6.3" 3301 - "@types/node" "*" 3302 - chalk "^4.0.0" 3303 - emittery "^0.13.1" 3304 - graceful-fs "^4.2.9" 3305 - jest-docblock "^29.7.0" 3306 - jest-environment-node "^29.7.0" 3307 - jest-haste-map "^29.7.0" 3308 - jest-leak-detector "^29.7.0" 3309 - jest-message-util "^29.7.0" 3310 - jest-resolve "^29.7.0" 3311 - jest-runtime "^29.7.0" 3312 - jest-util "^29.7.0" 3313 - jest-watcher "^29.7.0" 3314 - jest-worker "^29.7.0" 3315 - p-limit "^3.1.0" 3316 - source-map-support "0.5.13" 3317 - 3318 - jest-runtime@^29.7.0: 3319 - version "29.7.0" 3320 - resolved "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz" 3321 - integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== 3322 - dependencies: 3323 - "@jest/environment" "^29.7.0" 3324 - "@jest/fake-timers" "^29.7.0" 3325 - "@jest/globals" "^29.7.0" 3326 - "@jest/source-map" "^29.6.3" 3327 - "@jest/test-result" "^29.7.0" 3328 - "@jest/transform" "^29.7.0" 3329 - "@jest/types" "^29.6.3" 3330 - "@types/node" "*" 3331 - chalk "^4.0.0" 3332 - cjs-module-lexer "^1.0.0" 3333 - collect-v8-coverage "^1.0.0" 3334 - glob "^7.1.3" 3335 - graceful-fs "^4.2.9" 3336 - jest-haste-map "^29.7.0" 3337 - jest-message-util "^29.7.0" 3338 - jest-mock "^29.7.0" 3339 - jest-regex-util "^29.6.3" 3340 - jest-resolve "^29.7.0" 3341 - jest-snapshot "^29.7.0" 3342 - jest-util "^29.7.0" 3343 - slash "^3.0.0" 3344 - strip-bom "^4.0.0" 3345 - 3346 - jest-snapshot@^29.7.0: 3347 - version "29.7.0" 3348 - resolved "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz" 3349 - integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== 3350 - dependencies: 3351 - "@babel/core" "^7.11.6" 3352 - "@babel/generator" "^7.7.2" 3353 - "@babel/plugin-syntax-jsx" "^7.7.2" 3354 - "@babel/plugin-syntax-typescript" "^7.7.2" 3355 - "@babel/types" "^7.3.3" 3356 - "@jest/expect-utils" "^29.7.0" 3357 - "@jest/transform" "^29.7.0" 3358 - "@jest/types" "^29.6.3" 3359 - babel-preset-current-node-syntax "^1.0.0" 3360 - chalk "^4.0.0" 3361 - expect "^29.7.0" 3362 - graceful-fs "^4.2.9" 3363 - jest-diff "^29.7.0" 3364 - jest-get-type "^29.6.3" 3365 - jest-matcher-utils "^29.7.0" 3366 - jest-message-util "^29.7.0" 3367 - jest-util "^29.7.0" 3368 - natural-compare "^1.4.0" 3369 - pretty-format "^29.7.0" 3370 - semver "^7.5.3" 3371 - 3372 - jest-util@^29.0.0, jest-util@^29.7.0: 3373 - version "29.7.0" 3374 - resolved "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz" 3375 - integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== 3376 - dependencies: 3377 - "@jest/types" "^29.6.3" 3378 - "@types/node" "*" 3379 - chalk "^4.0.0" 3380 - ci-info "^3.2.0" 3381 - graceful-fs "^4.2.9" 3382 - picomatch "^2.2.3" 3383 - 3384 - jest-validate@^29.7.0: 3385 - version "29.7.0" 3386 - resolved "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz" 3387 - integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== 3388 - dependencies: 3389 - "@jest/types" "^29.6.3" 3390 - camelcase "^6.2.0" 3391 - chalk "^4.0.0" 3392 - jest-get-type "^29.6.3" 3393 - leven "^3.1.0" 3394 - pretty-format "^29.7.0" 3395 - 3396 - jest-watcher@^29.7.0: 3397 - version "29.7.0" 3398 - resolved "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz" 3399 - integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== 3400 - dependencies: 3401 - "@jest/test-result" "^29.7.0" 3402 - "@jest/types" "^29.6.3" 3403 - "@types/node" "*" 3404 - ansi-escapes "^4.2.1" 3405 - chalk "^4.0.0" 3406 - emittery "^0.13.1" 3407 - jest-util "^29.7.0" 3408 - string-length "^4.0.1" 3409 - 3410 - jest-worker@^29.7.0: 3411 - version "29.7.0" 3412 - resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz" 3413 - integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== 3414 - dependencies: 3415 - "@types/node" "*" 3416 - jest-util "^29.7.0" 3417 - merge-stream "^2.0.0" 3418 - supports-color "^8.0.0" 3419 - 3420 - jest@^29.0.0, jest@^29.5.0: 3421 - version "29.7.0" 3422 - resolved "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz" 3423 - integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== 3424 - dependencies: 3425 - "@jest/core" "^29.7.0" 3426 - "@jest/types" "^29.6.3" 3427 - import-local "^3.0.2" 3428 - jest-cli "^29.7.0" 3429 - 3430 - js-tokens@^4.0.0: 3431 - version "4.0.0" 3432 - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" 3433 - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 3434 - 3435 - js-yaml@^3.13.1: 3436 - version "3.14.1" 3437 - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" 3438 - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== 3439 - dependencies: 3440 - argparse "^1.0.7" 3441 - esprima "^4.0.0" 3442 - 3443 - js-yaml@^4.1.0: 3444 - version "4.1.0" 3445 - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" 3446 - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 3447 - dependencies: 3448 - argparse "^2.0.1" 3449 - 3450 - jsesc@^3.0.2: 3451 - version "3.1.0" 3452 - resolved "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz" 3453 - integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== 3454 - 3455 - json-buffer@3.0.1: 3456 - version "3.0.1" 3457 - resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz" 3458 - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== 3459 - 3460 - json-parse-even-better-errors@^2.3.0: 3461 - version "2.3.1" 3462 - resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" 3463 - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== 3464 - 3465 - json-schema-traverse@^0.4.1: 3466 - version "0.4.1" 3467 - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" 3468 - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 3469 - 3470 - json-schema-traverse@^1.0.0: 3471 - version "1.0.0" 3472 - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" 3473 - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== 3474 - 3475 - json-stable-stringify-without-jsonify@^1.0.1: 3476 - version "1.0.1" 3477 - resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" 3478 - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== 3479 - 3480 - json-stable-stringify@^1.0.2: 3481 - version "1.1.1" 3482 - resolved "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz" 3483 - integrity sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg== 3484 - dependencies: 3485 - call-bind "^1.0.5" 3486 - isarray "^2.0.5" 3487 - jsonify "^0.0.1" 3488 - object-keys "^1.1.1" 3489 - 3490 - json5@^2.2.3: 3491 - version "2.2.3" 3492 - resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" 3493 - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== 3494 - 3495 - jsonfile@^4.0.0: 3496 - version "4.0.0" 3497 - resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz" 3498 - integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== 3499 - optionalDependencies: 3500 - graceful-fs "^4.1.6" 3501 - 3502 - jsonfile@^6.0.1: 3503 - version "6.1.0" 3504 - resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" 3505 - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== 3506 - dependencies: 3507 - universalify "^2.0.0" 3508 - optionalDependencies: 3509 - graceful-fs "^4.1.6" 3510 - 3511 - jsonify@^0.0.1: 3512 - version "0.0.1" 3513 - resolved "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz" 3514 - integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== 3515 - 3516 - jsonparse@^1.2.0: 3517 - version "1.3.1" 3518 - resolved "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz" 3519 - integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== 3520 - 3521 - JSONStream@^1.3.5: 3522 - version "1.3.5" 3523 - resolved "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz" 3524 - integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== 3525 - dependencies: 3526 - jsonparse "^1.2.0" 3527 - through ">=2.2.7 <3" 3528 - 3529 - keyv@^4.5.3: 3530 - version "4.5.4" 3531 - resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz" 3532 - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== 3533 - dependencies: 3534 - json-buffer "3.0.1" 3535 - 3536 - kind-of@^6.0.3: 3537 - version "6.0.3" 3538 - resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" 3539 - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== 3540 - 3541 - kleur@^3.0.3: 3542 - version "3.0.3" 3543 - resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" 3544 - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== 3545 - 3546 - leven@^3.1.0: 3547 - version "3.1.0" 3548 - resolved "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" 3549 - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== 3550 - 3551 - levn@^0.4.1: 3552 - version "0.4.1" 3553 - resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" 3554 - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== 3555 - dependencies: 3556 - prelude-ls "^1.2.1" 3557 - type-check "~0.4.0" 3558 - 3559 - lilconfig@2.1.0: 3560 - version "2.1.0" 3561 - resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz" 3562 - integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== 3563 - 3564 - lines-and-columns@^1.1.6: 3565 - version "1.2.4" 3566 - resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" 3567 - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== 3568 - 3569 - linkedom@^0.18.12, linkedom@^0.18.9: 3570 - version "0.18.12" 3571 - resolved "https://registry.npmjs.org/linkedom/-/linkedom-0.18.12.tgz" 3572 - integrity sha512-jalJsOwIKuQJSeTvsgzPe9iJzyfVaEJiEXl+25EkKevsULHvMJzpNqwvj1jOESWdmgKDiXObyjOYwlUqG7wo1Q== 3573 - dependencies: 3574 - css-select "^5.1.0" 3575 - cssom "^0.5.0" 3576 - html-escaper "^3.0.3" 3577 - htmlparser2 "^10.0.0" 3578 - uhyphen "^0.2.0" 3579 - 3580 - linkify-it@^5.0.0: 3581 - version "5.0.0" 3582 - resolved "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz" 3583 - integrity sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ== 3584 - dependencies: 3585 - uc.micro "^2.0.0" 3586 - 3587 - lint-staged@^13.2.2: 3588 - version "13.3.0" 3589 - resolved "https://registry.npmjs.org/lint-staged/-/lint-staged-13.3.0.tgz" 3590 - integrity sha512-mPRtrYnipYYv1FEE134ufbWpeggNTo+O/UPzngoaKzbzHAthvR55am+8GfHTnqNRQVRRrYQLGW9ZyUoD7DsBHQ== 3591 - dependencies: 3592 - chalk "5.3.0" 3593 - commander "11.0.0" 3594 - debug "4.3.4" 3595 - execa "7.2.0" 3596 - lilconfig "2.1.0" 3597 - listr2 "6.6.1" 3598 - micromatch "4.0.5" 3599 - pidtree "0.6.0" 3600 - string-argv "0.3.2" 3601 - yaml "2.3.1" 3602 - 3603 - listr2@6.6.1: 3604 - version "6.6.1" 3605 - resolved "https://registry.npmjs.org/listr2/-/listr2-6.6.1.tgz" 3606 - integrity sha512-+rAXGHh0fkEWdXBmX+L6mmfmXmXvDGEKzkjxO+8mP3+nI/r/CWznVBvsibXdxda9Zz0OW2e2ikphN3OwCT/jSg== 3607 - dependencies: 3608 - cli-truncate "^3.1.0" 3609 - colorette "^2.0.20" 3610 - eventemitter3 "^5.0.1" 3611 - log-update "^5.0.1" 3612 - rfdc "^1.3.0" 3613 - wrap-ansi "^8.1.0" 3614 - 3615 - locate-path@^5.0.0: 3616 - version "5.0.0" 3617 - resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" 3618 - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== 3619 - dependencies: 3620 - p-locate "^4.1.0" 3621 - 3622 - locate-path@^6.0.0: 3623 - version "6.0.0" 3624 - resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" 3625 - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 3626 - dependencies: 3627 - p-locate "^5.0.0" 3628 - 3629 - lodash.camelcase@^4.3.0: 3630 - version "4.3.0" 3631 - resolved "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz" 3632 - integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== 3633 - 3634 - lodash.isfunction@^3.0.9: 3635 - version "3.0.9" 3636 - resolved "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz" 3637 - integrity sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw== 3638 - 3639 - lodash.isplainobject@^4.0.6: 3640 - version "4.0.6" 3641 - resolved "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz" 3642 - integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== 3643 - 3644 - lodash.kebabcase@^4.1.1: 3645 - version "4.1.1" 3646 - resolved "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz" 3647 - integrity sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g== 3648 - 3649 - lodash.map@^4.5.1: 3650 - version "4.6.0" 3651 - resolved "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz" 3652 - integrity sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q== 3653 - 3654 - lodash.memoize@4.x: 3655 - version "4.1.2" 3656 - resolved "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz" 3657 - integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== 3658 - 3659 - lodash.merge@^4.6.2: 3660 - version "4.6.2" 3661 - resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" 3662 - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== 3663 - 3664 - lodash.mergewith@^4.6.2: 3665 - version "4.6.2" 3666 - resolved "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz" 3667 - integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== 3668 - 3669 - lodash.snakecase@^4.1.1: 3670 - version "4.1.1" 3671 - resolved "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz" 3672 - integrity sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw== 3673 - 3674 - lodash.startcase@^4.4.0: 3675 - version "4.4.0" 3676 - resolved "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz" 3677 - integrity sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg== 3678 - 3679 - lodash.uniq@^4.5.0: 3680 - version "4.5.0" 3681 - resolved "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz" 3682 - integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== 3683 - 3684 - lodash.upperfirst@^4.3.1: 3685 - version "4.3.1" 3686 - resolved "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz" 3687 - integrity sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg== 3688 - 3689 - lodash@^4.17.15, lodash@^4.17.21, lodash@4.17.21: 3690 - version "4.17.21" 3691 - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" 3692 - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 3693 - 3694 - log-symbols@^4.1.0: 3695 - version "4.1.0" 3696 - resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" 3697 - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== 3698 - dependencies: 3699 - chalk "^4.1.0" 3700 - is-unicode-supported "^0.1.0" 3701 - 3702 - log-update@^5.0.1: 3703 - version "5.0.1" 3704 - resolved "https://registry.npmjs.org/log-update/-/log-update-5.0.1.tgz" 3705 - integrity sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw== 3706 - dependencies: 3707 - ansi-escapes "^5.0.0" 3708 - cli-cursor "^4.0.0" 3709 - slice-ansi "^5.0.0" 3710 - strip-ansi "^7.0.1" 3711 - wrap-ansi "^8.0.1" 3712 - 3713 - longest@^2.0.1: 3714 - version "2.0.1" 3715 - resolved "https://registry.npmjs.org/longest/-/longest-2.0.1.tgz" 3716 - integrity sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q== 3717 - 3718 - lru-cache@^10.2.0: 3719 - version "10.2.2" 3720 - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz" 3721 - integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ== 3722 - 3723 - lru-cache@^5.1.1: 3724 - version "5.1.1" 3725 - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" 3726 - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== 3727 - dependencies: 3728 - yallist "^3.0.2" 3729 - 3730 - lru-cache@^6.0.0: 3731 - version "6.0.0" 3732 - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" 3733 - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== 3734 - dependencies: 3735 - yallist "^4.0.0" 3736 - 3737 - lunr@^2.3.9: 3738 - version "2.3.9" 3739 - resolved "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz" 3740 - integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== 3741 - 3742 - magic-string@^0.30.10: 3743 - version "0.30.10" 3744 - resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz" 3745 - integrity sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ== 3746 - dependencies: 3747 - "@jridgewell/sourcemap-codec" "^1.4.15" 3748 - 3749 - make-dir@^3.0.2: 3750 - version "3.1.0" 3751 - resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" 3752 - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== 3753 - dependencies: 3754 - semver "^6.0.0" 3755 - 3756 - make-dir@^4.0.0: 3757 - version "4.0.0" 3758 - resolved "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz" 3759 - integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== 3760 - dependencies: 3761 - semver "^7.5.3" 3762 - 3763 - make-error@^1.1.1, make-error@1.x: 3764 - version "1.3.6" 3765 - resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" 3766 - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== 3767 - 3768 - makeerror@1.0.12: 3769 - version "1.0.12" 3770 - resolved "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz" 3771 - integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== 3772 - dependencies: 3773 - tmpl "1.0.5" 3774 - 3775 - map-obj@^1.0.0: 3776 - version "1.0.1" 3777 - resolved "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz" 3778 - integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== 3779 - 3780 - map-obj@^4.0.0: 3781 - version "4.3.0" 3782 - resolved "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz" 3783 - integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== 3784 - 3785 - markdown-it@^14.1.0: 3786 - version "14.1.0" 3787 - resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz" 3788 - integrity sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg== 3789 - dependencies: 3790 - argparse "^2.0.1" 3791 - entities "^4.4.0" 3792 - linkify-it "^5.0.0" 3793 - mdurl "^2.0.0" 3794 - punycode.js "^2.3.1" 3795 - uc.micro "^2.1.0" 3796 - 3797 - math-intrinsics@^1.1.0: 3798 - version "1.1.0" 3799 - resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz" 3800 - integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== 3801 - 3802 - mdurl@^2.0.0: 3803 - version "2.0.0" 3804 - resolved "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz" 3805 - integrity sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w== 3806 - 3807 - meow@^8.0.0, meow@^8.1.2: 3808 - version "8.1.2" 3809 - resolved "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz" 3810 - integrity sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q== 3811 - dependencies: 3812 - "@types/minimist" "^1.2.0" 3813 - camelcase-keys "^6.2.2" 3814 - decamelize-keys "^1.1.0" 3815 - hard-rejection "^2.1.0" 3816 - minimist-options "4.1.0" 3817 - normalize-package-data "^3.0.0" 3818 - read-pkg-up "^7.0.1" 3819 - redent "^3.0.0" 3820 - trim-newlines "^3.0.0" 3821 - type-fest "^0.18.0" 3822 - yargs-parser "^20.2.3" 3823 - 3824 - merge-stream@^2.0.0: 3825 - version "2.0.0" 3826 - resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" 3827 - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== 3828 - 3829 - merge@^2.1.1: 3830 - version "2.1.1" 3831 - resolved "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz" 3832 - integrity sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w== 3833 - 3834 - merge2@^1.3.0, merge2@^1.4.1: 3835 - version "1.4.1" 3836 - resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" 3837 - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== 3838 - 3839 - micromatch@^4.0.2, micromatch@^4.0.4: 3840 - version "4.0.7" 3841 - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz" 3842 - integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== 3843 - dependencies: 3844 - braces "^3.0.3" 3845 - picomatch "^2.3.1" 3846 - 3847 - micromatch@4.0.5: 3848 - version "4.0.5" 3849 - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz" 3850 - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== 3851 - dependencies: 3852 - braces "^3.0.2" 3853 - picomatch "^2.3.1" 3854 - 3855 - mime-db@1.52.0: 3856 - version "1.52.0" 3857 - resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" 3858 - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 3859 - 3860 - mime-types@^2.1.12: 3861 - version "2.1.35" 3862 - resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" 3863 - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 3864 - dependencies: 3865 - mime-db "1.52.0" 3866 - 3867 - mimic-fn@^2.1.0: 3868 - version "2.1.0" 3869 - resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" 3870 - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== 3871 - 3872 - mimic-fn@^4.0.0: 3873 - version "4.0.0" 3874 - resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz" 3875 - integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== 3876 - 3877 - min-indent@^1.0.0: 3878 - version "1.0.1" 3879 - resolved "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz" 3880 - integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== 3881 - 3882 - minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: 3883 - version "3.1.2" 3884 - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" 3885 - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 3886 - dependencies: 3887 - brace-expansion "^1.1.7" 3888 - 3889 - minimatch@^9.0.4: 3890 - version "9.0.4" 3891 - resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz" 3892 - integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== 3893 - dependencies: 3894 - brace-expansion "^2.0.1" 3895 - 3896 - minimatch@^9.0.5: 3897 - version "9.0.5" 3898 - resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz" 3899 - integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== 3900 - dependencies: 3901 - brace-expansion "^2.0.1" 3902 - 3903 - minimist-options@4.1.0: 3904 - version "4.1.0" 3905 - resolved "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz" 3906 - integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== 3907 - dependencies: 3908 - arrify "^1.0.1" 3909 - is-plain-obj "^1.1.0" 3910 - kind-of "^6.0.3" 3911 - 3912 - minimist@^1.2.6: 3913 - version "1.2.8" 3914 - resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" 3915 - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== 3916 - 3917 - minimist@1.2.7: 3918 - version "1.2.7" 3919 - resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz" 3920 - integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== 3921 - 3922 - "minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: 3923 - version "7.1.2" 3924 - resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz" 3925 - integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== 3926 - 3927 - ms@^2.1.3: 3928 - version "2.1.3" 3929 - resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" 3930 - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 3931 - 3932 - ms@2.1.2: 3933 - version "2.1.2" 3934 - resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" 3935 - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 3936 - 3937 - mute-stream@0.0.8: 3938 - version "0.0.8" 3939 - resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz" 3940 - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== 3941 - 3942 - natural-compare-lite@^1.4.0: 3943 - version "1.4.0" 3944 - resolved "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz" 3945 - integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== 3946 - 3947 - natural-compare@^1.4.0: 3948 - version "1.4.0" 3949 - resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" 3950 - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== 3951 - 3952 - node-fetch@^2.6.12: 3953 - version "2.7.0" 3954 - resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz" 3955 - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== 3956 - dependencies: 3957 - whatwg-url "^5.0.0" 3958 - 3959 - node-int64@^0.4.0: 3960 - version "0.4.0" 3961 - resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz" 3962 - integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== 3963 - 3964 - node-releases@^2.0.21: 3965 - version "2.0.21" 3966 - resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz" 3967 - integrity sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw== 3968 - 3969 - normalize-package-data@^2.5.0: 3970 - version "2.5.0" 3971 - resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz" 3972 - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== 3973 - dependencies: 3974 - hosted-git-info "^2.1.4" 3975 - resolve "^1.10.0" 3976 - semver "2 || 3 || 4 || 5" 3977 - validate-npm-package-license "^3.0.1" 3978 - 3979 - normalize-package-data@^3.0.0: 3980 - version "3.0.3" 3981 - resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz" 3982 - integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA== 3983 - dependencies: 3984 - hosted-git-info "^4.0.1" 3985 - is-core-module "^2.5.0" 3986 - semver "^7.3.4" 3987 - validate-npm-package-license "^3.0.1" 3988 - 3989 - normalize-path@^3.0.0: 3990 - version "3.0.0" 3991 - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" 3992 - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 3993 - 3994 - npm-run-path@^4.0.1: 3995 - version "4.0.1" 3996 - resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" 3997 - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== 3998 - dependencies: 3999 - path-key "^3.0.0" 4000 - 4001 - npm-run-path@^5.1.0: 4002 - version "5.3.0" 4003 - resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz" 4004 - integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ== 4005 - dependencies: 4006 - path-key "^4.0.0" 4007 - 4008 - nth-check@^2.0.1: 4009 - version "2.1.1" 4010 - resolved "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz" 4011 - integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== 4012 - dependencies: 4013 - boolbase "^1.0.0" 4014 - 4015 - object-assign@^4.0.1: 4016 - version "4.1.1" 4017 - resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" 4018 - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== 4019 - 4020 - object-keys@^1.1.1: 4021 - version "1.1.1" 4022 - resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" 4023 - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== 4024 - 4025 - once@^1.3.0: 4026 - version "1.4.0" 4027 - resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" 4028 - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== 4029 - dependencies: 4030 - wrappy "1" 4031 - 4032 - onetime@^5.1.0, onetime@^5.1.2: 4033 - version "5.1.2" 4034 - resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" 4035 - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== 4036 - dependencies: 4037 - mimic-fn "^2.1.0" 4038 - 4039 - onetime@^6.0.0: 4040 - version "6.0.0" 4041 - resolved "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz" 4042 - integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== 4043 - dependencies: 4044 - mimic-fn "^4.0.0" 4045 - 4046 - optionator@^0.9.3: 4047 - version "0.9.4" 4048 - resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz" 4049 - integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== 4050 - dependencies: 4051 - deep-is "^0.1.3" 4052 - fast-levenshtein "^2.0.6" 4053 - levn "^0.4.1" 4054 - prelude-ls "^1.2.1" 4055 - type-check "^0.4.0" 4056 - word-wrap "^1.2.5" 4057 - 4058 - ora@^5.4.1: 4059 - version "5.4.1" 4060 - resolved "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz" 4061 - integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== 4062 - dependencies: 4063 - bl "^4.1.0" 4064 - chalk "^4.1.0" 4065 - cli-cursor "^3.1.0" 4066 - cli-spinners "^2.5.0" 4067 - is-interactive "^1.0.0" 4068 - is-unicode-supported "^0.1.0" 4069 - log-symbols "^4.1.0" 4070 - strip-ansi "^6.0.0" 4071 - wcwidth "^1.0.1" 4072 - 4073 - os-tmpdir@~1.0.2: 4074 - version "1.0.2" 4075 - resolved "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" 4076 - integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== 4077 - 4078 - otpauth@^9.2.2: 4079 - version "9.3.1" 4080 - resolved "https://registry.npmjs.org/otpauth/-/otpauth-9.3.1.tgz" 4081 - integrity sha512-E6d2tMxPofHNk4sRFp+kqW7vQ+WJGO9VLI2N/W00DnI+ThskU12Qa10kyNSGklrzhN5c+wRUsN4GijVgCU2N9w== 4082 - dependencies: 4083 - "@noble/hashes" "1.4.0" 4084 - 4085 - p-limit@^2.2.0: 4086 - version "2.3.0" 4087 - resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" 4088 - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== 4089 - dependencies: 4090 - p-try "^2.0.0" 4091 - 4092 - p-limit@^3.0.2, p-limit@^3.1.0: 4093 - version "3.1.0" 4094 - resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" 4095 - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 4096 - dependencies: 4097 - yocto-queue "^0.1.0" 4098 - 4099 - p-locate@^4.1.0: 4100 - version "4.1.0" 4101 - resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" 4102 - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== 4103 - dependencies: 4104 - p-limit "^2.2.0" 4105 - 4106 - p-locate@^5.0.0: 4107 - version "5.0.0" 4108 - resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" 4109 - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 4110 - dependencies: 4111 - p-limit "^3.0.2" 4112 - 4113 - p-try@^2.0.0: 4114 - version "2.2.0" 4115 - resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" 4116 - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== 4117 - 4118 - parent-module@^1.0.0: 4119 - version "1.0.1" 4120 - resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" 4121 - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== 4122 - dependencies: 4123 - callsites "^3.0.0" 4124 - 4125 - parse-json@^5.0.0, parse-json@^5.2.0: 4126 - version "5.2.0" 4127 - resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" 4128 - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== 4129 - dependencies: 4130 - "@babel/code-frame" "^7.0.0" 4131 - error-ex "^1.3.1" 4132 - json-parse-even-better-errors "^2.3.0" 4133 - lines-and-columns "^1.1.6" 4134 - 4135 - parse-passwd@^1.0.0: 4136 - version "1.0.0" 4137 - resolved "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz" 4138 - integrity sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q== 4139 - 4140 - path-exists@^4.0.0: 4141 - version "4.0.0" 4142 - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" 4143 - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 4144 - 4145 - path-is-absolute@^1.0.0: 4146 - version "1.0.1" 4147 - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" 4148 - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== 4149 - 4150 - path-key@^3.0.0, path-key@^3.1.0: 4151 - version "3.1.1" 4152 - resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" 4153 - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 4154 - 4155 - path-key@^4.0.0: 4156 - version "4.0.0" 4157 - resolved "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz" 4158 - integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== 4159 - 4160 - path-parse@^1.0.7: 4161 - version "1.0.7" 4162 - resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" 4163 - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 4164 - 4165 - path-scurry@^1.11.1: 4166 - version "1.11.1" 4167 - resolved "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz" 4168 - integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== 4169 - dependencies: 4170 - lru-cache "^10.2.0" 4171 - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" 4172 - 4173 - path-type@^4.0.0: 4174 - version "4.0.0" 4175 - resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" 4176 - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== 4177 - 4178 - picocolors@^1.1.1: 4179 - version "1.1.1" 4180 - resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" 4181 - integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== 4182 - 4183 - picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: 4184 - version "2.3.1" 4185 - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" 4186 - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 4187 - 4188 - pidtree@0.6.0: 4189 - version "0.6.0" 4190 - resolved "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz" 4191 - integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== 4192 - 4193 - pify@^2.0.0: 4194 - version "2.3.0" 4195 - resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" 4196 - integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== 4197 - 4198 - pinkie-promise@^2.0.0: 4199 - version "2.0.1" 4200 - resolved "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" 4201 - integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== 4202 - dependencies: 4203 - pinkie "^2.0.0" 4204 - 4205 - pinkie@^2.0.0: 4206 - version "2.0.4" 4207 - resolved "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" 4208 - integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== 4209 - 4210 - pirates@^4.0.4: 4211 - version "4.0.7" 4212 - resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz" 4213 - integrity sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA== 4214 - 4215 - pkg-dir@^4.1.0, pkg-dir@^4.2.0: 4216 - version "4.2.0" 4217 - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" 4218 - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== 4219 - dependencies: 4220 - find-up "^4.0.0" 4221 - 4222 - prelude-ls@^1.2.1: 4223 - version "1.2.1" 4224 - resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" 4225 - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== 4226 - 4227 - prettier-linter-helpers@^1.0.0: 4228 - version "1.0.0" 4229 - resolved "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz" 4230 - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== 4231 - dependencies: 4232 - fast-diff "^1.1.2" 4233 - 4234 - prettier@^2.8.8, prettier@>=2.0.0: 4235 - version "2.8.8" 4236 - resolved "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz" 4237 - integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== 4238 - 4239 - pretty-format@^29.0.0, pretty-format@^29.7.0: 4240 - version "29.7.0" 4241 - resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz" 4242 - integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== 4243 - dependencies: 4244 - "@jest/schemas" "^29.6.3" 4245 - ansi-styles "^5.0.0" 4246 - react-is "^18.0.0" 4247 - 4248 - prompts@^2.0.1: 4249 - version "2.4.2" 4250 - resolved "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz" 4251 - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== 4252 - dependencies: 4253 - kleur "^3.0.3" 4254 - sisteransi "^1.0.5" 4255 - 4256 - psl@^1.1.33: 4257 - version "1.9.0" 4258 - resolved "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz" 4259 - integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== 4260 - 4261 - punycode.js@^2.3.1: 4262 - version "2.3.1" 4263 - resolved "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz" 4264 - integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA== 4265 - 4266 - punycode@^2.1.0, punycode@^2.1.1: 4267 - version "2.3.1" 4268 - resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz" 4269 - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== 4270 - 4271 - pure-rand@^6.0.0: 4272 - version "6.1.0" 4273 - resolved "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz" 4274 - integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== 4275 - 4276 - querystringify@^2.1.1: 4277 - version "2.2.0" 4278 - resolved "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz" 4279 - integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== 4280 - 4281 - queue-microtask@^1.2.2: 4282 - version "1.2.3" 4283 - resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" 4284 - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== 4285 - 4286 - quick-lru@^4.0.1: 4287 - version "4.0.1" 4288 - resolved "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz" 4289 - integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== 4290 - 4291 - react-is@^18.0.0: 4292 - version "18.3.1" 4293 - resolved "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz" 4294 - integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== 4295 - 4296 - read-pkg-up@^7.0.1: 4297 - version "7.0.1" 4298 - resolved "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz" 4299 - integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== 4300 - dependencies: 4301 - find-up "^4.1.0" 4302 - read-pkg "^5.2.0" 4303 - type-fest "^0.8.1" 4304 - 4305 - read-pkg@^5.2.0: 4306 - version "5.2.0" 4307 - resolved "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz" 4308 - integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== 4309 - dependencies: 4310 - "@types/normalize-package-data" "^2.4.0" 4311 - normalize-package-data "^2.5.0" 4312 - parse-json "^5.0.0" 4313 - type-fest "^0.6.0" 4314 - 4315 - readable-stream@^3.0.0, readable-stream@^3.4.0, readable-stream@3: 4316 - version "3.6.2" 4317 - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" 4318 - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== 4319 - dependencies: 4320 - inherits "^2.0.3" 4321 - string_decoder "^1.1.1" 4322 - util-deprecate "^1.0.1" 4323 - 4324 - redent@^3.0.0: 4325 - version "3.0.0" 4326 - resolved "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz" 4327 - integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== 4328 - dependencies: 4329 - indent-string "^4.0.0" 4330 - strip-indent "^3.0.0" 4331 - 4332 - require-directory@^2.1.1: 4333 - version "2.1.1" 4334 - resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" 4335 - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== 4336 - 4337 - require-from-string@^2.0.2: 4338 - version "2.0.2" 4339 - resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" 4340 - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== 4341 - 4342 - requires-port@^1.0.0: 4343 - version "1.0.0" 4344 - resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" 4345 - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== 4346 - 4347 - resolve-cwd@^3.0.0: 4348 - version "3.0.0" 4349 - resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz" 4350 - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== 4351 - dependencies: 4352 - resolve-from "^5.0.0" 4353 - 4354 - resolve-dir@^1.0.0, resolve-dir@^1.0.1: 4355 - version "1.0.1" 4356 - resolved "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz" 4357 - integrity sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg== 4358 - dependencies: 4359 - expand-tilde "^2.0.0" 4360 - global-modules "^1.0.0" 4361 - 4362 - resolve-from@^4.0.0: 4363 - version "4.0.0" 4364 - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" 4365 - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 4366 - 4367 - resolve-from@^5.0.0, resolve-from@5.0.0: 4368 - version "5.0.0" 4369 - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" 4370 - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== 4371 - 4372 - resolve-global@^1.0.0, resolve-global@1.0.0: 4373 - version "1.0.0" 4374 - resolved "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz" 4375 - integrity sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw== 4376 - dependencies: 4377 - global-dirs "^0.1.1" 4378 - 4379 - resolve-pkg-maps@^1.0.0: 4380 - version "1.0.0" 4381 - resolved "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz" 4382 - integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== 4383 - 4384 - resolve.exports@^2.0.0: 4385 - version "2.0.3" 4386 - resolved "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz" 4387 - integrity sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A== 4388 - 4389 - resolve@^1.10.0, resolve@^1.20.0: 4390 - version "1.22.10" 4391 - resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz" 4392 - integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== 4393 - dependencies: 4394 - is-core-module "^2.16.0" 4395 - path-parse "^1.0.7" 4396 - supports-preserve-symlinks-flag "^1.0.0" 4397 - 4398 - restore-cursor@^3.1.0: 4399 - version "3.1.0" 4400 - resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz" 4401 - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== 4402 - dependencies: 4403 - onetime "^5.1.0" 4404 - signal-exit "^3.0.2" 4405 - 4406 - restore-cursor@^4.0.0: 4407 - version "4.0.0" 4408 - resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz" 4409 - integrity sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg== 4410 - dependencies: 4411 - onetime "^5.1.0" 4412 - signal-exit "^3.0.2" 4413 - 4414 - reusify@^1.0.4: 4415 - version "1.0.4" 4416 - resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" 4417 - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== 4418 - 4419 - rfdc@^1.3.0: 4420 - version "1.4.1" 4421 - resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz" 4422 - integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== 4423 - 4424 - rimraf@^3.0.2: 4425 - version "3.0.2" 4426 - resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" 4427 - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== 4428 - dependencies: 4429 - glob "^7.1.3" 4430 - 4431 - rimraf@^5.0.7: 4432 - version "5.0.7" 4433 - resolved "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz" 4434 - integrity sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg== 4435 - dependencies: 4436 - glob "^10.3.7" 4437 - 4438 - rollup-plugin-dts@^6.1.1: 4439 - version "6.1.1" 4440 - resolved "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-6.1.1.tgz" 4441 - integrity sha512-aSHRcJ6KG2IHIioYlvAOcEq6U99sVtqDDKVhnwt70rW6tsz3tv5OSjEiWcgzfsHdLyGXZ/3b/7b/+Za3Y6r1XA== 4442 - dependencies: 4443 - magic-string "^0.30.10" 4444 - optionalDependencies: 4445 - "@babel/code-frame" "^7.24.2" 4446 - 4447 - rollup-plugin-esbuild@^6.1.1: 4448 - version "6.1.1" 4449 - resolved "https://registry.npmjs.org/rollup-plugin-esbuild/-/rollup-plugin-esbuild-6.1.1.tgz" 4450 - integrity sha512-CehMY9FAqJD5OUaE/Mi1r5z0kNeYxItmRO2zG4Qnv2qWKF09J2lTy5GUzjJR354ZPrLkCj4fiBN41lo8PzBUhw== 4451 - dependencies: 4452 - "@rollup/pluginutils" "^5.0.5" 4453 - debug "^4.3.4" 4454 - es-module-lexer "^1.3.1" 4455 - get-tsconfig "^4.7.2" 4456 - 4457 - "rollup@^1.20.0 || ^2.0.0 || ^3.0.0 || ^4.0.0", rollup@^1.20.0||^2.0.0||^3.0.0||^4.0.0, "rollup@^3.29.4 || ^4", rollup@^4.18.0: 4458 - version "4.18.0" 4459 - resolved "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz" 4460 - integrity sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg== 4461 - dependencies: 4462 - "@types/estree" "1.0.5" 4463 - optionalDependencies: 4464 - "@rollup/rollup-android-arm-eabi" "4.18.0" 4465 - "@rollup/rollup-android-arm64" "4.18.0" 4466 - "@rollup/rollup-darwin-arm64" "4.18.0" 4467 - "@rollup/rollup-darwin-x64" "4.18.0" 4468 - "@rollup/rollup-linux-arm-gnueabihf" "4.18.0" 4469 - "@rollup/rollup-linux-arm-musleabihf" "4.18.0" 4470 - "@rollup/rollup-linux-arm64-gnu" "4.18.0" 4471 - "@rollup/rollup-linux-arm64-musl" "4.18.0" 4472 - "@rollup/rollup-linux-powerpc64le-gnu" "4.18.0" 4473 - "@rollup/rollup-linux-riscv64-gnu" "4.18.0" 4474 - "@rollup/rollup-linux-s390x-gnu" "4.18.0" 4475 - "@rollup/rollup-linux-x64-gnu" "4.18.0" 4476 - "@rollup/rollup-linux-x64-musl" "4.18.0" 4477 - "@rollup/rollup-win32-arm64-msvc" "4.18.0" 4478 - "@rollup/rollup-win32-ia32-msvc" "4.18.0" 4479 - "@rollup/rollup-win32-x64-msvc" "4.18.0" 4480 - fsevents "~2.3.2" 4481 - 4482 - run-async@^2.4.0: 4483 - version "2.4.1" 4484 - resolved "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz" 4485 - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== 4486 - 4487 - run-parallel@^1.1.9: 4488 - version "1.2.0" 4489 - resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" 4490 - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== 4491 - dependencies: 4492 - queue-microtask "^1.2.2" 4493 - 4494 - rxjs@^7.5.5: 4495 - version "7.8.1" 4496 - resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz" 4497 - integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== 4498 - dependencies: 4499 - tslib "^2.1.0" 4500 - 4501 - safe-buffer@~5.2.0: 4502 - version "5.2.1" 4503 - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" 4504 - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 4505 - 4506 - "safer-buffer@>= 2.1.2 < 3": 4507 - version "2.1.2" 4508 - resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" 4509 - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 4510 - 4511 - semver@^6.0.0: 4512 - version "6.3.1" 4513 - resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" 4514 - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== 4515 - 4516 - semver@^6.3.0: 4517 - version "6.3.1" 4518 - resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" 4519 - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== 4520 - 4521 - semver@^6.3.1: 4522 - version "6.3.1" 4523 - resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" 4524 - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== 4525 - 4526 - semver@^7.3.4, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4, semver@7.5.4: 4527 - version "7.5.4" 4528 - resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" 4529 - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== 4530 - dependencies: 4531 - lru-cache "^6.0.0" 4532 - 4533 - "semver@2 || 3 || 4 || 5": 4534 - version "5.7.2" 4535 - resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz" 4536 - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== 4537 - 4538 - set-cookie-parser@^2.6.0: 4539 - version "2.6.0" 4540 - resolved "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz" 4541 - integrity sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ== 4542 - 4543 - set-function-length@^1.2.1: 4544 - version "1.2.2" 4545 - resolved "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz" 4546 - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== 4547 - dependencies: 4548 - define-data-property "^1.1.4" 4549 - es-errors "^1.3.0" 4550 - function-bind "^1.1.2" 4551 - get-intrinsic "^1.2.4" 4552 - gopd "^1.0.1" 4553 - has-property-descriptors "^1.0.2" 4554 - 4555 - shebang-command@^2.0.0: 4556 - version "2.0.0" 4557 - resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" 4558 - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 4559 - dependencies: 4560 - shebang-regex "^3.0.0" 4561 - 4562 - shebang-regex@^3.0.0: 4563 - version "3.0.0" 4564 - resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" 4565 - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 4566 - 4567 - signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: 4568 - version "3.0.7" 4569 - resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" 4570 - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== 4571 - 4572 - signal-exit@^4.0.1: 4573 - version "4.1.0" 4574 - resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" 4575 - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== 4576 - 4577 - sisteransi@^1.0.5: 4578 - version "1.0.5" 4579 - resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" 4580 - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== 4581 - 4582 - slash@^3.0.0: 4583 - version "3.0.0" 4584 - resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" 4585 - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== 4586 - 4587 - slice-ansi@^5.0.0: 4588 - version "5.0.0" 4589 - resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz" 4590 - integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ== 4591 - dependencies: 4592 - ansi-styles "^6.0.0" 4593 - is-fullwidth-code-point "^4.0.0" 4594 - 4595 - source-map-support@0.5.13: 4596 - version "0.5.13" 4597 - resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz" 4598 - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== 4599 - dependencies: 4600 - buffer-from "^1.0.0" 4601 - source-map "^0.6.0" 4602 - 4603 - source-map@^0.6.0, source-map@^0.6.1: 4604 - version "0.6.1" 4605 - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" 4606 - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 4607 - 4608 - spdx-correct@^3.0.0: 4609 - version "3.2.0" 4610 - resolved "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz" 4611 - integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== 4612 - dependencies: 4613 - spdx-expression-parse "^3.0.0" 4614 - spdx-license-ids "^3.0.0" 4615 - 4616 - spdx-exceptions@^2.1.0: 4617 - version "2.5.0" 4618 - resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz" 4619 - integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== 4620 - 4621 - spdx-expression-parse@^3.0.0: 4622 - version "3.0.1" 4623 - resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz" 4624 - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== 4625 - dependencies: 4626 - spdx-exceptions "^2.1.0" 4627 - spdx-license-ids "^3.0.0" 4628 - 4629 - spdx-license-ids@^3.0.0: 4630 - version "3.0.18" 4631 - resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz" 4632 - integrity sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ== 4633 - 4634 - split2@^3.0.0, split2@^3.2.2: 4635 - version "3.2.2" 4636 - resolved "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz" 4637 - integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg== 4638 - dependencies: 4639 - readable-stream "^3.0.0" 4640 - 4641 - sprintf-js@~1.0.2: 4642 - version "1.0.3" 4643 - resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" 4644 - integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== 4645 - 4646 - stack-utils@^2.0.3: 4647 - version "2.0.6" 4648 - resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz" 4649 - integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== 4650 - dependencies: 4651 - escape-string-regexp "^2.0.0" 4652 - 4653 - string_decoder@^1.1.1: 4654 - version "1.3.0" 4655 - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" 4656 - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== 4657 - dependencies: 4658 - safe-buffer "~5.2.0" 4659 - 4660 - string-argv@0.3.2: 4661 - version "0.3.2" 4662 - resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz" 4663 - integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== 4664 - 4665 - string-length@^4.0.1: 4666 - version "4.0.2" 4667 - resolved "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz" 4668 - integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== 4669 - dependencies: 4670 - char-regex "^1.0.2" 4671 - strip-ansi "^6.0.0" 4672 - 4673 - "string-width-cjs@npm:string-width@^4.2.0": 4674 - version "4.2.3" 4675 - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" 4676 - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 4677 - dependencies: 4678 - emoji-regex "^8.0.0" 4679 - is-fullwidth-code-point "^3.0.0" 4680 - strip-ansi "^6.0.1" 4681 - 4682 - string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: 4683 - version "4.2.3" 4684 - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" 4685 - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 4686 - dependencies: 4687 - emoji-regex "^8.0.0" 4688 - is-fullwidth-code-point "^3.0.0" 4689 - strip-ansi "^6.0.1" 4690 - 4691 - string-width@^5.0.0: 4692 - version "5.1.2" 4693 - resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" 4694 - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== 4695 - dependencies: 4696 - eastasianwidth "^0.2.0" 4697 - emoji-regex "^9.2.2" 4698 - strip-ansi "^7.0.1" 4699 - 4700 - string-width@^5.0.1, string-width@^5.1.2: 4701 - version "5.1.2" 4702 - resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" 4703 - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== 4704 - dependencies: 4705 - eastasianwidth "^0.2.0" 4706 - emoji-regex "^9.2.2" 4707 - strip-ansi "^7.0.1" 4708 - 4709 - "strip-ansi-cjs@npm:strip-ansi@^6.0.1": 4710 - version "6.0.1" 4711 - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" 4712 - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 4713 - dependencies: 4714 - ansi-regex "^5.0.1" 4715 - 4716 - strip-ansi@^6.0.0, strip-ansi@^6.0.1: 4717 - version "6.0.1" 4718 - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" 4719 - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 4720 - dependencies: 4721 - ansi-regex "^5.0.1" 4722 - 4723 - strip-ansi@^7.0.1: 4724 - version "7.1.0" 4725 - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz" 4726 - integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== 4727 - dependencies: 4728 - ansi-regex "^6.0.1" 4729 - 4730 - strip-bom@^4.0.0, strip-bom@4.0.0: 4731 - version "4.0.0" 4732 - resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz" 4733 - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== 4734 - 4735 - strip-final-newline@^2.0.0: 4736 - version "2.0.0" 4737 - resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" 4738 - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== 4739 - 4740 - strip-final-newline@^3.0.0: 4741 - version "3.0.0" 4742 - resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz" 4743 - integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== 4744 - 4745 - strip-indent@^3.0.0: 4746 - version "3.0.0" 4747 - resolved "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz" 4748 - integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== 4749 - dependencies: 4750 - min-indent "^1.0.0" 4751 - 4752 - strip-json-comments@^3.1.1, strip-json-comments@3.1.1: 4753 - version "3.1.1" 4754 - resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" 4755 - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 4756 - 4757 - strip-outer@^1.0.1: 4758 - version "1.0.1" 4759 - resolved "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz" 4760 - integrity sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg== 4761 - dependencies: 4762 - escape-string-regexp "^1.0.2" 4763 - 4764 - supports-color@^5.3.0: 4765 - version "5.5.0" 4766 - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" 4767 - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 4768 - dependencies: 4769 - has-flag "^3.0.0" 4770 - 4771 - supports-color@^7.1.0: 4772 - version "7.2.0" 4773 - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" 4774 - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 4775 - dependencies: 4776 - has-flag "^4.0.0" 4777 - 4778 - supports-color@^8.0.0: 4779 - version "8.1.1" 4780 - resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" 4781 - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== 4782 - dependencies: 4783 - has-flag "^4.0.0" 4784 - 4785 - supports-preserve-symlinks-flag@^1.0.0: 4786 - version "1.0.0" 4787 - resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" 4788 - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== 4789 - 4790 - test-exclude@^6.0.0: 4791 - version "6.0.0" 4792 - resolved "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz" 4793 - integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== 4794 - dependencies: 4795 - "@istanbuljs/schema" "^0.1.2" 4796 - glob "^7.1.4" 4797 - minimatch "^3.0.4" 4798 - 4799 - text-extensions@^1.0.0: 4800 - version "1.9.0" 4801 - resolved "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz" 4802 - integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== 4803 - 4804 - text-table@^0.2.0: 4805 - version "0.2.0" 4806 - resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" 4807 - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== 4808 - 4809 - through@^2.3.6, "through@>=2.2.7 <3": 4810 - version "2.3.8" 4811 - resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" 4812 - integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== 4813 - 4814 - through2@^4.0.0: 4815 - version "4.0.2" 4816 - resolved "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz" 4817 - integrity sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw== 4818 - dependencies: 4819 - readable-stream "3" 4820 - 4821 - tmp@^0.0.33: 4822 - version "0.0.33" 4823 - resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" 4824 - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== 4825 - dependencies: 4826 - os-tmpdir "~1.0.2" 4827 - 4828 - tmpl@1.0.5: 4829 - version "1.0.5" 4830 - resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz" 4831 - integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== 4832 - 4833 - to-regex-range@^5.0.1: 4834 - version "5.0.1" 4835 - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" 4836 - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 4837 - dependencies: 4838 - is-number "^7.0.0" 4839 - 4840 - tough-cookie@^4.1.2: 4841 - version "4.1.4" 4842 - resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz" 4843 - integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== 4844 - dependencies: 4845 - psl "^1.1.33" 4846 - punycode "^2.1.1" 4847 - universalify "^0.2.0" 4848 - url-parse "^1.5.3" 4849 - 4850 - tr46@~0.0.3: 4851 - version "0.0.3" 4852 - resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" 4853 - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== 4854 - 4855 - trim-newlines@^3.0.0: 4856 - version "3.0.1" 4857 - resolved "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz" 4858 - integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== 4859 - 4860 - trim-repeated@^1.0.0: 4861 - version "1.0.0" 4862 - resolved "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz" 4863 - integrity sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg== 4864 - dependencies: 4865 - escape-string-regexp "^1.0.2" 4866 - 4867 - ts-jest@^29.1.0: 4868 - version "29.1.5" 4869 - resolved "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.5.tgz" 4870 - integrity sha512-UuClSYxM7byvvYfyWdFI+/2UxMmwNyJb0NPkZPQE2hew3RurV7l7zURgOHAd/1I1ZdPpe3GUsXNXAcN8TFKSIg== 4871 - dependencies: 4872 - bs-logger "0.x" 4873 - fast-json-stable-stringify "2.x" 4874 - jest-util "^29.0.0" 4875 - json5 "^2.2.3" 4876 - lodash.memoize "4.x" 4877 - make-error "1.x" 4878 - semver "^7.5.3" 4879 - yargs-parser "^21.0.1" 4880 - 4881 - ts-node@^10.8.1, ts-node@>=10, ts-node@>=9.0.0: 4882 - version "10.9.2" 4883 - resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz" 4884 - integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== 4885 - dependencies: 4886 - "@cspotcode/source-map-support" "^0.8.0" 4887 - "@tsconfig/node10" "^1.0.7" 4888 - "@tsconfig/node12" "^1.0.7" 4889 - "@tsconfig/node14" "^1.0.0" 4890 - "@tsconfig/node16" "^1.0.2" 4891 - acorn "^8.4.1" 4892 - acorn-walk "^8.1.1" 4893 - arg "^4.1.0" 4894 - create-require "^1.1.0" 4895 - diff "^4.0.1" 4896 - make-error "^1.1.1" 4897 - v8-compile-cache-lib "^3.0.1" 4898 - yn "3.1.1" 4899 - 4900 - tslib@^1.8.1: 4901 - version "1.14.1" 4902 - resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" 4903 - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== 4904 - 4905 - tslib@^2.1.0, tslib@^2.5.2: 4906 - version "2.6.3" 4907 - resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz" 4908 - integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== 4909 - 4910 - tsutils@^3.21.0: 4911 - version "3.21.0" 4912 - resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz" 4913 - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== 4914 - dependencies: 4915 - tslib "^1.8.1" 4916 - 4917 - type-check@^0.4.0, type-check@~0.4.0: 4918 - version "0.4.0" 4919 - resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" 4920 - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== 4921 - dependencies: 4922 - prelude-ls "^1.2.1" 4923 - 4924 - type-detect@4.0.8: 4925 - version "4.0.8" 4926 - resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" 4927 - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== 4928 - 4929 - type-fest@^0.18.0: 4930 - version "0.18.1" 4931 - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz" 4932 - integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== 4933 - 4934 - type-fest@^0.20.2: 4935 - version "0.20.2" 4936 - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" 4937 - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== 4938 - 4939 - type-fest@^0.21.3: 4940 - version "0.21.3" 4941 - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" 4942 - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== 4943 - 4944 - type-fest@^0.6.0: 4945 - version "0.6.0" 4946 - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz" 4947 - integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== 4948 - 4949 - type-fest@^0.8.1: 4950 - version "0.8.1" 4951 - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz" 4952 - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== 4953 - 4954 - type-fest@^1.0.2: 4955 - version "1.4.0" 4956 - resolved "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz" 4957 - integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== 4958 - 4959 - typedoc@^0.27.6: 4960 - version "0.27.6" 4961 - resolved "https://registry.npmjs.org/typedoc/-/typedoc-0.27.6.tgz" 4962 - integrity sha512-oBFRoh2Px6jFx366db0lLlihcalq/JzyCVp7Vaq1yphL/tbgx2e+bkpkCgJPunaPvPwoTOXSwasfklWHm7GfAw== 4963 - dependencies: 4964 - "@gerrit0/mini-shiki" "^1.24.0" 4965 - lunr "^2.3.9" 4966 - markdown-it "^14.1.0" 4967 - minimatch "^9.0.5" 4968 - yaml "^2.6.1" 4969 - 4970 - "typescript@^4.5 || ^5.0", "typescript@^4.6.4 || ^5.2.2", typescript@^5.0.4, typescript@>=2.7, "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta", typescript@>=4, "typescript@>=4.3 <6", typescript@>=4.9.5, "typescript@5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x": 4971 - version "5.4.5" 4972 - resolved "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz" 4973 - integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== 4974 - 4975 - uc.micro@^2.0.0, uc.micro@^2.1.0: 4976 - version "2.1.0" 4977 - resolved "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz" 4978 - integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A== 4979 - 4980 - uhyphen@^0.2.0: 4981 - version "0.2.0" 4982 - resolved "https://registry.npmjs.org/uhyphen/-/uhyphen-0.2.0.tgz" 4983 - integrity sha512-qz3o9CHXmJJPGBdqzab7qAYuW8kQGKNEuoHFYrBwV6hWIMcpAmxDLXojcHfFr9US1Pe6zUswEIJIbLI610fuqA== 4984 - 4985 - undici-types@~6.21.0: 4986 - version "6.21.0" 4987 - resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz" 4988 - integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== 4989 - 4990 - universalify@^0.1.0: 4991 - version "0.1.2" 4992 - resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz" 4993 - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== 4994 - 4995 - universalify@^0.2.0: 4996 - version "0.2.0" 4997 - resolved "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz" 4998 - integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== 4999 - 5000 - universalify@^2.0.0: 5001 - version "2.0.1" 5002 - resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz" 5003 - integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== 5004 - 5005 - update-browserslist-db@^1.1.3: 5006 - version "1.1.3" 5007 - resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz" 5008 - integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== 5009 - dependencies: 5010 - escalade "^3.2.0" 5011 - picocolors "^1.1.1" 5012 - 5013 - uri-js@^4.2.2, uri-js@^4.4.1: 5014 - version "4.4.1" 5015 - resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" 5016 - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 5017 - dependencies: 5018 - punycode "^2.1.0" 5019 - 5020 - url-parse@^1.5.3: 5021 - version "1.5.10" 5022 - resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz" 5023 - integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== 5024 - dependencies: 5025 - querystringify "^2.1.1" 5026 - requires-port "^1.0.0" 5027 - 5028 - util-deprecate@^1.0.1: 5029 - version "1.0.2" 5030 - resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" 5031 - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== 5032 - 5033 - v8-compile-cache-lib@^3.0.1: 5034 - version "3.0.1" 5035 - resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" 5036 - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== 5037 - 5038 - v8-to-istanbul@^9.0.1: 5039 - version "9.2.0" 5040 - resolved "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz" 5041 - integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== 5042 - dependencies: 5043 - "@jridgewell/trace-mapping" "^0.3.12" 5044 - "@types/istanbul-lib-coverage" "^2.0.1" 5045 - convert-source-map "^2.0.0" 5046 - 5047 - validate-npm-package-license@^3.0.1: 5048 - version "3.0.4" 5049 - resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz" 5050 - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== 5051 - dependencies: 5052 - spdx-correct "^3.0.0" 5053 - spdx-expression-parse "^3.0.0" 5054 - 5055 - walker@^1.0.8: 5056 - version "1.0.8" 5057 - resolved "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz" 5058 - integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== 5059 - dependencies: 5060 - makeerror "1.0.12" 5061 - 5062 - wcwidth@^1.0.1: 5063 - version "1.0.1" 5064 - resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz" 5065 - integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== 5066 - dependencies: 5067 - defaults "^1.0.3" 5068 - 5069 - webidl-conversions@^3.0.0: 5070 - version "3.0.1" 5071 - resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" 5072 - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== 5073 - 5074 - whatwg-url@^5.0.0: 5075 - version "5.0.0" 5076 - resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" 5077 - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== 5078 - dependencies: 5079 - tr46 "~0.0.3" 5080 - webidl-conversions "^3.0.0" 5081 - 5082 - which@^1.2.14: 5083 - version "1.3.1" 5084 - resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz" 5085 - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 5086 - dependencies: 5087 - isexe "^2.0.0" 5088 - 5089 - which@^2.0.1: 5090 - version "2.0.2" 5091 - resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" 5092 - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 5093 - dependencies: 5094 - isexe "^2.0.0" 5095 - 5096 - word-wrap@^1.0.3, word-wrap@^1.2.5: 5097 - version "1.2.5" 5098 - resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz" 5099 - integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== 5100 - 5101 - "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": 5102 - version "7.0.0" 5103 - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" 5104 - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 5105 - dependencies: 5106 - ansi-styles "^4.0.0" 5107 - string-width "^4.1.0" 5108 - strip-ansi "^6.0.0" 5109 - 5110 - wrap-ansi@^7.0.0: 5111 - version "7.0.0" 5112 - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" 5113 - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 5114 - dependencies: 5115 - ansi-styles "^4.0.0" 5116 - string-width "^4.1.0" 5117 - strip-ansi "^6.0.0" 5118 - 5119 - wrap-ansi@^8.0.1: 5120 - version "8.1.0" 5121 - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz" 5122 - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== 5123 - dependencies: 5124 - ansi-styles "^6.1.0" 5125 - string-width "^5.0.1" 5126 - strip-ansi "^7.0.1" 5127 - 5128 - wrap-ansi@^8.1.0: 5129 - version "8.1.0" 5130 - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz" 5131 - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== 5132 - dependencies: 5133 - ansi-styles "^6.1.0" 5134 - string-width "^5.0.1" 5135 - strip-ansi "^7.0.1" 5136 - 5137 - wrappy@1: 5138 - version "1.0.2" 5139 - resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" 5140 - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== 5141 - 5142 - write-file-atomic@^4.0.2: 5143 - version "4.0.2" 5144 - resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz" 5145 - integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== 5146 - dependencies: 5147 - imurmurhash "^0.1.4" 5148 - signal-exit "^3.0.7" 5149 - 5150 - ws@^8.17.0: 5151 - version "8.18.3" 5152 - resolved "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz" 5153 - integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== 5154 - 5155 - x-client-transaction-id@^0.1.9: 5156 - version "0.1.9" 5157 - resolved "https://registry.npmjs.org/x-client-transaction-id/-/x-client-transaction-id-0.1.9.tgz" 5158 - integrity sha512-CES4zgkJ0wbfFWm0qgdKphthyb+L7lVHymgOY15v6ivcWSx5p9lp5kzAed+BuqJSP7bS0GbQyJ16ONkRthgsUw== 5159 - dependencies: 5160 - linkedom "^0.18.9" 5161 - 5162 - y18n@^5.0.5: 5163 - version "5.0.8" 5164 - resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" 5165 - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== 5166 - 5167 - yallist@^3.0.2: 5168 - version "3.1.1" 5169 - resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" 5170 - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== 5171 - 5172 - yallist@^4.0.0: 5173 - version "4.0.0" 5174 - resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" 5175 - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 5176 - 5177 - yaml@^2.6.1: 5178 - version "2.7.0" 5179 - resolved "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz" 5180 - integrity sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA== 5181 - 5182 - yaml@2.3.1: 5183 - version "2.3.1" 5184 - resolved "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz" 5185 - integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== 5186 - 5187 - yargs-parser@^20.2.3: 5188 - version "20.2.9" 5189 - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz" 5190 - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== 5191 - 5192 - yargs-parser@^21.0.1: 5193 - version "21.1.1" 5194 - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" 5195 - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== 5196 - 5197 - yargs-parser@^21.1.1: 5198 - version "21.1.1" 5199 - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" 5200 - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== 5201 - 5202 - yargs@^17.0.0, yargs@^17.3.1: 5203 - version "17.7.2" 5204 - resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" 5205 - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== 5206 - dependencies: 5207 - cliui "^8.0.1" 5208 - escalade "^3.1.1" 5209 - get-caller-file "^2.0.5" 5210 - require-directory "^2.1.1" 5211 - string-width "^4.2.3" 5212 - y18n "^5.0.5" 5213 - yargs-parser "^21.1.1" 5214 - 5215 - yn@3.1.1: 5216 - version "3.1.1" 5217 - resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" 5218 - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== 5219 - 5220 - yocto-queue@^0.1.0: 5221 - version "0.1.0" 5222 - resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" 5223 - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==