diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 5ef04108..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,37 +0,0 @@ -module.exports = { - "env": { - "browser": false, - "es6": true, - "mocha": true, - "node": true - }, - "extends": [ - "google", - "eslint:recommended" - ], - "rules": { - "block-spacing": [2, "always"], - "brace-style": [2, "1tbs", { "allowSingleLine": true }], - "camelcase": [2, {properties: "never"}], - "comma-dangle": 0, - "curly": 0, - "key-spacing": [2, {align: "value"}], - "max-len": [1, 120], - "no-control-regex": 0, - "no-console": 1, - "no-empty": [2, { "allowEmptyCatch": true }], - "no-eval": 1, // we use it on purpose - "no-loop-func": 1, - "no-multi-spaces": 0, - "no-proto": 1, - "no-unused-expressions": 1, - "no-unused-vars": 1, - "no-var": 0, - "no-warning-comments": 0, - "prefer-rest-params": 0, - "prefer-spread": 0, - "quote-props": 1, - "quotes": [2, "single", {avoidEscape: true}], - "require-jsdoc": 0, - } -}; diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..df588d4c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,30 @@ +name: ci + +on: + push: + branches: [main, dev] + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + node: [20, 22, 24] + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: 10 + + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + cache: pnpm + + - run: pnpm install --frozen-lockfile + + - run: pnpm test + diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..398be9f7 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,46 @@ +name: release + +on: + push: + branches: [main] + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: 10 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + + - run: pnpm install --frozen-lockfile + + - name: build standalone binaries + run: pnpm exec pkg . --out-path dist + + - name: checksums + run: | + cd dist + for f in *; do sha256sum "$f" > "$f.sha256"; done + + - name: create release + env: + GH_TOKEN: ${{ github.token }} + run: | + TAG="v$(node -p "require('./package.json').version")" + if git ls-remote --exit-code --tags origin "refs/tags/$TAG" > /dev/null; then + echo "tag $TAG already exists, skipping (bump version in package.json for a new release)" + exit 0 + fi + gh release create "$TAG" dist/* \ + --title "$TAG" \ + --generate-notes diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..77d0bf00 --- /dev/null +++ b/.npmignore @@ -0,0 +1,11 @@ +.github/ +docs/ +test/ +.eslintrc.js +.gitignore +.travis.yml +Dockerfile +.dockerignore +.nyc_output/ +.vscode/ +coverage/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 247f9281..5331588d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ node_js: os: - linux - osx - - windows install: - npm install diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..c4d2ab92 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,30 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "program": "${workspaceFolder}/bin/leetcode", + "args": ["show", "1", "--solution"] + }, + { + "type": "node", + "request": "launch", + "name": "Mocha Tests", + "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", + "args": [ + "-u", + "tdd", + "--timeout", + "999999", + "--colors", + "${workspaceFolder}/test/plugins" + ], + "internalConsoleOptions": "openOnSessionStart" + }, + ] +} \ No newline at end of file diff --git a/1.js b/1.js new file mode 100644 index 00000000..9eedda5c --- /dev/null +++ b/1.js @@ -0,0 +1,29 @@ +/* + * @lc app=leetcode id=1 lang=javascript + * + * [1] Two Sum + */ + +// @lc code=start +/** + * @param {number[]} nums + * @param {number} target + * @return {number[]} + */ +var twoSum = function(nums, target) { + let map = {}; + for (var index = 0; index < nums.length; index++) { + var element = nums[index]; + let rest = target - element; + if (map.hasOwnProperty(rest)) { + return [map[rest], index]; + } + map[element] = index; + } + return [-1, -1]; +}; +/** +// TEST: +console.log(twoSum([2, 9, 4, 5], 7)); +*/ +// @lc code=end diff --git a/README.md b/README.md index 258b5df8..fa4042e0 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,13 @@ -[![npm version](https://img.shields.io/npm/v/leetcode-cli.svg?style=flat)](https://www.npmjs.com/package/leetcode-cli) -[![Releases](https://img.shields.io/github/release/skygragon/leetcode-cli.svg?style=flat)](https://github.com/skygragon/leetcode-cli/releases) -[![license](https://img.shields.io/npm/l/leetcode-cli.svg?style=flat)](https://github.com/skygragon/leetcode-cli/blob/master/LICENSE) -[![Build](https://img.shields.io/travis/skygragon/leetcode-cli.svg?style=flat)](https://travis-ci.org/skygragon/leetcode-cli) -[![Join chat at https://gitter.im/skygragon/leetcode-cli](https://img.shields.io/gitter/room/skygragon/leetcode-cli.svg?style=flat)](https://gitter.im/skygragon/leetcode-cli) +This repository is forked from [skygragon/leetcode-cli](https://github.com/skygragon/leetcode-cli). It seems the source repository is not maintained, I fix some issues here. + +- Fix warnings message caused by old dependencies. +- Fix `leetcode show ID` fail. # leetcode-cli +> Note: This repository is forked from [leetcode-cli](https://github.com/skygragon/leetcode-cli) for temporary usage. +> Note: Copy cookie from webbrowser and Using **leetcode user -c** can temporary fix can't [login problem](https://github.com/jdneo/vscode-leetcode/issues/478). + A productive cli tool to enjoy leetcode! @@ -35,10 +37,13 @@ Great thanks to leetcode.com, a really awesome website! ## Quick Start - Read help first $ leetcode help - Login with your leetcode account $ leetcode user -l - Browse all questions $ leetcode list - Choose one question $ leetcode show 1 -g -l cpp + Read help first $ leetcode help + Login with your leetcode account $ leetcode user -l + Login with third party account--GitHub $ leetcode user -g + Login with third party account--LinkedIn $ leetcode user -i + Cookie login with cookie $ leetcode user -c + Browse all questions $ leetcode list + Choose one question $ leetcode show 1 -g -l cpp Coding it! - Run test(s) and pray... $ leetcode test ./two-sum.cpp -t '[3,2,4]\n7' - Submit final solution! $ leetcode submit ./two-sum.cpp + Run test(s) and pray... $ leetcode test ./two-sum.cpp -t '[3,2,4]\n7' + Submit final solution! $ leetcode submit ./two-sum.cpp diff --git a/docs/_config.yml b/docs/_config.yml deleted file mode 100644 index c4192631..00000000 --- a/docs/_config.yml +++ /dev/null @@ -1 +0,0 @@ -theme: jekyll-theme-cayman \ No newline at end of file diff --git a/docs/advanced.md b/docs/advanced.md deleted file mode 100644 index 42904e91..00000000 --- a/docs/advanced.md +++ /dev/null @@ -1,205 +0,0 @@ ---- -layout: default -title: Advanced Topic ---- - -* [Aliases](#aliases) -* [Auto Login](#auto-login) -* [Bash Completion](#bash-completion) -* [Cache](#cache) -* [Configuration](#configuration) -* [Color Themes](#color-themes) -* [File Name](#file-name) -* [Log Levels](#log-levels) -* [Plugins](#plugins) - -# Aliases - -The commands in leetcode-cli usually has builtin aliases as below: - -|Command |Aliases | -|----------|-----------------------| -|config |conf, cfg, setting | -|list |ls | -|plugin |extension, ext | -|session |branch | -|show |view, pick | -|star |like, favorite | -|stat |stats, progress, report| -|submission|pull | -|submit |push, commit | -|test |run | -|user |account | -|version |info, env | - -# Auto Login - -Leetcode.com is restricting only one session alive in the same time, which means if you login same account otherwhere, the existing login session will be expired immediately. This will greatly harm your experience since you have to re-login again and again among different sessions. - -The good news is leetcode-cli will help a lot on this by trying re-login transparently and automatically without interrupting your current work whenever it detects your current session is expired. To enable this feature you could add following in your config then login again: - - { - "autologin": { - "enable": true - } - } - -**NOTE: once enabled, your PASSWORD will be persisted locally for further using, so PLEASE be careful to ONLY enable this on your OWN computer for the sake of security!** - -# Bash Completion - -Copy `.lc-completion.bash` to your home directory, and source it in .bashrc (Linux) or .bash_profile (MacOS). - - $ cp .lc-completion.bash ~ - $ echo "source ~/.lc-completion.bash" >> ~/.bashrc - $ source ~/.bashrc - - $ leetcode list -- - --help --keyword --query --stat - -**NOTE: it might become slower in bash with this enabled, personally I would NOT suggest to use it...** - -# Cache - -The local cache folder (`.lc/`) is in your home directory, e.g. - - $ ls -a1 ~/.lc/ - cache # folder of cached questions - config.json # user customized config - user.json # user account info - - $ ls -a1 ~/.lc/cache/ - problems.json # cached questions list - 1.two-sum.algorithms.json # cached specific question - -**NOTE: Normally you don't need dig into the folder to manipulate those files. Use [cache command](https://skygragon.github.io/leetcode-cli/commands#cache) instead.** - -# Configuration - -The config file is saved in `~/.lc/config.json`, here is a full exmaple (includes default configs): - - $ cat ~/.lc/config.json - - { - "auto_login": { - "enable": false - }, - "code": { - "editor": "vim", - "lang": "cpp" - }, - "color": { - "enable": true, - "theme": "default" - }, - "file": { - "show": "${fid}.${slug}", - "submission": "${fid}.${slug}.${sid}.${ac}" - }, - "icon": { - "theme": "" - }, - "network": { - "concurrency": 10 - }, - "plugins": {} - } - -Here are some useful settings: - -* `autologin:enable` to enable auto login feature. (see [Auto Login](#auto-login)) -* `code:editor` to set editor used to open generated source file. -* `code:lang` to set your default language used in coding. -* `color:enable` to enable colorful output. -* `color:theme` to set color theme used in output. (see [Color Theme](#color-theme)) -* `file.show` to set filename pattern for generated code file. (see [File Name](#file-name)) -* `icon:theme` to set icon them used in output. -* `plugins` to config each installed plugins. (see [Plugins](#plugins)) - -**NOTE: Normally you don't need dig into the folder to manipulate those files. Use [config command](https://skygragon.github.io/leetcode-cli/commands#config) instead.** - -*Example* - -Config for `github.js` and `cpp.lint.js` plugins: - - { - "plugins": { - "github": { - "repo": "https://github.com/skygragon/test", - "token": "abcdefghijklmnopqrstuvwxyz" - }, - "cpp.lint": { - "bin": "~/bin/cpplibt.py", - "flags": [] - } - } - } - -# Color Themes - -You can choose to use colorful output or not. - -* `--color` to enable color. -* `--no-color` to disable it. - -Or use configuration setting to avoid typing it repeatedly. (see [color:enable](#configuration)) - -When color is enabled, you can choose your favor color theme as well. (see [color:theme](#configuration)) - -Following are available themes: - -* `blue` -* `dark` for night. -* `default` -* `molokai` -* `orange` -* `pink` for girls. -* `solarized` -* `solarized.light` - -Of course you can create your own themes if you like, look into `colors` folder in the source code for more tips. - -*Example* - - $ cat colors/default.json - { - "black": "#000000", - "blue": "#0000ff", - "cyan": "#00ffff", - "green": "#00ff00", - "magenta": "#ff00ff", - "red": "#ff0000", - "white": "#ffffff", - "yellow": "#ffff00" - } - -# File Name - -You could configure file name pattern in code generation. - -* config `file.show` for generated file in `show`. -* config `file.submission` for downloaded file in `submission`. - -Followings are some variables you could used in the pattern: - -* `${fid}` for question id. (e.g. `123`) -* `${slug}` for dash-separated question name. (e.g. `add-two`) -* `${name}` for space-separated questions name. (e.g. `Add Two`) -* `${level}` for question level. (e.g. `Hard`) -* `${category}` for question category. (e.g. `algorithms`) -* `${sid}` for submission id. -* `${ac}` for accept status of existing submission. - -# Log Levels - -* `-v` to enable debug output. -* `-vv` to enable trace output. - * Will print detailed HTTP requests/responses. - -# Plugins - -You can easily introduce more features by installing other plugins form third parties. Here lists the avaible 3rd party plugins at the moment: - -* [leetcode-cli-plugins](https://github.com/skygragon/leetcode-cli-plugins) - -Feel free to try out the plugins above. Or you can develope your own plugins to enrich leetcode-cli's functionalities. diff --git a/docs/commands.md b/docs/commands.md deleted file mode 100644 index 1893dbc4..00000000 --- a/docs/commands.md +++ /dev/null @@ -1,506 +0,0 @@ ---- -layout: default -title: Commands Help ---- - -* [help](#help) -* [cache](#cache) -* [config](#config) -* [list](#list) -* [plugin](#plugin) -* [show](#show) -* [star](#star) -* [stat](#stat) -* [session](#session) -* [submission](#submission) -* [submit](#submit) -* [test](#test) -* [user](#user) -* [version](#version) - -# help - -Display help message. It also shows examples of the commands. - -* `leetcode help ` to see help on sub command. -* `leetcode -h` also works. - -*Examples* - - $ leetcode -h - leetcode [command] - - Commands: - leetcode cache [keyword] Manage local cache - leetcode config [key] [value] Manage user configs [aliases: conf, cfg, setting] - leetcode list [keyword] List questions [aliases: ls] - leetcode plugin [name] Manage plugins [aliases: extension, ext] - leetcode session [keyword] Manage sessions [aliases: branch] - leetcode show [keyword] Show question [aliases: view, pick] - leetcode star Star favorite question [aliases: like, favorite] - leetcode stat Show statistics [aliases: stats, progress, report] - leetcode submission [keyword] Download submission code [aliases: pull] - leetcode submit Submit code [aliases: push, commit] - leetcode test Test code [aliases: run] - leetcode user Manage account [aliases: account] - leetcode version Show version info [aliases: info, env] - leetcode completion generate bash completion script - - Options: - -h, --help Show help [boolean] - - Seek more help at https://skygragon.github.io/leetcode-cli/commands - -Show help on sub command: - - $ leetcode cache -h - leetcode cache [keyword] - - Manage local cache - - Positionals: - keyword Cache name or question id [string] [default: ""] - - Options: - -h, --help Show help [boolean] - -d, --delete Delete cache by keyword [boolean] [default: false] - - Examples: - leetcode cache Show all cache - leetcode cache 1 Show cache of question 1 - - leetcode cache -d Delete all cache - leetcode cache 1 -d Delete cache of question 1 - -# cache - -Show local cached questions. - -* `leetcode cache ` to show specific question cache by id. -* `-d ` to delete specific question cache by id. -* `-d` to delete all cached questions. - -*Examples* - -Show cache: - - $ leetcode cache - problems 190.71K 7 hours ago - 1.two-sum.algorithms 2.82K 13 hours ago - 733.flood-fill.algorithms 4.52K 7 hours ago - 746.min-cost-climbing-stairs.algorithms 2.96K 8 hours ago - ...... - -Delete cache of question 733: - - $ leetcode cache -d 733 - -# config - -Manage user config. - -* `leetcode config` to show all user customized configs. -* `-a` to show all user configs (includes default ones). -* `leetcode config ` to show config by key. -* `leetcode config ` to set config by key. -* `-d` to delete config by key. - -*Examples* - -Set config: - - $ leetcode config color:enable false - -**NOTE: the key is using colon ":" as the separator, not dot "."** - -Show config by key: - - $ leetcode config color - { - "enable": true - } - -# list - -Navigate the quations. - -* Symbols - * `✔` means you have AC-ed this question. - * `✘` means not AC-ed. - * `★` means starred question. - * `🔒` means locked question. -* `-q` to query by conditions. - * `e` = easy, `E` = not easy = m + h. - * `m` = medium, `M` = not medium = e + h. - * `h` = hard, `H` = not hard = e + m. - * `d` = done = AC-ed, `D` = not AC-ed. - * `l` = locked, `L` = not locked. - * `s` = starred, `S` = unstarred. -* `-t` to filter by given tag. - * by category - * `algorithms` - * `database` - * `shell` - * by company (require plugin) - * by topic (require plugin) -* `-s` to show statistic counters of the output list. -* `leetcode list ` to search by keyword matching. - -*Examples* - -Show statistcis: - - $ leetcode list -s - [385] Mini Parser Medium (26.5%) - ✘ [384] Shuffle an Array Medium (45.7%) - ✔ [383] Ransom Note Easy (44.5%) - ✔ [382] Linked List Random Node Medium (46.6%) - ...... - ✔ [ 4] Median of Two Sorted Arrays Hard (19.6%) - ✔ [ 3] Longest Substring Without Repeating Characters Medium (22.9%) - ★ ✔ [ 2] Add Two Numbers Medium (25.37 %) - ★ ✔ [ 1] Two Sum Easy (27.61 %) - - Listed: 400 Locked: 73 Starred: 3 - Accept: 196 Not-AC: 15 Remain: 189 - Easy: 106 Medium: 207 Hard: 87 - -Use keyword search and query: - - $ leetcode list -q Dml array - - 🔒 [360] Sort Transformed Array Medium (41.0%) - 🔒 [325] Maximum Size Subarray Sum Equals k Medium (40.9%) - -# plugin - -Manage plugins. To install 3rd party plugins, please check the [Advanced Tips](https://skygragon.github.io/leetcode-cli/advanced#plugins). - -* `-i` to install new plugin. -* `-d` to disable plugin. -* `-e` to enable plugin. -* `-D` to physically delete plugin. -* `-c` to show plugin's config. - -*Example* - -Install plugin from github: - - $ leetcode plugin -i company - -(Deprecated) Install plugin from local file: - - $ leetcode plugin -i /company.js - -List all the plugins, `✘` means the plugin is disabled. - - $ leetcode plugin - ✔ retry default Plugin to retry last failed request if autologin is on. - ✔ cache default Plugin to provide local cache. - ✔ leetcode default Plugin to talk with leetcode APIs. - -# session - -Manage coding sessions, each session has individual status traced. - -* `-c` to create new session. -* `-e` to enable/activate specific seesion. -* `-d` to delete session. - -*Examples* - -Show all sessions: - - $ leetcode session - Active Id Name AC Questions AC Submits - -------------------------------------------------------------------------------- - ✔ 77299 Anonymous Session 393 ( 98.50 %) 896 ( 47.13 %) - 1111667 Untitled Session 0 ( 0.00 %) 0 ( 0.00 %) - - -# show - -Display question details. With `-g`/`-l`/`-x`, the code template would be auto generated for you. - -* `-g` to generate source file. -* `-x` to add question description in the generated source file. -* `-e` to open editor with generated source file. -* `-o` to specify the output folder. -* `-l` to choose programming language. (Depends on which langs are provided on leetcode) - * bash - * c - * cpp - * csharp - * golang - * java - * javascript - * kotlin - * mysql - * php - * python - * python3 - * ruby - * scala - * swift -* `-c` to only show code template. -* Instead of id, you can use name to select specific question. - * `leetcode show 1` - * `leetcode show "Two Sum"` - * `leetcode show two-sum` -* If no id/name provided, a random question will be selected for you. - * `leetcode show` - * `-q` to filter questions by query. (same as `list` command) - * `-t` to filter questions by tags. (same as `list` command) - -*Examples* - - $ leetcode show 1 -g -l cpp - - [1] Two Sum (File: two-sum.cpp) - - https://leetcode.com/problems/two-sum/ - - * algorithms - * Easy (25.6%) - * Total Accepted: 274880 - * Total Submissions: 1074257 - * Testcase Example: '[3,2,4]\n6' - - Given an array of integers, return indices of the two numbers such that they add up to a specific target. - - You may assume that each input would have exactly one solution. - - Example: - - Given nums = [2, 7, 11, 15], target = 9, - - Because nums[0] + nums[1] = 2 + 7 = 9, - return [0, 1]. - - UPDATE (2016/2/13): - The return format had been changed to zero-based indices. Please read the above updated description carefully. - -Only show the code template: - - $ leetcode show -c 1 - class Solution { - public: - vector twoSum(vector& nums, int target) { - - } - }; - -Random select question: easy + unlocked - - $ leetcode show -q eL - -# star - -Mark your favorite questions. The starred question will be shown with a `★`. - -* `-d` to unstar. -* Instead of id, you can use name to star a question. - * `leetcode star "Two Sum"` - * `leetcode star two-sum` - -*Example* - - $ leetcode star 1 - [1] Two Sum ★ - - $ leetcode star 1 -d - [1] Two Sum ☆ - -# stat - -Show your personal statistics of the question progress. - -* `-g` to show the heatmap graph of all the questions. -* `-c` to show how many AC-ed questions per day by calendar. -* `-q` to filter questions by query. (same as `list` command) -* `-t` to filter questions by tags. (same as `list` command) -* `--no-lock` to exclude lokced questions. - -*Example* - -Show AC-ed progress: - - $ leetcode stat - - Easy 141/205 ( 68.78 %) █████████████████████░░░░░░░░░ - Medium 200/365 ( 54.79 %) █████████████████░░░░░░░░░░░░░ - Hard 52/148 ( 35.14 %) ███████████░░░░░░░░░░░░░░░░░░░ - -Show heatmap graph: - - $ leetcode stat -g - - 1 10 11 20 21 30 31 40 41 50 - 000 ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ⬚ ▣ ▣ ▣ ▣ ▣ ▣ ⬚ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ - 050 ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ - 100 ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ⬚ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ - 150 ▣ ▣ ▣ ▣ ▣ ⬚ ⬚ ⬚ ⬚ ▣ ⬚ ▣ ⬚ ▣ ▣ ▣ ▣ ▣ ▣ ⬚ ▣ ▣ ▣ ▣ ⬚ ⬚ ⬚ ⬚ ▣ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▣ ▣ ▣ ▣ ▣ ⬚ ⬚ ⬚ ▣ ⬚ ⬚ ▣ ▣ ▣ - 200 ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ⬚ ▣ ▣ ▣ ▣ ▣ ⬚ ▣ ▤ ▣ ▣ ▣ ⬚ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ - 250 ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▣ ▣ ⬚ ▣ ⬚ ⬚ ▣ ▣ ⬚ ⬚ ⬚ ▣ ⬚ ⬚ ⬚ ⬚ ⬚ ▣ ▣ ⬚ ⬚ ▣ ▣ ⬚ ⬚ ⬚ ▣ ▣ ⬚ ⬚ ▣ ⬚ ⬚ ▣ ⬚ ▣ ⬚ ⬚ ▣ ⬚ ▣ ⬚ ▣ ▣ - 300 ▣ ⬚ ▣ ▣ ⬚ ▣ ▣ ⬚ ▣ ⬚ ⬚ ▣ ▣ ⬚ ▣ ▣ ⬚ ▣ ▣ ⬚ ⬚ ▣ ⬚ ▤ ⬚ ▣ ⬚ ▣ ▣ ▣ ▣ ▣ ⬚ ▣ ▣ ▤ ▣ ▣ ⬚ ⬚ ▣ ▣ ▣ ▣ ▣ ⬚ ▣ ⬚ ▣ ▣ - 350 ⬚ ▣ ⬚ ⬚ ⬚ ⬚ ▣ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▣ ⬚ ▣ ▣ ⬚ ⬚ ▣ ▣ ▣ ▣ ⬚ ⬚ ▣ ⬚ ⬚ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▤ ⬚ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ ▣ - 400 ▣ ▣ ▣ ▣ ▣ ▣ ⬚ ⬚ ▣ ⬚ ⬚ ▣ ▣ ▣ ▣ ▣ ▣ ⬚ ⬚ ⬚ ⬚ ⬚ ▣ ⬚ ⬚ ⬚ ▣ ▣ ⬚ ▣ ▣ ⬚ ⬚ ▣ ▣ ⬚ ⬚ ▣ ⬚ ▣ ▣ ⬚ ⬚ - 450 ▣ ▣ ▣ ⬚ ▣ ▣ ▣ ⬚ ▣ ▣ ▣ ⬚ ⬚ ⬚ ▣ ⬚ ⬚ ⬚ ⬚ ▣ ▣ ▣ ▣ ▣ ⬚ ⬚ ▣ ▣ ⬚ ⬚ ▣ ▣ ⬚ ⬚ ⬚ ⬚ ▣ ⬚ ▣ ▣ ▣ ▣ ⬚ ▣ - 500 ▣ ⬚ ▣ ▣ ⬚ ▣ ▣ ▣ ▣ ⬚ ▣ ▣ ▤ ▣ ⬚ ⬚ ▣ ▣ ▤ ▣ ⬚ ▣ ▣ ⬚ ▣ ⬚ ▣ ⬚ ▣ ▣ ▣ ⬚ ▣ ▣ ▣ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ - 550 ⬚ ⬚ ⬚ ⬚ ⬚ ▣ ▣ ⬚ ▣ ⬚ ▣ ⬚ ⬚ ▣ ⬚ ⬚ ⬚ ⬚ ⬚ ▣ ⬚ ⬚ ▣ ⬚ ⬚ ⬚ ⬚ ⬚ ▣ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▣ ▣ - 600 ⬚ ⬚ ⬚ ⬚ ▣ ▣ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▣ ⬚ ⬚ ⬚ ⬚ ⬚ ▣ ▣ ⬚ ⬚ ▣ ⬚ ⬚ ⬚ ⬚ ▣ ⬚ ⬚ ⬚ ▣ ⬚ ⬚ ⬚ ⬚ ▣ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▣ - 650 ⬚ ▣ ▣ ▣ ⬚ ⬚ ▣ ▣ ⬚ ▣ ⬚ ▣ ⬚ ⬚ ▣ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ - 700 ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▣ ⬚ ▣ ▣ ⬚ ⬚ ⬚ - 750 ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ - - ▣ Accepted ▤ Not Accepted ⬚ Remaining - -Show calendar graph: - - $ leetcode stat -c - - Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Jan - Sun ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ - Mon ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ - Tue ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ - Wed ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ - Thu ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ - Fri ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ - Sat ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ▣ - - ▣ 1~5 ▣ 6~10 ▣ 11~15 ▣ 16+ - -# submission - -Download your former submissions. - -* For AC-ed question, the last accepted submission will be downloaded, which output in green color. -* For non AC-ed question, the last non-accepted submission will be downloaded, which output in yellow. -* If the submission file already exists in local, it will skip downloading and output in white. - -Available options: - -* `-o` to specify the output folder. -* `-a` to work against all questions. -* `-l` to filter by specific programming language. -* `-x` to add question details in the output file. -* Or work against specfic question only. - * `leetcode submission 1` - * `leetcode submission two-sum` - - -*Examples* - - $ leetcode submission -a -o tmp - - [303] Range Sum Query - Immutable tmp/range-sum-query-immutable.52178990.ac.cpp - [319] Bulb Switcher tmp/bulb-switcher.52257927.ac.cpp - [313] Super Ugly Number tmp/super-ugly-number.52256965.ac.cpp - ...... - [ 1] Two Sum tmp/two-sum.73790064.ac.cpp - -# submit - -Submit code to leetcode.com. - -*Examples* - - $ leetcode submit ./two-sum.cpp - - ✔ Accepted - ✔ 16/16 cases passed (12 ms) - ✔ Your runtime beats 49.89 % of cpp submissions - -# test - -Test code on leetcode.com. If no testcase provided, a default testcase will be used. - -* `-t` to provide test case in command line. - * NOTE: use single quote `'` to surround your test case. (double quote is NOT safe in bash shell due to escaping) -* `-i` to provide test case in interactive mode. - * on Linux/MacOS, press `Ctrl-D` to finish input. - * on Windows, press `Ctrl-D` and `Return` to finish input. - -*Examples* - - $ leetcode test ./two-sum.cpp -t '[3,2,4]\n7' - - Input data: - [3,2,4] - 7 - - Actual - ✔ runtime: 0 ms - ✘ answer: [1,2] - ✔ output: - - Expected - ✔ runtime: 0 ms - ✔ answer: [0,2] - ✔ output: - -# user - -Login with your leetcode account (username or email). - -* `-l` to login -* `-L` to logout. -* `leetcode user` to show current account. - -*Examples* - -Login: - - $ leetcode user -l - login: - pass: - Successfully login as - -# version - -Display version information. - -* `-v` to show verbose info. - -*Examples* - -Short: - - $ leetcode version - 2.6.2 - -Verbose: - - $ leetcode version -v - _ _ _ - | | | | | | - | | ___ ___| |_ ___ ___ __| | ___ - | |/ _ \/ _ \ __|/ __|/ _ \ / _` |/ _ \ - | | __/ __/ |_ (__| (_) | (_| | __/ - |_|\___|\___|\__|\___|\___/ \__,_|\___| CLI v2.6.2 - - [Environment] - Node v8.1.4 - OS darwin 15.6.0 - Cache /Users/skygragon/.lc/cache - Config /Users/skygragon/.lc/config.json - - [Configuration] - autologin {"enable":true} - code {"editor":"vim","lang":"cpp"} - color {"enable":true,"theme":"molokai"} - icon {"theme":""} - network {"concurrency":10} - - [Themes] - Colors blue,dark,default,molokai,orange,pink,solarized,solarized.light - Icons ascii,default,win7 - - [Plugins] - solution.discuss 2017.12.21 - company 2017.12.18 - github 2017.08.10 - cache default - retry default - leetcode default - diff --git a/docs/demo.html b/docs/demo.html deleted file mode 100644 index d0472d97..00000000 --- a/docs/demo.html +++ /dev/null @@ -1,8 +0,0 @@ ---- -layout: default -title: Showcases ---- -
- - -
diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 9deeb3a7..00000000 --- a/docs/index.html +++ /dev/null @@ -1,17 +0,0 @@ ---- -layout: default -title: Leetcode CLI ---- - -
- Installation - Release Notes - Showcases - Commands - Advanced Tips -
diff --git a/docs/install.md b/docs/install.md deleted file mode 100644 index c2e20595..00000000 --- a/docs/install.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -layout: default -title: Installation ---- - -# All in One (beta) - -No need to install node.js. Now available on 64bits linux, mac, and windows. - -[Download](https://github.com/skygragon/leetcode-cli/releases) - -# Prerequisites - -Install the latest LTS version of `node.js` (`npm` included): - -* [Install from package manager](https://nodejs.org/en/download/package-manager/) -* [Install from directly download](https://nodejs.org/en/download/) - -Check before going next: - - $ node -v - $ npm -v - -# Installation - -There are different ways to install `leetcode-cli`: - -### From npm - -This will install the latest STABLE version, but not include the latest DEV version. - - $ npm install -g leetcode-cli - $ leetcode version - -In case Ubuntu failed due to **permission denied**, try following: - - $ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash - $ source ~/.bashrc - $ nvm install --lts - -Find more details [here](https://docs.npmjs.com/getting-started/fixing-npm-permissions). - -### From GitHub - -This will install the latest DEV version from GitHub repo. - - $ npm install -g skygragon/leetcode-cli - $ leetcode version - -### From source - -Similar with above, while you can introduce your own changes as you wish. - - $ git clone http://github.com/skygragon/leetcode-cli - $ cd leetcode-cli && ./bin/install - $ leetcode version - -### From source (all-in-one) - - $ git clone http://github.com/skygragon/leetcode-cli - $ cd leetcode-cli && node ./bin/pkg - -### From docker - -NOTE: This is just a tiny taste to let you feel that leetcode-cli is. Please use other ways above to install leetcode-cli if you like it. - - $ alias leetcode='docker run -it --rm skygragon/leetcode-cli' - $ leetcode version - -To persistent user data, you can mount a folder like this: - - $ alias leetcode='docker run -it --rm -v /Users/skygragon/data:/root skygragon/leetcode-cli' diff --git a/docs/logo.png b/docs/logo.png deleted file mode 100644 index 0ad15c7a..00000000 Binary files a/docs/logo.png and /dev/null differ diff --git a/docs/releases.md b/docs/releases.md deleted file mode 100644 index 77cce5eb..00000000 --- a/docs/releases.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -layout: default -title: Release Notes ---- -# 2.6.2 -* `submit` - * fixes beta ratio issue - -# 2.6.1 -* `submit` - * fixes 500 error on windows. - -# 2.6.0 -* build all-in-one binary for linux/macos/windows. -* `show` - * support customized filename. - * use "--" as comment in sql file. -* `list` - * fixes format issue. -* fixes UT failures on windows. - -# 2.5.4 -* fixes error in fresh env without .lc existed. -* embed meta in file content instead of file name. -* update dependencies. - -# 2.5.3 - -* fixes "Failed to load locked problem" issue. -* move plugin's data into separate folders: - * login info - * problems list - * problem cache - -# 2.5.2 - -* `show` - * fixes 400 error - * support translated content for leetcode-cn - -# 2.5.1 - -* auto install missing plugins after upgrade. -* use 16m colors if possible. -* enhance color output on windows. -* `cache` - * fix issue that can't delete cache by name. -* `session` - * fix issue if session name is a number. -* `stat` - * use level weight in calendar view. - -# 2.5.0 - -* add `session` command to manage coding sessions on leetcode.com. -* add more color themes. - * molokai - * solarized - * solarized.light -* `list` - * fix id mismatch issue. -* `show` - * add `-o` option to specify output folder. - * fix badge output in non-default color themes. -* `stat` - * calculate on AC-ed questions in calendar graph. -* `test` - * fix out-of-order output issue. - -# 2.4.0 - -* only supports node's version >= 4. -* Refactor folder structure: - * now `~/.lc/` would be the only folder used by leetcode-cli. - * move lcconfig file to `~/.lc/`. - * move cache files to `~/.lc/cache/`. -* `config` - * fix string value parsing error. -* `list` - * show tag/lang badges in `-x` output. -* `show` - * add `-q` `-t` options to filter random questions. -* `stat` - * enhance output of `-g` option. - * enhance output on windows. - * add `-c` option to display calendar stat of how many AC-ed questions per day. - * add `--no-lock` option to filter out locked questions. - * add `-q` `-t` options to filter questions stat. - -# 2.3.0 - -* `plugin` - * only install necessary depedencies on specific platform. - * add `-c` option to show plugin config. - * support [cookie.chrome](https://github.com/skygragon/leetcode-cli-plugins/blob/master/docs/cookie.chrome.md) plugin. - * support [cookie.firefox](https://github.com/skygragon/leetcode-cli-plugins/blob/master/docs/cookie.firefox.md) plugin. -* docker - * support running leetcode-cli as docker container for new user's tasting. - * auto build docker image in Docker Hub. -* UI - * Add spinner message for long time running works. -* Add logo and updte documents. - -# 2.2.1 - -* add commands aliases. -* enhance documents about install error on Ubuntu. -* `config` - * fix wrong parsing on non-string value. -* `plugin` - * fix bug when installing new npm modules. -* `show` - * use traditional `.py` for python3 filename. -* `submission` - * enhance recursive folder creation. - -# 2.2.0 - -* `config` - * add new `config` command to manage user configs. - * try to save user from manually editing config file (~/.lcconfig). - * start to use new json config format. (NOTE: not compatible with old format!) -* `show` - * print suppoerted language list. -* add Release Notes page. -* remove several legacy hacks. - -# 2.1.1 -* `show` - * add `-e` option to open editor for coding. - * add `-c` option to display source code only. - * remove legacy `-t` `-d` options. - * fix bad alignment in colorful output. -* `list` - * enhance `-t` option to support multiple tags, e.g. `leetcode list -t google -t array` - * support latest `company` plugin to filter questions by tags like `array` or `dynamic programming` -* config - * add `EDITOR` to set default editor. -* fix `--no-color` bug. - - -# 2.1.0 -* `show` - * fix "unknown language" error due to recent API changes on leetcode.com. - * add `kotlin` language. -* `cache` - * remove `-a` option, now `leetcode cache -d` will directly clear all cache. - * add keyword match, e.g. `leetcode cache 537` will only show the cache for question 537. -* update most libray depedencies. diff --git a/docs/screenshots/intro.2018.01.13.gif b/docs/screenshots/intro.2018.01.13.gif deleted file mode 100644 index 9d7123aa..00000000 Binary files a/docs/screenshots/intro.2018.01.13.gif and /dev/null differ diff --git a/docs/workflow.png b/docs/workflow.png deleted file mode 100644 index fadaee92..00000000 Binary files a/docs/workflow.png and /dev/null differ diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000..6c5a1238 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,90 @@ +'use strict'; + +// Effective ruleset captured from the previous eslint 5 + google 0.11 +// setup (via --print-config, active rules only), so lint behavior is +// preserved exactly while dropping the archived google preset. +const RULES = { + 'block-spacing': [2, 'always'], + 'brace-style': [2, '1tbs', {allowSingleLine: true}], + 'camelcase': [2, {properties: 'never'}], + 'constructor-super': 'error', + 'for-direction': 'error', + 'getter-return': 'error', + 'key-spacing': [2, {align: 'value'}], + 'max-len': [1, 120], + 'no-case-declarations': 'error', + 'no-class-assign': 'error', + 'no-compare-neg-zero': 'error', + 'no-cond-assign': 'error', + 'no-console': 1, + 'no-const-assign': 'error', + 'no-constant-condition': 'error', + 'no-debugger': 'error', + 'no-delete-var': 'error', + 'no-dupe-args': 'error', + 'no-dupe-class-members': 'error', + 'no-dupe-keys': 'error', + 'no-duplicate-case': 'error', + 'no-empty': [2, {allowEmptyCatch: true}], + 'no-empty-character-class': 'error', + 'no-empty-pattern': 'error', + 'no-eval': 1, + 'no-ex-assign': 'error', + 'no-extra-boolean-cast': 'error', + 'no-extra-semi': 'error', + 'no-fallthrough': 'error', + 'no-func-assign': 'error', + 'no-global-assign': 'error', + 'no-inner-declarations': 'error', + 'no-invalid-regexp': 'error', + 'no-irregular-whitespace': 'error', + 'no-loop-func': 1, + 'no-mixed-spaces-and-tabs': 'error', + 'no-new-symbol': 'error', + 'no-obj-calls': 'error', + 'no-octal': 'error', + 'no-proto': 1, + 'no-redeclare': 'error', + 'no-regex-spaces': 'error', + 'no-self-assign': 'error', + 'no-sparse-arrays': 'error', + 'no-this-before-super': 'error', + 'no-undef': 'error', + 'no-unexpected-multiline': 'error', + 'no-unreachable': 'error', + 'no-unsafe-finally': 'error', + 'no-unsafe-negation': 'error', + 'no-unused-expressions': 1, + 'no-unused-labels': 'error', + 'no-unused-vars': [1, {args: 'none'}], + 'no-useless-escape': 'error', + 'quote-props': [1, 'consistent'], + 'quotes': [2, 'single', {avoidEscape: true}], + 'require-yield': 'error', + 'use-isnan': 'error', + 'valid-typeof': 'error' +}; + +const NODE_MOCHA_GLOBALS = { + URL: 'readonly', require: 'readonly', module: 'writable', exports: 'writable', + process: 'readonly', console: 'readonly', Buffer: 'readonly', + __dirname: 'readonly', __filename: 'readonly', setTimeout: 'readonly', + setImmediate: 'readonly', + clearTimeout: 'readonly', setInterval: 'readonly', clearInterval: 'readonly', + describe: 'readonly', it: 'readonly', before: 'readonly', after: 'readonly', + beforeEach: 'readonly', afterEach: 'readonly' +}; + +module.exports = [ + { + ignores: ['node_modules/**', 'tmp/**', 'lib/plugins/company.js'] + }, + { + languageOptions: { + ecmaVersion: 2023, + sourceType: 'commonjs', + globals: NODE_MOCHA_GLOBALS + }, + rules: RULES + } +]; diff --git a/lib/cache.js b/lib/cache.js index 42efad0b..dc10d52e 100644 --- a/lib/cache.js +++ b/lib/cache.js @@ -9,6 +9,12 @@ cache.init = function() { file.mkdir(file.cacheDir()); }; +cache.deleteAll = function () { + cache.list().forEach(value => { + cache.del(value.name); + }) +}; + cache.get = function(k) { const fullpath = file.cacheFile(k); if (!file.exist(fullpath)) return null; diff --git a/lib/cli.js b/lib/cli.js index e59cf7f5..13cb0950 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -33,15 +33,16 @@ function initLogLevel() { // print HTTP details in TRACE if (level === 'TRACE') { - const request = require('request'); - request.debug = true; + require('./http').debug = true; console.error = _.wrap(console.error, function(func) { let args = Array.from(arguments); args.shift(); // FIXME: hack HTTP request log, hope no one else use it... - if (args.length > 0 && args[0].indexOf('REQUEST ') === 0) { + // args may hold non-strings (yargs logs through console.error too) + if (args.length > 0 && typeof args[0] === 'string' && + args[0].indexOf('REQUEST ') === 0) { args = args.map((x) => h.printSafeHTTP(x)); log.trace.apply(log, args); } else { @@ -74,8 +75,14 @@ function initPlugins(cb) { var cli = {}; function runCommand() { + // -v/-vv were already consumed by initLogLevel; yargs snapshots + // process.argv at require time and bails silently on unknown options + // placed before the command, so strip them BEFORE it loads + process.argv = process.argv.filter(x => x !== '-v' && x !== '-vv'); + var yargs = require('yargs'); h.width = yargs.terminalWidth(); + yargs.commandDir('commands') .completion() .help('h') @@ -83,7 +90,7 @@ function runCommand() { .version(false) .epilog('Seek more help at https://skygragon.github.io/leetcode-cli/commands') .wrap(Math.min(h.width, 120)) - .argv; + .parse(); } cli.run = function() { @@ -91,12 +98,13 @@ cli.run = function() { if (e.code === 'EPIPE') process.exit(); }); - config.init(); + // Directory must be initialized with first priority + initDir(); + config.init(); initColor(); initIcon(); initLogLevel(); - initDir() initPlugins(function(e) { if (e) return log.fatal(e); cache.init(); diff --git a/lib/commands/cache.js b/lib/commands/cache.js index 154a3302..413f2dc3 100644 --- a/lib/commands/cache.js +++ b/lib/commands/cache.js @@ -47,8 +47,15 @@ cmd.handler = function(argv) { if (argv.delete) { for (let f of caches) cache.del(f.name); } else { - log.info(chalk.gray(sprintf(' %s %63s %s', 'Cache', 'Size', 'Created'))); - log.info(chalk.gray('-'.repeat(86))); + // some cache names (e.g. long slugs) exceed 60 chars, widen the name + // column to the longest one so size/created columns stay aligned + const width = caches.reduce((m, f) => Math.max(m, f.name.length), 60); + + // per-problem caches get a solved marker from the problems list + const problems = name === '' ? cache.get(h.KEYS.problems) : null; + + log.info(chalk.gray(sprintf(' %-' + width + 's %8s %s', 'Cache', 'Size', 'Created'))); + log.info(chalk.gray('-'.repeat(width + 26))); _.sortBy(caches, function(f) { let x = parseInt(f.name.split('.')[0], 10); @@ -56,7 +63,16 @@ cmd.handler = function(argv) { return x; }) .forEach(function(f) { - log.printf(' %-60s %8s %s ago', + let marker = ' '; + if (problems) { + const fid = parseInt(f.name, 10); + const problem = Number.isInteger(fid) && + problems.find(x => x.fid === fid); + if (problem) marker = problem.state === 'ac' ? h.prettyState('ac') : ' '; + marker += ' '; + } + log.printf(' %s%-' + width + 's %8s %s ago', + marker, chalk.green(f.name), h.prettySize(f.size), h.prettyTime((Date.now() - f.mtime) / 1000)); diff --git a/lib/commands/config.js b/lib/commands/config.js index 6a1fe364..50ea1ea5 100644 --- a/lib/commands/config.js +++ b/lib/commands/config.js @@ -89,7 +89,7 @@ cmd.handler = function(argv) { // set try { nconf.set(argv.key, JSON.parse(argv.value)); - } catch (e) { + } catch { nconf.set(argv.key, JSON.parse('"' + argv.value + '"')); } return saveConfig(); diff --git a/lib/commands/list.js b/lib/commands/list.js index c010de86..e14e6a4a 100644 --- a/lib/commands/list.js +++ b/lib/commands/list.js @@ -28,6 +28,12 @@ const cmd = { default: false, describe: 'Show extra details: category, companies, tags.' }) + .option('T', { + alias: 'dontTranslate', + type: 'boolean', + default: false, + describe: 'Set to true to disable endpoint\'s translation', + }) .positional('keyword', { type: 'string', default: '', @@ -60,20 +66,27 @@ cmd.handler = function(argv) { for (let x of ['locked', 'starred', 'ac', 'notac', 'None', 'Easy', 'Medium', 'Hard']) stat[x] = 0; problems = _.sortBy(problems, x => -x.fid); + + // column widths follow the data: fids grow over time and some names + // exceed 60 chars, either would shift the level column of the row + const fidWidth = problems.length ? ('' + problems[0].fid).length : 4; + const nameWidth = problems.reduce((m, x) => Math.max(m, x.name.length), 60); + const extraIndent = 8 + fidWidth; + for (let problem of problems) { stat[problem.level] = (stat[problem.level] || 0) + 1; stat[problem.state] = (stat[problem.state] || 0) + 1; if (problem.locked) ++stat.locked; if (problem.starred) ++stat.starred; - log.printf('%s %s %s [%=4s] %-60s %-6s (%s %%)', + log.printf('%s %s %s [%=' + fidWidth + 's] %-' + nameWidth + 's %-6s (%s %%)', (problem.starred ? chalk.yellow(icon.like) : icon.empty), (problem.locked ? chalk.red(icon.lock) : icon.nolock), h.prettyState(problem.state), problem.fid, problem.name, h.prettyLevel(problem.level), - problem.percent.toFixed(2)); + (problem.percent || 0).toFixed(2)); if (argv.extra) { let badges = [problem.category]; @@ -83,8 +96,8 @@ cmd.handler = function(argv) { let buf = []; let len = 0; for (let x of badges) { - if (len + x.length + 3 >= 60) { - log.printf('%12s%s', ' ', chalk.gray(buf.join(' | '))); + if (len + x.length + 3 >= nameWidth) { + log.printf('%' + extraIndent + 's%s', ' ', chalk.gray(buf.join(' | '))); buf = []; len = 0; } @@ -92,7 +105,7 @@ cmd.handler = function(argv) { len += x.length + 3; } if (buf.length > 0) - log.printf('%12s%s', ' ', chalk.gray(buf.join(' | '))); + log.printf('%' + extraIndent + 's%s', ' ', chalk.gray(buf.join(' | '))); } } diff --git a/lib/commands/session.js b/lib/commands/session.js index 64d460d6..c3bc82f5 100644 --- a/lib/commands/session.js +++ b/lib/commands/session.js @@ -1,5 +1,4 @@ 'use strict'; -var prompt = require('prompt'); var h = require('../helper'); var chalk = require('../chalk'); @@ -99,24 +98,7 @@ cmd.handler = function(argv) { } if (argv.delete) { - log.info([ - chalk.red.bold('CAREFUL! This action CANNOT be undone!'), - '\nThis will permanently delete all your submissions', - 'and progress associated with this session.', - '\nAre you sure you want to delete this session?\n', - '\nPlease type in the session\'s', - chalk.yellow.bold('number of accepted submissions'), - 'to confirm.\n' - ].join(' ')); - - prompt.colors = false; - prompt.message = ''; - prompt.start(); - prompt.get([{name: 'answer', type: 'integer', required: true}], function(e, x) { - if (x.answer !== session.total_acs) return; - return core.deleteSession(session, printSessions); - }); - return; + return core.deleteSession(session, printSessions); } } printSessions(null, sessions); diff --git a/lib/commands/show.js b/lib/commands/show.js index 7c66204a..48f1b42f 100644 --- a/lib/commands/show.js +++ b/lib/commands/show.js @@ -2,6 +2,8 @@ var util = require('util'); var _ = require('underscore'); +var cheerio = require('cheerio'); +var he = require('he'); var childProcess = require('child_process'); var h = require('../helper'); @@ -25,6 +27,12 @@ const cmd = { default: false, describe: 'Only show code template' }) + .option('d', { + alias: 'daily', + type: 'boolean', + default: false, + describe: 'Show question of the day' + }) .option('e', { alias: 'editor', type: 'string', @@ -57,6 +65,12 @@ const cmd = { default: false, describe: 'Show extra question details in source code' }) + .option('T', { + alias: 'dontTranslate', + type: 'boolean', + default: false, + describe: 'Set to true to disable endpoint\'s translation', + }) .positional('keyword', { type: 'string', default: '', @@ -67,6 +81,7 @@ const cmd = { .example(chalk.yellow('leetcode show 1 -gxe'), 'Open generated code in editor') .example('', '') .example(chalk.yellow('leetcode show'), 'Show random question') + .example(chalk.yellow('leetcode show -d'), 'Show question of the day') .example(chalk.yellow('leetcode show -q h'), 'Show random hard question') .example(chalk.yellow('leetcode show -t google'), 'Show random question from Google (require plugin)'); } @@ -152,24 +167,50 @@ function showProblem(problem, argv) { log.printf('* %s', problem.category); log.printf('* %s (%s%%)', h.prettyLevel(problem.level), problem.percent.toFixed(2)); - if (filename) - log.printf('* Source Code: %s', chalk.yellow.underline(filename)); + if (problem.likes) + log.printf('* Likes: %s', problem.likes); + if (problem.dislikes) + log.printf('* Dislikes: %s', problem.dislikes); + else + log.printf('* Dislikes: -'); if (problem.totalAC) log.printf('* Total Accepted: %s', problem.totalAC); if (problem.totalSubmit) log.printf('* Total Submissions: %s', problem.totalSubmit); if (problem.testable && problem.testcase) log.printf('* Testcase Example: %s', chalk.yellow(util.inspect(problem.testcase))); + if (filename) + log.printf('* Source Code: %s', chalk.yellow.underline(filename)); log.info(); - log.info(problem.desc); + log.info(plainText(problem.desc)); + + for (let i of (problem.hints || []).keys()) { + log.info(); + log.printf('%s %s', chalk.yellow('Hint ' + (i + 1) + ':'), plainText(problem.hints[i])); + } +} + +// terminal-friendly text: strip tags, decode entities, keep line structure +function plainText(html) { + return he.decode(cheerio.load('' + html).root().text()).trim(); } cmd.handler = function(argv) { session.argv = argv; + + if (argv.daily) { + // show question of the day + core.getProblemOfToday(!argv.dontTranslate, function(e, problem) { + if (e) return log.fail(e); + showProblem(problem, argv); + }); + return; + } + if (argv.keyword.length > 0) { // show specific one - core.getProblem(argv.keyword, function(e, problem) { + core.getProblem(argv.keyword, !argv.dontTranslate, function(e, problem) { if (e) return log.fail(e); showProblem(problem, argv); }); @@ -188,7 +229,7 @@ cmd.handler = function(argv) { if (problems.length === 0) return log.fail('Problem not found!'); const problem = _.sample(problems); - core.getProblem(problem, function(e, problem) { + core.getProblem(problem, !argv.dontTranslate, function(e, problem) { if (e) return log.fail(e); showProblem(problem, argv); }); diff --git a/lib/commands/star.js b/lib/commands/star.js index 3660432b..6a396dc9 100644 --- a/lib/commands/star.js +++ b/lib/commands/star.js @@ -29,7 +29,8 @@ const cmd = { cmd.handler = function(argv) { session.argv = argv; - core.getProblem(argv.keyword, function(e, problem) { + // translation doesn't affect question lookup + core.getProblem(argv.keyword, true, function(e, problem) { if (e) return log.fail(e); core.starProblem(problem, !argv.delete, function(e, starred) { diff --git a/lib/commands/stat.js b/lib/commands/stat.js index 772499c4..1618df19 100644 --- a/lib/commands/stat.js +++ b/lib/commands/stat.js @@ -46,11 +46,11 @@ const cmd = { } }; -function printLine(key, done, all) { +function printLine(key, done, all, width) { const n = 30; const percent = (all > 0) ? done / all : 0; const x = Math.ceil(n * percent); - log.printf(' %s\t%3s/%-3s (%6s %%) %s%s', + log.printf(' %s\t%' + width + 's/%-' + width + 's (%6s %%) %s%s', h.prettyLevel(key), done, all, (100 * percent).toFixed(2), chalk.green('█'.repeat(x)), @@ -75,9 +75,11 @@ function showProgress(problems) { ++stats[level][state]; } - printLine('Easy', stats.easy.ac, stats.easy.all); - printLine('Medium', stats.medium.ac, stats.medium.all); - printLine('Hard', stats.hard.ac, stats.hard.all); + // width follows the largest count so the bars stay aligned + const width = ('' + Math.max(stats.easy.all, stats.medium.all, stats.hard.all)).length; + printLine('Easy', stats.easy.ac, stats.easy.all, width); + printLine('Medium', stats.medium.ac, stats.medium.all, width); + printLine('Hard', stats.hard.ac, stats.hard.all, width); } function showGraph(problems) { @@ -98,7 +100,7 @@ function showGraph(problems) { const header = _.range(groups) .map(x => sprintf('%4s%18s', x * 10 + 1, x * 10 + 10)) .join(''); - log.info(' ' + header); + log.info(' ' + header); const graph = []; for (let problem of problems) @@ -168,7 +170,9 @@ function showCal(problems) { const d = now.clone().subtract(i, 'months').date(1); const idx = now.diff(d, 'days'); - const j = (N_WEEKS - idx / N_WEEKDAYS + 1) * 2; + // week position is fractional, Buffer.write needs an integer offset + // (modern node throws ERR_OUT_OF_RANGE on the coerced value) + const j = Math.floor((N_WEEKS - idx / N_WEEKDAYS + 1) * 2); if (j >= 0) buf.write(MONTHS[d.month()], j); } log.printf('%7s%s', ' ', buf.toString()); diff --git a/lib/commands/submission.js b/lib/commands/submission.js index de0449a3..40d1911d 100644 --- a/lib/commands/submission.js +++ b/lib/commands/submission.js @@ -42,6 +42,12 @@ const cmd = { default: false, describe: 'Show extra question details in submission code' }) + .option('T', { + alias: 'dontTranslate', + type: 'boolean', + default: false, + describe: 'Set to true to disable endpoint\'s translation', + }) .positional('keyword', { type: 'string', default: '', @@ -62,6 +68,7 @@ function doTask(problem, queue, cb) { // - green: accepted, fresh download // - yellow: not ac-ed, fresh download // - white: existed already, skip download + if (e) process.exitCode = 1; log.printf('[%=4s] %-60s %s', problem.fid, problem.name, (e ? chalk.red('ERROR: ' + (e.msg || e)) : msg)); if (cb) cb(e); @@ -69,7 +76,7 @@ function doTask(problem, queue, cb) { if (argv.extra) { // have to get problem details, e.g. problem description. - core.getProblem(problem.fid, function(e, problem) { + core.getProblem(problem.fid, !argv.dontTranslate, function(e, problem) { if (e) return cb(e); exportSubmission(problem, argv, onTaskDone); }); @@ -135,7 +142,7 @@ cmd.handler = function(argv) { if (!argv.keyword) return log.fail('missing keyword?'); - core.getProblem(argv.keyword, function(e, problem) { + core.getProblem(argv.keyword, !argv.dontTranslate, function(e, problem) { if (e) return log.fail(e); q.addTask(problem).run(); }); diff --git a/lib/commands/submit.js b/lib/commands/submit.js index 56f5ed04..75a1c6c1 100644 --- a/lib/commands/submit.js +++ b/lib/commands/submit.js @@ -1,6 +1,7 @@ 'use strict'; var util = require('util'); + var h = require('../helper'); var file = require('../file'); var chalk = require('../chalk'); @@ -29,7 +30,7 @@ function printResult(actual, k) { const v = actual[k] || ''; const lines = Array.isArray(v) ? v : [v]; for (let line of lines) { - if (k !== 'state') line = k + ': ' + line; + if (k !== 'state') line = h.startCase(k) + ': ' + line; log.info(' ' + h.prettyText(' ' + line, actual.ok)); } } @@ -48,7 +49,8 @@ cmd.handler = function(argv) { const meta = file.meta(argv.filename); - core.getProblem(meta.id, function(e, problem) { + // translation doesn't affect problem lookup + core.getProblem(meta.id, true, function(e, problem) { if (e) return log.fail(e); problem.file = argv.filename; @@ -66,24 +68,40 @@ cmd.handler = function(argv) { if (result.ok) { session.updateStat('ac', 1); session.updateStat('ac.set', problem.fid); - core.getSubmission({id: result.id}, function(e, submission) { - if (e || !submission || !submission.distributionChart) - return log.warn('Failed to get submission beat ratio.'); - - const lang = submission.distributionChart.lang; - const scores = submission.distributionChart.distribution; - const myRuntime = parseFloat(result.runtime); - - let ratio = 0.0; - for (let score of scores) { - if (parseFloat(score[0]) >= myRuntime) - ratio += parseFloat(score[1]); - } - - printLine(result, 'Your runtime beats %d %% of %s submissions', - ratio.toFixed(2), lang); - }); + + (function () { + if (result.runtime_percentile) + printLine(result, 'Your runtime beats %d %% of %s submissions', + result.runtime_percentile.toFixed(2), result.lang); + else + return log.warn('Failed to get runtime percentile.'); + if (result.memory && result.memory_percentile) + printLine(result, 'Your memory usage beats %d %% of %s submissions (%s)', + result.memory_percentile.toFixed(2), result.lang, result.memory); + else + return log.warn('Failed to get memory percentile.'); + })(); + + // core.getSubmission({id: result.id}, function(e, submission) { + // if (e || !submission || !submission.distributionChart) + // return log.warn('Failed to get submission beat ratio.'); + + // const lang = submission.distributionChart.lang; + // const scores = submission.distributionChart.distribution; + // const myRuntime = parseFloat(result.runtime); + + // let ratio = 0.0; + // for (let score of scores) { + // if (parseFloat(score[0]) > myRuntime) + // ratio += parseFloat(score[1]); + // } + + // printLine(result, 'Your runtime beats %d %% of %s submissions', + // ratio.toFixed(2), lang); + // }); } else { + process.exitCode = 1; + result.testcase = result.testcase.slice(1, -1).replace(/\\n/g, '\n'); printResult(result, 'error'); printResult(result, 'testcase'); printResult(result, 'answer'); diff --git a/lib/commands/test.js b/lib/commands/test.js index 21c4a4eb..78c89849 100644 --- a/lib/commands/test.js +++ b/lib/commands/test.js @@ -36,18 +36,18 @@ const cmd = { } }; -function printResult(actual, expect, k) { +function printResult(actual, extra, k) { if (!actual.hasOwnProperty(k)) return; // HACk: leetcode still return 'Accepted' even the answer is wrong!! const v = actual[k] || ''; if (k === 'state' && v === 'Accepted') return; let ok = actual.ok; - if (expect && !_.isEqual(actual[k], expect[k])) ok = false; const lines = Array.isArray(v) ? v : [v]; for (let line of lines) { - if (k !== 'state') line = k + ': ' + line; + const extraInfo = extra ? ` (${extra})` : ''; + if (k !== 'state') line = h.startCase(k) + extraInfo + ': ' + line; log.info(' ' + h.prettyText(' ' + line, ok)); } } @@ -58,7 +58,7 @@ function runTest(argv) { const meta = file.meta(argv.filename); - core.getProblem(meta.id, function(e, problem) { + core.getProblem(meta.id, true, function(e, problem) { if (e) return log.fail(e); if (!problem.testable) @@ -73,23 +73,28 @@ function runTest(argv) { problem.file = argv.filename; problem.lang = meta.lang; - log.info('\nInput data:'); - log.info(problem.testcase); - core.testProblem(problem, function(e, results) { if (e) return log.fail(e); results = _.sortBy(results, x => x.type); - for (let i = 0; i < results.length; ++i) { - log.info(); - log.info(chalk.yellow(results[i].type)); - - printResult(results[i], null, 'state'); - printResult(results[i], null, 'runtime'); - printResult(results[i], results[i + 1], 'answer'); - printResult(results[i], results[i + 1], 'stdout'); - printResult(results[i], null, 'error'); + if (results[0].state === 'Accepted') + results[0].state = 'Finished'; + printResult(results[0], null, 'state'); + printResult(results[0], null, 'error'); + + results[0].your_input = problem.testcase; + results[0].output = results[0].answer; + // LeetCode-CN returns the actual and expected answer into two separate responses + if (results[1]) { + results[0].expected_answer = results[1].answer; } + results[0].stdout = results[0].stdout.slice(1, -1).replace(/\\n/g, '\n'); + printResult(results[0], null, 'your_input'); + printResult(results[0], results[0].runtime, 'output'); + printResult(results[0], null, 'expected_answer'); + printResult(results[0], null, 'stdout'); + log.info(); + if (!results[0].ok) process.exitCode = 1; }); }); } diff --git a/lib/commands/user.js b/lib/commands/user.js index 4cd903cd..cbbcfb7b 100644 --- a/lib/commands/user.js +++ b/lib/commands/user.js @@ -1,5 +1,4 @@ 'use strict'; -var prompt = require('prompt'); var h = require('../helper'); var config = require('../config'); @@ -15,21 +14,42 @@ const cmd = { desc: 'Manage account', builder: function(yargs) { return yargs - .option('l', { - alias: 'login', - type: 'boolean', - default: false, - describe: 'Login' - }) - .option('L', { - alias: 'logout', - type: 'boolean', - default: false, - describe: 'Logout' - }) - .example(chalk.yellow('leetcode user'), 'Show current user') - .example(chalk.yellow('leetcode user -l'), 'User login') - .example(chalk.yellow('leetcode user -L'), 'User logout'); + .option('l', { + alias: 'login', + type: 'boolean', + default: false, + describe: 'Login' + }) + .option('c', { + alias: 'cookie', + type: 'boolean', + default: false, + describe: 'cookieLogin' + }) + .option('g', { + alias: 'github', + type: 'boolean', + default: false, + describe: 'githubLogin' + }) + .option('i', { + alias: 'linkedin', + type: 'boolean', + default: false, + describe: 'linkedinLogin' + }) + .option('L', { + alias: 'logout', + type: 'boolean', + default: false, + describe: 'Logout' + }) + .example(chalk.yellow('leetcode user'), 'Show current user') + .example(chalk.yellow('leetcode user -l'), 'User login') + .example(chalk.yellow('leetcode user -c'), 'User Cookie login') + .example(chalk.yellow('leetcode user -g'), 'User GitHub login') + .example(chalk.yellow('leetcode user -i'), 'User LinkedIn login') + .example(chalk.yellow('leetcode user -L'), 'User logout'); } }; @@ -38,18 +58,15 @@ cmd.handler = function(argv) { let user = null; if (argv.login) { // login - prompt.colors = false; - prompt.message = ''; - prompt.start(); - prompt.get([ - {name: 'login', required: true}, - {name: 'pass', required: true, hidden: true} + h.readInput([ + {name: 'login'}, + {name: 'pass', hidden: true} ], function(e, user) { if (e) return log.fail(e); core.login(user, function(e, user) { if (e) return log.fail(e); - log.info('Successfully login as', chalk.yellow(user.name)); + log.info('Successfully login as', chalk.yellow(user.name || user.login)); }); }); } else if (argv.logout) { @@ -59,6 +76,41 @@ cmd.handler = function(argv) { log.info('Successfully logout as', chalk.yellow(user.name)); else log.fail('You are not login yet?'); + // third parties + } else if (argv.github || argv.linkedin) { + // add future third parties here + const functionMap = new Map( + [ + ['g', core.githubLogin], + ['github', core.githubLogin], + ['i', core.linkedinLogin], + ['linkedin', core.linkedinLogin], + ] + ); + const keyword = Object.entries(argv).filter((i) => (i[1] === true))[0][0]; + const coreFunction = functionMap.get(keyword); + h.readInput([ + {name: 'login'}, + {name: 'pass', hidden: true} + ], function(e, user) { + if (e) return log.fail(e); + coreFunction(user, function(e, user) { + if (e) return log.fail(e); + log.info('Successfully third party login as', chalk.yellow(user.name || user.login)); + }); + }); + } else if (argv.cookie) { + // session + h.readInput([ + {name: 'login'}, + {name: 'cookie'} + ], function(e, user) { + if (e) return log.fail(e); + core.cookieLogin(user, function(e, user) { + if (e) return log.fail(e); + log.info('Successfully cookie login as', chalk.yellow(user.name || user.login)); + }); + }); } else { // show current user user = session.getUser(); @@ -66,9 +118,9 @@ cmd.handler = function(argv) { log.info(chalk.gray(sprintf(' %-9s %-20s %s', 'Premium', 'User', 'Host'))); log.info(chalk.gray('-'.repeat(60))); log.printf(' %s %-20s %s', - h.prettyText('', user.paid || false), - chalk.yellow(user.name), - config.sys.urls.base); + h.prettyText('', user.paid || false), + chalk.yellow(user.name), + config.sys.urls.base); } else return log.fail('You are not login yet?'); } diff --git a/lib/commands/version.js b/lib/commands/version.js index 4ba16749..c3d45cde 100644 --- a/lib/commands/version.js +++ b/lib/commands/version.js @@ -29,7 +29,7 @@ function getVersion() { try { const commit = require('../../.env.json').commit.short; if (commit) version += '-' + commit; - } catch (e) {} + } catch {} return version; } diff --git a/lib/config.js b/lib/config.js index 373b9f0f..5d517ab8 100644 --- a/lib/config.js +++ b/lib/config.js @@ -1,6 +1,7 @@ 'use strict'; var _ = require('underscore'); var nconf = require('nconf'); +var fs = require('fs'); var file = require('./file'); @@ -10,7 +11,8 @@ const DEFAULT_CONFIG = { categories: [ 'algorithms', 'database', - 'shell' + 'shell', + 'concurrency' ], langs: [ 'bash', @@ -28,24 +30,41 @@ const DEFAULT_CONFIG = { 'ruby', 'rust', 'scala', - 'swift' + 'swift', + 'typescript' ], urls: { - base: 'https://leetcode.com', - graphql: 'https://leetcode.com/graphql', - login: 'https://leetcode.com/accounts/login/', - problems: 'https://leetcode.com/api/problems/$category/', - problem: 'https://leetcode.com/problems/$slug/description/', - test: 'https://leetcode.com/problems/$slug/interpret_solution/', - session: 'https://leetcode.com/session/', - submit: 'https://leetcode.com/problems/$slug/submit/', - submissions: 'https://leetcode.com/api/submissions/$slug', - submission: 'https://leetcode.com/submissions/detail/$id/', - verify: 'https://leetcode.com/submissions/detail/$id/check/', - favorites: 'https://leetcode.com/list/api/questions', - favorite_delete: 'https://leetcode.com/list/api/questions/$hash/$id', - plugin: 'https://github.com/skygragon/leetcode-cli-plugins/raw/master/plugins/$name.js' - } + // base urls + site: 'leetcode.com', + base: 'https://leetcode.com', + graphql: 'https://leetcode.com/graphql', + login: 'https://leetcode.com/accounts/login/', + // third part login base urls. TODO facebook google + github_login: 'https://leetcode.com/accounts/github/login/?next=%2F', + facebook_login: 'https://leetcode.com/accounts/facebook/login/?next=%2F', + linkedin_login: 'https://leetcode.com/accounts/linkedin_oauth2/login/?next=%2F', + // redirect urls + leetcode_redirect: 'https://leetcode.com/', + github_tf_redirect: 'https://github.com/sessions/two-factor', + // simulate login urls + github_login_request: 'https://github.com/login', + github_session_request: 'https://github.com/session', + github_tf_session_request: 'https://github.com/sessions/two-factor', + linkedin_login_request: 'https://www.linkedin.com/login', + linkedin_session_request: 'https://www.linkedin.com/checkpoint/lg/login-submit', + // questions urls + problems: 'https://leetcode.com/api/problems/$category/', + problem: 'https://leetcode.com/problems/$slug/description/', + test: 'https://leetcode.com/problems/$slug/interpret_solution/', + session: 'https://leetcode.com/session/', + submit: 'https://leetcode.com/problems/$slug/submit/', + submissions: 'https://leetcode.com/api/submissions/$slug', + submission: 'https://leetcode.com/submissions/detail/$id/', + verify: 'https://leetcode.com/submissions/detail/$id/check/', + favorites: 'https://leetcode.com/list/api/questions', + favorite_delete: 'https://leetcode.com/list/api/questions/$hash/$id', + plugin: 'https://raw.githubusercontent.com/leetcode-tools/leetcode-cli/master/lib/plugins/$name.js' + }, }, // but you will want change these @@ -78,16 +97,26 @@ const DEFAULT_CONFIG = { function Config() {} Config.prototype.init = function() { + // Init a default config file with default urls. + if (!fs.existsSync(file.configFile())) { + const defaultO = { + sys: { + urls: DEFAULT_CONFIG.sys.urls + } + } + fs.writeFileSync(file.configFile(), JSON.stringify(defaultO, null, 2)) + } + nconf.file('local', file.configFile()) - .add('global', {type: 'literal', store: DEFAULT_CONFIG}) - .defaults({}); + .add('global', {type: 'literal', store: DEFAULT_CONFIG}) + .defaults({}); const cfg = nconf.get(); nconf.remove('local'); nconf.remove('global'); // HACK: remove old style configs - for (let x in cfg) { + for (const x in cfg) { if (x === x.toUpperCase()) delete cfg[x]; } delete DEFAULT_CONFIG.type; diff --git a/lib/core.js b/lib/core.js index 74362f78..684cdd5f 100644 --- a/lib/core.js +++ b/lib/core.js @@ -2,6 +2,8 @@ var util = require('util'); var _ = require('underscore'); +var cheerio = require('cheerio'); +var he = require('he'); var log = require('./log'); var h = require('./helper'); @@ -59,7 +61,7 @@ const QUERY_HANDLERS = { }; core.filterProblems = function(opts, cb) { - this.getProblems(function(e, problems) { + this.getProblems(!opts.dontTranslate, function(e, problems) { if (e) return cb(e); for (let q of (opts.query || '').split('')) { @@ -80,19 +82,38 @@ core.filterProblems = function(opts, cb) { }); }; -core.getProblem = function(keyword, cb) { +core.getProblem = function(keyword, needTranslation, cb) { if (keyword.id) - return core.next.getProblem(keyword, cb); + return core.next.getProblem(keyword, needTranslation, cb); - this.getProblems(function(e, problems) { + // accept a full problem url, e.g. https://leetcode.com/problems/two-sum/ + const url = /\/problems\/([^/]+)/.exec(keyword); + if (url) keyword = url[1]; + + this.getProblems(needTranslation, function(e, problems) { if (e) return cb(e); keyword = Number(keyword) || keyword; + const metaFid = file.exist(keyword) ? Number(file.meta(keyword).id) : NaN; const problem = problems.find(function(x) { - return x.fid === keyword || x.name === keyword || x.slug === keyword; + return x.fid + '' === keyword + '' || x.fid + '' === metaFid + '' || x.name === keyword || x.slug === keyword; }); if (!problem) return cb('Problem not found!'); - core.next.getProblem(problem, cb); + core.next.getProblem(problem, needTranslation, cb); + }); +}; + +core.getProblemOfToday = function(needTranslation, cb) { + this.next.getProblemOfToday(needTranslation, function(e, slug) { + if (e) return cb(e); + + core.getProblems(needTranslation, function(e, problems) { + if (e) return cb(e); + + const problem = problems.find(x => x.slug === slug); + if (!problem) return cb('Problem not found!'); + core.next.getProblem(problem, needTranslation, cb); + }); }); }; @@ -105,6 +126,24 @@ core.starProblem = function(problem, starred, cb) { core.next.starProblem(problem, starred, cb); }; +// greedy word wrap at `width` columns, preserving existing newlines +// (replaces the abandoned `wordwrap` package) +function wordwrap(s, width) { + return s.split('\n').map(line => { + let out = '', len = 0; + for (const w of line.split(/ +/)) { + if (len > 0 && len + 1 + w.length > width) { + out += '\n' + w; + len = w.length; + } else { + out += (len > 0 ? ' ' : '') + w; + len += (len > 0 ? 1 : 0) + w.length; + } + } + return out; + }).join('\n'); +} + core.exportProblem = function(problem, opts) { const data = _.extend({}, problem); @@ -112,17 +151,21 @@ core.exportProblem = function(problem, opts) { data.app = require('./config').app || 'leetcode'; if (!data.fid) data.fid = data.id; if (!data.lang) data.lang = opts.lang; + if (!data.hints) data.hints = []; data.code = (opts.code || data.code || '').replace(/\r\n/g, '\n'); data.comment = h.langToCommentStyle(data.lang); data.percent = data.percent.toFixed(2); data.testcase = util.inspect(data.testcase || ''); if (opts.tpl === 'detailed') { - // NOTE: wordwrap internally uses '\n' as EOL, so here we have to + let desc = data.desc; + // Replace with '^' as the power operator + desc = desc.replace(/<\/sup>/gm, '').replace(//gm, '^'); + desc = he.decode(cheerio.load(desc).root().text()); + // NOTE: wrap internally uses '\n' as EOL, so here we have to // remove all '\r' in the raw string. - const desc = data.desc.replace(/\r\n/g, '\n').replace(/^ /mg, '⁠'); - const wrap = require('wordwrap')(79 - data.comment.line.length); - data.desc = wrap(desc).split('\n'); + desc = desc.replace(/\r\n/g, '\n').replace(/^ /mg, '⁠'); + data.desc = wordwrap(desc, 79 - data.comment.line.length).split('\n'); } return file.render(opts.tpl, data); diff --git a/lib/file.js b/lib/file.js index 51ea21c3..d67f38b7 100644 --- a/lib/file.js +++ b/lib/file.js @@ -1,9 +1,9 @@ 'use strict'; var fs = require('fs'); +var os = require('os'); var path = require('path'); var _ = require('underscore'); -var mkdirp = require('mkdirp'); const file = {} @@ -72,7 +72,7 @@ file.listCodeDir = function(dir) { /// general dirs & files /// file.mkdir = function(fullpath) { if (fs.existsSync(fullpath)) return; - mkdirp.sync(fullpath); + fs.mkdirSync(fullpath, {recursive: true}); }; file.exist = function(fullpath) { @@ -107,6 +107,24 @@ file.data = function(fullpath) { return fs.existsSync(fullpath) ? fs.readFileSync(fullpath).toString() : null; }; +file.codeData = function(fullpath) { + const data = this.data(fullpath); + + if (data === null) { + return null; + } + + const lines = data.split(/\r\n|\n|\r/); + const start = lines.findIndex(x => x.indexOf('@lc code=start') !== -1); + const end = lines.findIndex(x => x.indexOf('@lc code=end') !== -1); + + if (start !== -1 && end !== -1 && start + 1 <= end) { + return lines.slice(start + 1, end).join(os.EOL); + } + + return data; +}; + /// templates & metadata /// file.render = function(tpl, data) { const tplfile = path.join(this.codeDir('templates'), tpl + '.tpl'); @@ -145,7 +163,7 @@ file.meta = function(filename) { // first look into the file data const line = this.data(filename).split('\n') - .find(x => x.indexOf(' @lc ') >= 0) || ''; + .find(x => x.indexOf(' @lc app=') >= 0) || ''; line.split(' ').forEach(function(x) { const v = x.split('='); if (v.length == 2) { diff --git a/lib/helper.js b/lib/helper.js index 8806086e..176279dc 100644 --- a/lib/helper.js +++ b/lib/helper.js @@ -45,17 +45,25 @@ const LANGS = [ {lang: 'ruby', ext: '.rb', style: '#'}, {lang: 'rust', ext: '.rs', style: 'c'}, {lang: 'scala', ext: '.scala', style: 'c'}, - {lang: 'swift', ext: '.swift', style: 'c'} + {lang: 'swift', ext: '.swift', style: 'c'}, + {lang: 'typescript', ext: '.ts', style: 'c'} ]; const h = {}; h.KEYS = { - user: '../user', - stat: '../stat', - plugins: '../../plugins', - problems: 'problems', - problem: p => p.fid + '.' + p.slug + '.' + p.category + user: '../user', + stat: '../stat', + plugins: '../../plugins', + problems: 'problems', + problemsMeta: 'problemsMeta', + translation: 'translationConfig', + problem: p => p.fid + '.' + p.slug + '.' + p.category +}; + +// lodash.startCase replacement for the common snake/camel case keys +h.startCase = function(s) { + return ('' + s).split(/[_\s]+/).map(w => w ? w[0].toUpperCase() + w.slice(1) : w).join(' '); }; h.prettyState = function(state) { @@ -134,8 +142,34 @@ h.langToCommentStyle = function(lang) { const res = LANGS.find(x => x.lang === lang); return (res && res.style === 'c') ? - {start: '/*', line: ' *', end: ' */'} : - {start: res.style, line: res.style, end: res.style}; + {start: '/*', line: ' *', end: ' */', singleLine: '//'} : + {start: res.style, line: res.style, end: res.style, singleLine: res.style}; +}; + +// minimal interactive prompt on node:readline, fields: [{name, hidden}] +h.readInput = function(fields, cb) { + const readline = require('readline'); + const rl = readline.createInterface({input: process.stdin, output: process.stdout}); + const result = {}; + + (function ask(i) { + if (i >= fields.length) { + rl.close(); + return cb(null, result); + } + + const q = fields[i]; + const visible = rl.output.write.bind(rl.output); + rl.question(q.name + ': ', function(answer) { + if (q.hidden) { + delete rl.output.write; // restore echo + visible('\n'); + } + result[q.name] = answer; + ask(i + 1); + }); + if (q.hidden) rl.output.write = function() { return true; }; // mute secrets + })(0); }; h.readStdin = function(cb) { diff --git a/lib/http.js b/lib/http.js new file mode 100644 index 00000000..c6f91923 --- /dev/null +++ b/lib/http.js @@ -0,0 +1,163 @@ +'use strict'; +// Minimal drop-in for the deprecated `request` library, backed by axios. +// Preserves the callback semantics the codebase relies on: +// http(opts, cb) / http.post(opts, cb) -> cb(e, resp, body) +// resp.statusCode, resp.headers, resp.request.uri.href +// opts.json (json body + parsed response), opts.form (urlencoded body) +// http.defaults({jar: true, headers}) for cookie-aware login flows +// http.debug for -vv tracing +// HTTP error statuses resolve normally so plugin.checkError stays the +// single place mapping them to errors. +var axios = require('axios'); + +var http = function(opts, cb) { + if (typeof opts === 'string') opts = {url: opts}; + send(null, opts, cb); +}; + +http.debug = false; + +function trace(line) { + // matches the 'REQUEST ' prefix cli.js routes to log.trace + if (http.debug) console.error(line); +} + +function parseSetCookie(line) { + var kv = line.split(';')[0].split('='); + return kv.length < 2 ? null : [kv[0].trim(), kv.slice(1).join('=').trim()]; +} + +function encodeForm(form) { + return Object.keys(form).map(function(k) { + return encodeURIComponent(k) + '=' + encodeURIComponent(form[k]); + }).join('&'); +} + +function buildConfig(opts) { + var headers = Object.assign({}, opts.headers); + // some CDNs reject the default axios user agent + if (!headers['User-Agent']) headers['User-Agent'] = 'leetcode-cli'; + var conf = { + url: opts.url, + method: (opts.method || 'GET').toUpperCase(), + headers: headers, + maxRedirects: 0, // redirects are handled here for cookie control + validateStatus: function() { return true; }, // checkError owns statuses + transformResponse: function(d) { return d; }, // no auto JSON.parse + responseType: opts.responseType || 'text' + }; + if (opts.json) { + conf.data = JSON.stringify(opts.body || {}); + conf.headers['Content-Type'] = 'application/json'; + } else if (opts.form) { + conf.data = encodeForm(opts.form); + conf.headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } else if (opts.body !== undefined && conf.method !== 'GET') { + conf.data = opts.body; + } + return conf; +} + +function shim(resp, finalUrl) { + return { + statusCode: resp.status, + headers: Object.assign({}, resp.headers), + request: {uri: {href: finalUrl}} + }; +} + +function domainOf(url) { + try { return new URL(url).hostname; } catch { return ''; } +} + +function send(jar, opts, cb) { + var conf = buildConfig(opts); + if (jar) { + var host = domainOf(conf.url); + var cookie = Object.keys(jar).filter(function(k) { + return host === k || host.endsWith('.' + k); + }).map(function(k) { + return Object.keys(jar[k]).map(function(name) { + return name + '=' + jar[k][name]; + }).join('; '); + }).join('; '); + if (cookie) conf.headers['Cookie'] = cookie; + } + + trace('REQUEST ' + conf.method + ' ' + conf.url); + axios.request(conf).then(function(resp) { + // persist cookies from this hop + var setCookies = resp.headers['set-cookie']; + if (jar && Array.isArray(setCookies)) { + var host = domainOf(conf.url); + jar[host] = jar[host] || {}; + setCookies.forEach(function(line) { + var kv = parseSetCookie(line); + if (kv) jar[host][kv[0]] = kv[1]; + }); + } + + var status = resp.status; + var location = resp.headers['location']; + var canFollow = conf.method === 'GET' || conf.method === 'HEAD' || + opts.followAllRedirects; + if (location && canFollow && [301, 302, 303, 307, 308].includes(status)) { + var next = new URL(location, conf.url).href; + trace(' REDIRECT ' + status + ' -> ' + next); + var hop = Object.assign({}, opts, { + url: next, + method: [301, 302, 303].includes(status) && conf.method !== 'HEAD' ? + 'GET' : conf.method, + json: false, + body: undefined, + form: undefined, + headers: Object.assign({}, opts.headers) + }); + return send(jar, hop, cb); + } + + trace(' RESPONSE ' + status + ' ' + conf.url); + var shimResp = shim(resp, conf.url); + var body = resp.data; + if (opts.json && typeof body === 'string') { + try { body = JSON.parse(body); } catch { /* keep raw */ } + } + return cb(null, shimResp, body); + }).catch(function(err) { + return cb(err); + }); +} + +http.request = http; + +http.post = function(opts, cb) { + opts = Object.assign({}, opts, {method: 'POST'}); + http.request(opts, cb); +}; + +http.get = function(opts, cb) { + if (typeof opts === 'string') opts = {url: opts}; + opts = Object.assign({}, opts, {method: 'GET'}); + http.request(opts, cb); +}; + +// request.defaults({jar: true, headers}) equivalent +http.defaults = function(conf) { + var jar = conf.jar ? {} : null; + var baseHeaders = conf.headers || {}; + var bound = function(opts, cb) { + opts = Object.assign({}, opts); + opts.headers = Object.assign({}, baseHeaders, opts.headers); + send(jar, opts, cb); + }; + bound.post = function(opts, cb) { + bound(Object.assign({}, opts, {method: 'POST'}), cb); + }; + bound.get = function(opts, cb) { + if (typeof opts === 'string') opts = {url: opts}; + bound(Object.assign({}, opts, {method: 'GET'}), cb); + }; + return bound; +}; + +module.exports = http; diff --git a/lib/log.js b/lib/log.js index 394b356c..33b29101 100644 --- a/lib/log.js +++ b/lib/log.js @@ -25,6 +25,8 @@ log.isEnabled = function(name) { }; log.fail = function(e) { + // signal failure to scripts without killing batch runs mid-way + process.exitCode = 1; let msg = sprintf('%s', (e.msg || e)); if (e.statusCode) { msg += sprintf(' [code=%s]', e.statusCode); @@ -52,7 +54,7 @@ log.init = function() { const args = Array.from(arguments); if (name !== 'INFO') args.unshift('[' + name + ']'); - let s = args.map(x => x.toString()).join(' '); + let s = args.map(x => (x === null || x === undefined) ? '' : x.toString()).join(' '); if (level.color) s = chalk[level.color](s); this.output(s); diff --git a/lib/plugin.js b/lib/plugin.js index bbd6da44..06137f54 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -4,7 +4,7 @@ var fs = require('fs'); var path = require('path'); var _ = require('underscore'); -var request = require('request'); +var request = require('./http'); var h = require('./helper'); var file = require('./file'); @@ -66,7 +66,7 @@ Plugin.prototype.save = function() { Plugin.prototype.install = function(cb) { if (this.deps.length === 0) return cb(); - const cmd = 'npm install --save ' + this.deps.join(' '); + const cmd = 'pnpm add ' + this.deps.join(' '); log.debug(cmd); const spin = h.spin(cmd); cp.exec(cmd, {cwd: file.codeDir()}, function(e) { @@ -149,18 +149,9 @@ Plugin.copy = function(src, cb) { } const dst = file.pluginFile(src); - const srcstream = src.startsWith('https://') ? request(src) : fs.createReadStream(src); const dststream = fs.createWriteStream(dst); let error; - srcstream.on('response', function(resp) { - if (resp.statusCode !== 200) - srcstream.emit('error', 'HTTP Error: ' + resp.statusCode); - }); - srcstream.on('error', function(e) { - dststream.emit('error', e); - }); - dststream.on('error', function(e) { error = e; dststream.end(); @@ -173,7 +164,27 @@ Plugin.copy = function(src, cb) { log.debug('copying from ' + src); const spin = h.spin('Downloading ' + src); - srcstream.pipe(dststream); + + if (src.startsWith('https://')) { + request({url: src, responseType: 'stream'}, function(e, resp, srcstream) { + if (e) { + dststream.emit('error', e); + } else if (resp.statusCode !== 200) { + dststream.emit('error', 'HTTP Error: ' + resp.statusCode); + } else { + srcstream.on('error', function(e2) { + dststream.emit('error', e2); + }); + srcstream.pipe(dststream); + } + }); + } else { + const srcstream = fs.createReadStream(src); + srcstream.on('error', function(e) { + dststream.emit('error', e); + }); + srcstream.pipe(dststream); + } }; Plugin.install = function(name, cb) { diff --git a/lib/plugins/cache.js b/lib/plugins/cache.js index 677c6c84..c1070d00 100644 --- a/lib/plugins/cache.js +++ b/lib/plugins/cache.js @@ -9,31 +9,77 @@ var session = require('../session'); const plugin = new Plugin(50, 'cache', '', 'Plugin to provide local cache.'); -plugin.getProblems = function(cb) { +// the problem list embeds per-user solve state which goes stale silently, +// so only trust it within a TTL instead of forever. Bump VERSION whenever +// the list gains new fields, so existing caches refresh once. +const PROBLEMS_TTL_MS = 24 * 60 * 60 * 1000; +const PROBLEMS_META_VERSION = 2; + +function problemsCacheFresh() { + const meta = cache.get(h.KEYS.problemsMeta); + return Boolean(meta) && meta.v === PROBLEMS_META_VERSION && + (Date.now() - meta.fetchedAt) < PROBLEMS_TTL_MS; +} + +// this function will clear all caches if needTranslation is different than stored +// it will also store the new needTranslation into cache automatically +function clearCacheIfTchanged(needTranslation) { + const translationConfig = cache.get(h.KEYS.translation); + if (!translationConfig || translationConfig['useEndpointTranslation'] != needTranslation) { + // cache doesn't have the key => old cache version, need to update + // or cache does have the key but it contains a different value + cache.deleteAll(); + cache.set(h.KEYS.translation, { useEndpointTranslation: needTranslation }); + log.debug('cache cleared: -T option changed'); + } +} + +plugin.getProblems = function (needTranslation, cb) { + clearCacheIfTchanged(needTranslation); const problems = cache.get(h.KEYS.problems); - if (problems) { + if (problems && problemsCacheFresh()) { log.debug('cache hit: problems.json'); return cb(null, problems); } - plugin.next.getProblems(function(e, problems) { - if (e) return cb(e); + if (problems) log.debug('cache expired: problems.json'); - cache.set(h.KEYS.problems, problems); - return cb(null, problems); + plugin.next.getProblems(needTranslation, function(e, newProblems) { + if (e) { + // better to serve the stale list than nothing, e.g. when offline + if (problems) { + log.warn('Failed to refresh problems: ' + (e.msg || e) + ', using stale cache'); + return cb(null, problems); + } + return cb(e); + } + + cache.set(h.KEYS.problems, newProblems); + cache.set(h.KEYS.problemsMeta, {fetchedAt: Date.now(), v: PROBLEMS_META_VERSION}); + return cb(null, newProblems); }); }; -plugin.getProblem = function(problem, cb) { +plugin.getProblem = function (problem, needTranslation, cb) { + clearCacheIfTchanged(needTranslation); const k = h.KEYS.problem(problem); const _problem = cache.get(k); if (_problem) { - log.debug('cache hit: ' + k + '.json'); - _.extendOwn(problem, _problem); - return cb(null, problem); + if (!_problem.desc.includes('
')) {
+      // do not hit problem without html tags in desc (
 always exists for presenting testcase)
+      log.debug('cache discarded for being no longer valid: ' + k + '.json');
+    } else if (!['likes', 'dislikes', 'hints'].every(p => p in _problem)) {
+      // do not hit problem missing newer fields (logic will be improved in new lib)
+      log.debug('cache discarded for being too old: ' + k + '.json');
+    } else {
+      // cache hit
+      log.debug('cache hit: ' + k + '.json');
+      _.extendOwn(problem, _problem);
+      return cb(null, problem);
+    }
   }
 
-  plugin.next.getProblem(problem, function(e, _problem) {
+  plugin.next.getProblem(problem, needTranslation, function(e, _problem) {
     if (e) return cb(e);
 
     plugin.saveProblem(_problem);
@@ -60,14 +106,25 @@ plugin.updateProblem = function(problem, kv) {
   return cache.set(h.KEYS.problems, problems);
 };
 
-plugin.login = function(user, cb) {
-  this.logout(user, false);
-  plugin.next.login(user, function(e, user) {
-    if (e) return cb(e);
-    session.saveUser(user);
-    return cb(null, user);
-  });
-};
+// purge user related caches whenever a new session is established, no matter
+// which login method is used, so a different account never sees the previous
+// account's solve state. NOTE: use `plugin` instead of `this` here, some
+// commands call these methods detached from the plugin object.
+function loginWith(method) {
+  return function(user, cb) {
+    plugin.logout(user, false);
+    plugin.next[method](user, function(e, user) {
+      if (e) return cb(e);
+      session.saveUser(user);
+      return cb(null, user);
+    });
+  };
+}
+
+plugin.login = loginWith('login');
+plugin.cookieLogin = loginWith('cookieLogin');
+plugin.githubLogin = loginWith('githubLogin');
+plugin.linkedinLogin = loginWith('linkedinLogin');
 
 plugin.logout = function(user, purge) {
   if (!user) user = session.getUser();
diff --git a/lib/plugins/company.js b/lib/plugins/company.js
new file mode 100644
index 00000000..68cd2ac8
--- /dev/null
+++ b/lib/plugins/company.js
@@ -0,0 +1,1531 @@
+var Plugin = require('../plugin');
+
+//
+// [Usage]
+//
+// https://github.com/skygragon/leetcode-cli-plugins/blob/master/docs/company.md
+//
+var plugin = new Plugin(100, 'company', '2017.12.18',
+    'Plugin to query by company for free user.');
+
+// NOTE: those data is collected from different websites that has similar questions:
+// * careercup.com
+// * lintcode.com
+// * 1point3acres.com
+// * other results from google search
+var COMPONIES = {
+  '1': ['adobe', 'airbnb', 'amazon', 'apple', 'bloomberg', 'dropbox', 'facebook', 'linkedin', 'microsoft', 'uber', 'yahoo', 'yelp'],
+  '2': ['adobe', 'airbnb', 'amazon', 'bloomberg', 'microsoft'],
+  '3': ['adobe', 'amazon', 'bloomberg', 'yelp'],
+  '4': ['adobe', 'apple', 'dropbox', 'google', 'microsoft', 'yahoo', 'zenefits'],
+  '5': ['amazon', 'bloomberg', 'microsoft'],
+  '7': ['apple', 'bloomberg'],
+  '8': ['amazon', 'bloomberg', 'microsoft', 'uber'],
+
+  '10': ['airbnb', 'facebook', 'google', 'twitter', 'uber'],
+  '11': ['bloomberg'],
+  '12': ['twitter'],
+  '13': ['bloomberg', 'facebook', 'microsoft', 'uber', 'yahoo'],
+  '14': ['yelp'],
+  '15': ['adobe', 'amazon', 'bloomberg', 'facebook', 'microsoft'],
+  '16': ['bloomberg'],
+  '17': ['amazon', 'dropbox', 'facebook', 'google', 'uber'],
+  '18': ['linkedin'],
+  '20': ['airbnb', 'amazon', 'bloomberg', 'facebook', 'google', 'microsoft', 'twitter', 'zenefits'],
+  '21': ['amazon', 'apple', 'linkedin', 'microsoft'],
+  '22': ['google', 'uber', 'zenefits'],
+  '23': ['airbnb', 'amazon', 'facebook', 'google', 'linkedin', 'microsoft', 'twitter', 'uber'],
+  '24': ['bloomberg', 'microsoft', 'uber'],
+  '25': ['facebook', 'microsoft'],
+  '26': ['bloomberg', 'facebook', 'microsoft'],
+  '28': ['apple', 'facebook', 'microsoft', 'pocketgems'],
+  '31': ['google'],
+  '33': ['bloomberg', 'facebook', 'linkedin', 'microsoft', 'uber'],
+  '34': ['linkedin'],
+  '36': ['apple', 'snapchat', 'uber'],
+  '37': ['snapchat', 'uber'],
+  '38': ['facebook'],
+  '39': ['snapchat', 'uber'],
+  '40': ['snapchat'],
+  '42': ['amazon', 'apple', 'bloomberg', 'google', 'twitter', 'zenefits'],
+  '43': ['facebook', 'twitter'],
+  '44': ['facebook', 'google', 'snapchat', 'twitter', 'twosigma'],
+  '46': ['linkedin', 'microsoft'],
+  '47': ['linkedin', 'microsoft'],
+  '48': ['amazon', 'apple', 'microsoft'],
+  '49': ['amazon', 'bloomberg', 'facebook', 'uber', 'yelp'],
+  '50': ['bloomberg', 'facebook', 'google', 'linkedin'],
+  '52': ['zenefits'],
+  '53': ['bloomberg', 'linkedin', 'microsoft'],
+  '54': ['google', 'microsoft', 'uber'],
+  '55': ['microsoft'],
+  '56': ['bloomberg', 'facebook', 'google', 'linkedin', 'microsoft', 'twitter', 'yelp'],
+  '57': ['facebook', 'google', 'linkedin'],
+  '60': ['twitter'],
+  '62': ['bloomberg'],
+  '63': ['bloomberg'],
+  '65': ['linkedin'],
+  '66': ['google'],
+  '67': ['facebook'],
+  '68': ['airbnb', 'facebook', 'linkedin'],
+  '69': ['apple', 'bloomberg', 'facebook'],
+  '70': ['adobe', 'apple'],
+  '71': ['facebook', 'microsoft'],
+  '73': ['amazon', 'microsoft'],
+  '75': ['facebook', 'microsoft', 'pocketgems'],
+  '76': ['facebook', 'linkedin', 'snapchat', 'uber'],
+  '78': ['amazon', 'bloomberg', 'facebook', 'uber'],
+  '79': ['bloomberg', 'facebook', 'microsoft'],
+  '80': ['facebook'],
+  '85': ['facebook'],
+  '88': ['bloomberg', 'facebook', 'microsoft'],
+  '89': ['amazon'],
+  '90': ['facebook'],
+  '91': ['facebook', 'microsoft', 'uber'],
+  '94': ['microsoft'],
+  '96': ['snapchat'],
+  '98': ['amazon', 'bloomberg', 'facebook', 'microsoft'],
+
+  '100': ['bloomberg'],
+  '101': ['bloomberg', 'linkedin', 'microsoft'],
+  '102': ['amazon', 'apple', 'bloomberg', 'facebook', 'linkedin', 'microsoft'],
+  '103': ['bloomberg', 'linkedin', 'microsoft'],
+  '104': ['apple', 'linkedin', 'uber', 'yahoo'],
+  '105': ['bloomberg'],
+  '106': ['microsoft'],
+  '108': ['airbnb'],
+  '109': ['zenefits'],
+  '110': ['bloomberg'],
+  '112': ['microsoft'],
+  '113': ['bloomberg'],
+  '114': ['microsoft'],
+  '116': ['microsoft'],
+  '117': ['bloomberg', 'facebook', 'microsoft'],
+  '118': ['apple', 'twitter'],
+  '119': ['amazon'],
+  '121': ['amazon', 'bloomberg', 'facebook', 'microsoft', 'uber'],
+  '122': ['bloomberg'],
+  '124': ['baidu', 'microsoft'],
+  '125': ['facebook', 'microsoft', 'uber', 'zenefits'],
+  '126': ['amazon', 'yelp'],
+  '127': ['amazon', 'facebook', 'linkedin', 'snapchat', 'yelp'],
+  '128': ['facebook', 'google'],
+  '131': ['bloomberg'],
+  '133': ['facebook', 'google', 'pocketgems', 'uber'],
+  '136': ['airbnb', 'palantir'],
+  '138': ['amazon', 'bloomberg', 'microsoft', 'uber'],
+  '139': ['amazon', 'bloomberg', 'facebook', 'google', 'pocketgems', 'uber', 'yahoo'],
+  '140': ['dropbox', 'google', 'snapchat', 'twitter', 'uber'],
+  '141': ['amazon', 'bloomberg', 'microsoft', 'yahoo'],
+  '146': ['amazon', 'bloomberg', 'facebook', 'google', 'microsoft', 'palantir', 'snapchat', 'twitter', 'uber', 'yahoo', 'zenefits'],
+  '149': ['apple', 'linkedin', 'twitter'],
+  '150': ['linkedin'],
+  '151': ['apple', 'bloomberg', 'microsoft', 'snapchat', 'yelp'],
+  '152': ['linkedin'],
+  '153': ['microsoft'],
+  '155': ['amazon', 'bloomberg', 'google', 'snapchat', 'uber', 'zenefits'],
+  '156': ['linkedin'],
+  '157': ['facebook'],
+  '158': ['bloomberg', 'facebook', 'google'],
+  '159': ['google'],
+  '160': ['airbnb', 'amazon', 'bloomberg', 'microsoft'],
+  '161': ['facebook', 'snapchat', 'twitter', 'uber'],
+  '162': ['google', 'microsoft'],
+  '163': ['google'],
+  '165': ['apple', 'microsoft'],
+  '166': ['google'],
+  '167': ['amazon'],
+  '168': ['facebook', 'microsoft', 'zenefits'],
+  '169': ['adobe', 'zenefits'],
+  '170': ['linkedin'],
+  '171': ['microsoft', 'uber'],
+  '172': ['bloomberg'],
+  '173': ['facebook', 'google', 'linkedin', 'microsoft'],
+  '174': ['microsoft'],
+  '186': ['amazon', 'microsoft', 'uber'],
+  '187': ['linkedin'],
+  '189': ['amazon', 'bloomberg', 'microsoft'],
+  '190': ['airbnb', 'apple'],
+  '191': ['apple', 'microsoft'],
+  '195': ['adobe'],
+  '198': ['airbnb', 'linkedin'],
+  '199': ['amazon'],
+  '200': ['amazon', 'facebook', 'google', 'microsoft', 'zenefits'],
+  '202': ['airbnb', 'twitter', 'uber'],
+  '204': ['amazon', 'microsoft'],
+  '205': ['linkedin'],
+  '206': ['adobe', 'amazon', 'apple', 'bloomberg', 'facebook', 'microsoft', 'snapchat', 'twitter', 'uber', 'yahoo', 'yelp', 'zenefits'],
+  '207': ['apple', 'uber', 'yelp', 'zenefits'],
+  '208': ['bloomberg', 'facebook', 'google', 'microsoft', 'twitter', 'uber'],
+  '209': ['facebook'],
+  '210': ['facebook', 'zenefits'],
+  '211': ['facebook'],
+  '212': ['airbnb', 'google', 'microsoft'],
+  '213': ['microsoft'],
+  '214': ['google', 'pocketgems'],
+  '215': ['amazon', 'apple', 'bloomberg', 'facebook', 'microsoft', 'pocketgems'],
+  '217': ['airbnb', 'palantir', 'yahoo'],
+  '218': ['facebook', 'google', 'microsoft', 'twitter', 'yelp'],
+  '219': ['airbnb', 'palantir'],
+  '220': ['airbnb', 'palantir'],
+  '221': ['airbnb', 'apple', 'facebook'],
+  '224': ['google'],
+  '225': ['bloomberg'],
+  '227': ['airbnb'],
+  '228': ['google'],
+  '229': ['zenefits'],
+  '230': ['bloomberg', 'google', 'uber'],
+  '231': ['google'],
+  '232': ['bloomberg', 'microsoft'],
+  '234': ['amazon', 'facebook'],
+  '235': ['amazon', 'facebook', 'microsoft', 'twitter'],
+  '236': ['amazon', 'apple', 'facebook', 'linkedin', 'microsoft'],
+  '237': ['adobe', 'apple', 'microsoft'],
+  '238': ['amazon', 'apple', 'facebook', 'linkedin', 'microsoft'],
+  '239': ['amazon', 'google', 'zenefits'],
+  '240': ['amazon', 'apple', 'google'],
+  '242': ['amazon', 'uber', 'yelp'],
+  '243': ['linkedin'],
+  '244': ['linkedin'],
+  '245': ['linkedin'],
+  '246': ['google'],
+  '247': ['google'],
+  '249': ['google', 'uber'],
+  '251': ['airbnb', 'google', 'twitter', 'zenefits'],
+  '252': ['facebook'],
+  '253': ['facebook', 'google', 'snapchat'],
+  '254': ['linkedin', 'uber'],
+  '255': ['zenefits'],
+  '256': ['linkedin'],
+  '257': ['apple', 'facebook', 'google'],
+  '258': ['adobe', 'microsoft'],
+  '259': ['google'],
+  '261': ['facebook', 'google', 'zenefits'],
+  '262': ['uber'],
+  '265': ['facebook'],
+  '266': ['bloomberg', 'google', 'uber'],
+  '268': ['bloomberg', 'microsoft'],
+  '269': ['airbnb', 'facebook', 'google', 'pocketgems', 'snapchat', 'twitter'],
+  '270': ['google', 'microsoft', 'snapchat'],
+  '271': ['google'],
+  '272': ['google'],
+  '273': ['facebook', 'microsoft'],
+  '274': ['bloomberg', 'facebook', 'google'],
+  '275': ['facebook'],
+  '276': ['google'],
+  '277': ['facebook', 'linkedin'],
+  '278': ['facebook'],
+  '279': ['google'],
+  '280': ['google'],
+  '281': ['google'],
+  '282': ['facebook', 'google'],
+  '283': ['bloomberg', 'facebook'],
+  '284': ['apple', 'google', 'yahoo'],
+  '285': ['facebook', 'microsoft', 'pocketgems'],
+  '286': ['facebook', 'google'],
+  '287': ['bloomberg'],
+  '288': ['google'],
+  '289': ['dropbox', 'google', 'snapchat', 'twosigma'],
+  '290': ['dropbox', 'uber'],
+  '291': ['dropbox', 'uber'],
+  '292': ['adobe'],
+  '293': ['google'],
+  '294': ['google'],
+  '295': ['google'],
+  '296': ['twitter'],
+  '297': ['amazon', 'bloomberg', 'facebook', 'google', 'linkedin', 'microsoft', 'uber', 'yahoo'],
+  '298': ['google'],
+  '300': ['microsoft'],
+  '301': ['facebook'],
+  '302': ['google'],
+  '303': ['palantir'],
+  '305': ['google'],
+  '308': ['google'],
+  '309': ['google'],
+  '310': ['google'],
+  '311': ['facebook', 'linkedin'],
+  '312': ['google', 'snapchat'],
+  '313': ['google'],
+  '314': ['facebook', 'google', 'snapchat'],
+  '315': ['google'],
+  '316': ['google'],
+  '317': ['google', 'zenefits'],
+  '318': ['google'],
+  '320': ['google'],
+  '321': ['google'],
+  '323': ['google', 'twitter'],
+  '324': ['google'],
+  '325': ['facebook', 'palantir'],
+  '326': ['google'],
+  '327': ['google'],
+  '329': ['google'],
+  '330': ['google'],
+  '331': ['google'],
+  '332': ['google'],
+  '333': ['microsoft'],
+  '334': ['facebook'],
+  '336': ['airbnb', 'google'],
+  '337': ['uber'],
+  '339': ['linkedin'],
+  '340': ['google'],
+  '341': ['facebook', 'google', 'twitter'],
+  '342': ['twosigma'],
+  '345': ['google'],
+  '346': ['google'],
+  '347': ['pocketgems', 'yelp'],
+  '348': ['google', 'microsoft'],
+  '349': ['twosigma'],
+  '351': ['google'],
+  '353': ['google'],
+  '354': ['google'],
+  '355': ['amazon', 'twitter'],
+  '356': ['google'],
+  '357': ['google'],
+  '358': ['google'],
+  '359': ['google'],
+  '360': ['google'],
+  '361': ['google'],
+  '362': ['dropbox', 'google'],
+  '363': ['google'],
+  '364': ['linkedin'],
+  '365': ['microsoft'],
+  '366': ['linkedin'],
+  '367': ['linkedin'],
+  '368': ['google'],
+  '369': ['google'],
+  '370': ['google'],
+  '373': ['google', 'uber'],
+  '374': ['google'],
+  '375': ['google'],
+  '377': ['facebook', 'google', 'snapchat'],
+  '378': ['google', 'twitter'],
+  '379': ['google'],
+  '380': ['amazon', 'facebook', 'google', 'pocketgems', 'twitter', 'uber', 'yelp'],
+  '381': ['yelp'],
+  '382': ['google'],
+  '383': ['apple'],
+  '385': ['airbnb'],
+  '386': ['bloomberg'],
+  '387': ['amazon', 'bloomberg', 'microsoft'],
+  '388': ['google'],
+  '389': ['google'],
+  '391': ['google'],
+  '393': ['google'],
+  '394': ['google', 'yelp'],
+  '395': ['baidu'],
+  '396': ['amazon'],
+  '397': ['baidu', 'google'],
+  '398': ['facebook'],
+  '399': ['google'],
+  '400': ['google'],
+  '401': ['google'],
+  '402': ['google', 'snapchat'],
+  '403': ['snapchat'],
+  '404': ['facebook'],
+  '406': ['google'],
+  '407': ['google', 'twitter'],
+  '408': ['google'],
+  '409': ['google'],
+  '410': ['baidu', 'facebook'],
+  '411': ['google'],
+  '413': ['baidu'],
+  '414': ['amazon'],
+  '415': ['airbnb', 'google'],
+  '416': ['ebay'],
+  '417': ['google'],
+  '418': ['google'],
+  '419': ['microsoft'],
+  '421': ['google'],
+  '422': ['google'],
+  '424': ['pocketgems'],
+  '425': ['google'],
+  '432': ['uber'],
+  '433': ['twitter'],
+  '438': ['amazon'],
+  '439': ['snapchat'],
+  '442': ['pocketgems'],
+  '443': ['bloomberg', 'microsoft', 'snapchat', 'yelp'],
+  '444': ['google'],
+  '445': ['bloomberg', 'microsoft'],
+  '446': ['baidu'],
+  '447': ['google'],
+  '448': ['google'],
+  '449': ['amazon'],
+  '450': ['uber'],
+  '451': ['amazon', 'google'],
+  '452': ['microsoft'],
+  '453': ['indeed'],
+  '459': ['amazon', 'google'],
+  '460': ['amazon', 'google'],
+  '461': ['facebook'],
+  '463': ['google'],
+  '464': ['linkedin'],
+  '465': ['google'],
+  '468': ['twitter'],
+  '469': ['google'],
+  '471': ['google'],
+  '474': ['google'],
+  '475': ['google'],
+  '477': ['facebook'],
+  '479': ['yahoo'],
+  '480': ['google'],
+  '481': ['google'],
+  '482': ['google'],
+  '483': ['google'],
+  '484': ['google'],
+  '485': ['google'],
+  '486': ['google'],
+  '487': ['google'],
+  '488': ['baidu'],
+  '490': ['google'],
+  '491': ['yahoo'],
+  '493': ['google'],
+  '494': ['facebook', 'google'],
+  '498': ['google'],
+  '500': ['mathworks'],
+  '501': ['google'],
+  '503': ['google'],
+  '505': ['google'],
+  '506': ['google'],
+  '508': ['amazon'],
+  '513': ['microsoft'],
+  '514': ['google'],
+  '515': ['linkedin'],
+  '516': ['amazon', 'uber'],
+  '517': ['amazon'],
+  '520': ['google'],
+  '521': ['google'],
+  '522': ['google'],
+  '523': ['facebook'],
+  '524': ['google'],
+  '525': ['facebook'],
+  '526': ['google'],
+  '527': ['google', 'snapchat'],
+  '529': ['amazon'],
+  '530': ['google'],
+  '531': ['google'],
+  '532': ['amazon'],
+  '533': ['google'],
+  '534': ['amazon', 'facebook', 'google', 'uber'],
+  '535': ['amazon', 'facebook', 'google', 'uber'],
+  '536': ['amazon'],
+  '537': ['amazon'],
+  '538': ['amazon'],
+  '541': ['google'],
+  '542': ['google'],
+  '543': ['facebook', 'google'],
+  '544': ['google'],
+  '545': ['amazon', 'google'],
+  '547': ['bloomberg', 'twosigma'],
+  '548': ['alibaba'],
+  '549': ['google'],
+  '551': ['google'],
+  '552': ['google'],
+  '553': ['amazon'],
+  '554': ['facebook'],
+  '555': ['alibaba'],
+  '556': ['bloomberg'],
+  '557': ['zappos'],
+  '560': ['google'],
+  '562': ['google'],
+  '563': ['indeed'],
+  '564': ['yelp'],
+  '566': ['mathworks'],
+  '567': ['microsoft'],
+  '568': ['google'],
+  '569': ['google'],
+  '570': ['bloomberg'],
+  '572': ['ebay', 'facebook', 'google'],
+  '576': ['baidu'],
+  '578': ['facebook'],
+  '579': ['amazon'],
+  '580': ['twitter'],
+  '581': ['google'],
+  '582': ['bloomberg'],
+  '583': ['google'],
+  '585': ['twitter'],
+  '586': ['twitter'],
+  '587': ['google'],
+  '591': ['microsoft'],
+  '597': ['facebook'],
+  '599': ['yelp'],
+  '602': ['facebook'],
+  '604': ['google'],
+  '605': ['linkedin'],
+  '606': ['amazon'],
+  '608': ['twitter'],
+  '616': ['google'],
+  '617': ['amazon'],
+  '621': ['facebook'],
+  '631': ['microsoft'],
+  '633': ['linkedin'],
+  '635': ['snapchat'],
+  '636': ['facebook', 'uber'],
+  '637': ['facebook'],
+  '638': ['google'],
+  '639': ['facebook'],
+  '640': ['amazon'],
+  '642': ['facebook', 'microsoft'],
+  '643': ['google'],
+  '644': ['google'],
+  '645': ['amazon'],
+  '646': ['amazon'],
+  '647': ['facebook', 'linkedin'],
+  '648': ['uber'],
+  '650': ['microsoft'],
+  '651': ['google', 'microsoft'],
+  '652': ['google'],
+  '653': ['facebook'],
+  '654': ['microsoft'],
+  '656': ['google'],
+  '657': ['google'],
+  '658': ['google'],
+  '659': ['google'],
+  '661': ['amazon'],
+  '662': ['amazon'],
+  '663': ['amazon'],
+  '665': ['google'],
+  '667': ['google'],
+  '668': ['google'],
+  '669': ['bloomberg'],
+  '670': ['facebook'],
+  '671': ['linkedin'],
+  '672': ['microsoft'],
+  '673': ['facebook'],
+  '674': ['facebook'],
+  '675': ['amazon'],
+  '676': ['google'],
+  '679': ['google'],
+  '680': ['facebook'],
+  '681': ['google'],
+  '682': ['amazon'],
+  '683': ['google'],
+  '684': ['google'],
+  '685': ['google'],
+  '686': ['google'],
+  '687': ['google'],
+  '689': ['facebook', 'google'],
+  '690': ['uber'],
+  '692': ['amazon', 'bloomberg', 'uber', 'yelp'],
+  '694': ['amazon'],
+  '698': ['linkedin'],
+  '699': ['uber'],
+  '711': ['amazon'],
+  '714': ['bloomberg', 'facebook'],
+  '716': ['linkedin'],
+  '719': ['google'],
+  '721': ['facebook'],
+  '722': ['microsoft'],
+  '725': ['amazon'],
+  '726': ['google'],
+  '727': ['google'],
+  '729': ['google'],
+  '730': ['linkedin'],
+  '731': ['google']
+};
+
+var TAGS = {
+  '1':    ['array','hash-table'],
+  '2':    ['linked-list','math'],
+  '3':    ['hash-table','two-pointers','string','sliding-window'],
+  '4':    ['array','binary-search','divide-and-conquer'],
+  '5':    ['string','dynamic-programming'],
+  '6':    ['string'],
+  '7':    ['math'],
+  '8':    ['math','string'],
+  '9':    ['math'],
+  '10':   ['string','dynamic-programming','backtracking'],
+  '11':   ['array','two-pointers'],
+  '12':   ['math','string'],
+  '13':   ['math','string'],
+  '14':   ['string'],
+  '15':   ['array','two-pointers'],
+  '16':   ['array','two-pointers'],
+  '17':   ['string','backtracking'],
+  '18':   ['array','hash-table','two-pointers'],
+  '19':   ['linked-list','two-pointers'],
+  '20':   ['string','stack'],
+  '21':   ['linked-list'],
+  '22':   ['string','backtracking'],
+  '23':   ['linked-list','divide-and-conquer','heap'],
+  '24':   ['linked-list'],
+  '25':   ['linked-list'],
+  '26':   ['array','two-pointers'],
+  '27':   ['array','two-pointers'],
+  '28':   ['two-pointers','string'],
+  '29':   ['math','binary-search'],
+  '30':   ['hash-table','two-pointers','string'],
+  '31':   ['array'],
+  '32':   ['string','dynamic-programming'],
+  '33':   ['array','binary-search'],
+  '34':   ['array','binary-search'],
+  '35':   ['array','binary-search'],
+  '36':   ['hash-table'],
+  '37':   ['hash-table','backtracking'],
+  '38':   ['string'],
+  '39':   ['array','backtracking'],
+  '40':   ['array','backtracking'],
+  '41':   ['array'],
+  '42':   ['array','two-pointers','stack'],
+  '43':   ['math','string'],
+  '44':   ['string','dynamic-programming','backtracking','greedy'],
+  '45':   ['array', 'greedy'],
+  '46':   ['backtracking'],
+  '47':   ['backtracking'],
+  '48':   ['array'],
+  '49':   ['hash-table','string'],
+  '50':   ['math','binary-search'],
+  '51':   ['backtracking'],
+  '52':   ['backtracking'],
+  '53':   ['array','divide-and-conquer','dynamic-programming'],
+  '54':   ['array'],
+  '55':   ['array','greedy'],
+  '56':   ['array','sort'],
+  '57':   ['array','sort'],
+  '58':   ['string'],
+  '59':   ['array'],
+  '60':   ['math','backtracking'],
+  '61':   ['linked-list','two-pointers'],
+  '62':   ['array','dynamic-programming'],
+  '63':   ['array','dynamic-programming'],
+  '64':   ['array','dynamic-programming'],
+  '65':   ['math','string'],
+  '66':   ['array'],
+  '67':   ['math','string'],
+  '68':   ['string'],
+  '69':   ['math','binary-search'],
+  '70':   ['dynamic-programming'],
+  '71':   ['string','stack'],
+  '72':   ['string','dynamic-programming'],
+  '73':   ['array'],
+  '74':   ['array','binary-search'],
+  '75':   ['array','two-pointers','sort'],
+  '76':   ['hash-table','two-pointers','string','sliding-window'],
+  '77':   ['backtracking'],
+  '78':   ['array','backtracking','bit-manipulation'],
+  '79':   ['array','backtracking'],
+  '80':   ['array','two-pointers'],
+  '81':   ['array','binary-search'],
+  '82':   ['linked-list'],
+  '83':   ['linked-list'],
+  '84':   ['array','stack'],
+  '85':   ['array','hash-table','dynamic-programming','stack'],
+  '86':   ['linked-list','two-pointers'],
+  '87':   ['string','dynamic-programming'],
+  '88':   ['array','two-pointers'],
+  '89':   ['backtracking'],
+  '90':   ['array','backtracking'],
+  '91':   ['string','dynamic-programming'],
+  '92':   ['linked-list'],
+  '93':   ['string','backtracking'],
+  '94':   ['hash-table','stack','tree'],
+  '95':   ['dynamic-programming','tree'],
+  '96':   ['dynamic-programming','tree'],
+  '97':   ['string','dynamic-programming'],
+  '98':   ['tree','depth-first-search'],
+  '99':   ['tree','depth-first-search'],
+  '100':  ['tree','depth-first-search'],
+  '101':  ['tree','depth-first-search','breadth-first-search'],
+  '102':  ['tree','breadth-first-search'],
+  '103':  ['stack','tree','breadth-first-search'],
+  '104':  ['tree','depth-first-search'],
+  '105':  ['array','tree','depth-first-search'],
+  '106':  ['array','tree','depth-first-search'],
+  '107':  ['tree','breadth-first-search'],
+  '108':  ['tree','depth-first-search'],
+  '109':  ['linked-list','depth-first-search'],
+  '110':  ['tree','depth-first-search'],
+  '111':  ['tree','depth-first-search','breadth-first-search'],
+  '112':  ['tree','depth-first-search'],
+  '113':  ['tree','depth-first-search'],
+  '114':  ['tree','depth-first-search'],
+  '115':  ['string','dynamic-programming'],
+  '116':  ['tree','depth-first-search'],
+  '117':  ['tree','depth-first-search'],
+  '118':  ['array'],
+  '119':  ['array'],
+  '120':  ['array','dynamic-programming'],
+  '121':  ['array','dynamic-programming'],
+  '122':  ['array','greedy'],
+  '123':  ['array','dynamic-programming'],
+  '124':  ['tree','depth-first-search'],
+  '125':  ['two-pointers','string'],
+  '126':  ['array','string','backtracking','breadth-first-search'],
+  '127':  ['breadth-first-search'],
+  '128':  ['array','union-find'],
+  '129':  ['tree','depth-first-search'],
+  '130':  ['depth-first-search','breadth-first-search','union-find'],
+  '131':  ['backtracking'],
+  '132':  ['dynamic-programming'],
+  '133':  ['depth-first-search','breadth-first-search','graph'],
+  '134':  ['greedy'],
+  '135':  ['greedy'],
+  '136':  ['hash-table','bit-manipulation'],
+  '137':  ['bit-manipulation'],
+  '138':  ['hash-table','linked-list'],
+  '139':  ['dynamic-programming'],
+  '140':  ['dynamic-programming','backtracking'],
+  '141':  ['linked-list','two-pointers'],
+  '142':  ['linked-list','two-pointers'],
+  '143':  ['linked-list'],
+  '144':  ['stack','tree'],
+  '145':  ['stack','tree'],
+  '146':  ['design'],
+  '147':  ['linked-list','sort'],
+  '148':  ['linked-list','sort'],
+  '149':  ['hash-table','math'],
+  '150':  ['stack'],
+  '151':  ['string'],
+  '152':  ['array','dynamic-programming'],
+  '153':  ['array','binary-search'],
+  '154':  ['array','binary-search'],
+  '155':  ['stack','design'],
+  '156':  ['tree'],
+  '157':  ['string'],
+  '158':  ['string'],
+  '159':  ['hash-table','two-pointers','string','sliding-window'],
+  '160':  ['linked-list'],
+  '161':  ['string'],
+  '162':  ['array','binary-search'],
+  '163':  ['array'],
+  '164':  ['sort'],
+  '165':  ['string'],
+  '166':  ['hash-table','math'],
+  '167':  ['array','two-pointers','binary-search'],
+  '168':  ['math'],
+  '169':  ['array','divide-and-conquer','bit-manipulation'],
+  '170':  ['hash-table','design'],
+  '171':  ['math'],
+  '172':  ['math'],
+  '173':  ['stack','tree','design'],
+  '174':  ['binary-search','dynamic-programming'],
+  '179':  ['sort'],
+  '186':  ['string'],
+  '187':  ['hash-table','bit-manipulation'],
+  '188':  ['dynamic-programming'],
+  '189':  ['array'],
+  '190':  ['bit-manipulation'],
+  '191':  ['bit-manipulation'],
+  '198':  ['dynamic-programming'],
+  '199':  ['tree','depth-first-search','breadth-first-search'],
+  '200':  ['depth-first-search','breadth-first-search','union-find'],
+  '201':  ['bit-manipulation'],
+  '202':  ['hash-table','math'],
+  '203':  ['linked-list'],
+  '204':  ['hash-table','math'],
+  '205':  ['hash-table'],
+  '206':  ['linked-list'],
+  '207':  ['depth-first-search','breadth-first-search','graph','topological-sort'],
+  '208':  ['design','trie'],
+  '209':  ['array','two-pointers','binary-search'],
+  '210':  ['depth-first-search','breadth-first-search','graph','topological-sort'],
+  '211':  ['backtracking','design','trie'],
+  '212':  ['backtracking','trie'],
+  '213':  ['dynamic-programming'],
+  '214':  ['string'],
+  '215':  ['divide-and-conquer','heap'],
+  '216':  ['array','backtracking'],
+  '217':  ['array','hash-table'],
+  '218':  ['divide-and-conquer','heap','binary-indexed-tree','segment-tree','line-sweep'],
+  '219':  ['array','hash-table'],
+  '220':  ['sort','ordered-map'],
+  '221':  ['dynamic-programming'],
+  '222':  ['binary-search','tree'],
+  '223':  ['math'],
+  '224':  ['math','stack'],
+  '225':  ['stack','design'],
+  '226':  ['tree'],
+  '227':  ['string'],
+  '228':  ['array'],
+  '229':  ['array'],
+  '230':  ['binary-search','tree'],
+  '231':  ['math','bit-manipulation'],
+  '232':  ['stack','design'],
+  '233':  ['math'],
+  '234':  ['linked-list','two-pointers'],
+  '235':  ['tree'],
+  '236':  ['tree'],
+  '237':  ['linked-list'],
+  '238':  ['array'],
+  '239':  ['heap','sliding-window'],
+  '240':  ['binary-search','divide-and-conquer'],
+  '241':  ['divide-and-conquer'],
+  '242':  ['hash-table','sort'],
+  '243':  ['array'],
+  '244':  ['hash-table','design'],
+  '245':  ['array'],
+  '246':  ['hash-table','math'],
+  '247':  ['math','recursion'],
+  '248':  ['math','recursion'],
+  '249':  ['hash-table','string'],
+  '250':  ['tree'],
+  '251':  ['design'],
+  '252':  ['sort'],
+  '253':  ['heap','greedy','sort'],
+  '254':  ['backtracking'],
+  '255':  ['stack','tree'],
+  '256':  ['dynamic-programming'],
+  '257':  ['tree','depth-first-search'],
+  '258':  ['math'],
+  '259':  ['array','two-pointers'],
+  '260':  ['bit-manipulation'],
+  '261':  ['depth-first-search','breadth-first-search','union-find','graph'],
+  '263':  ['math'],
+  '264':  ['math','dynamic-programming','heap'],
+  '265':  ['dynamic-programming'],
+  '266':  ['hash-table'],
+  '267':  ['backtracking'],
+  '268':  ['array','math','bit-manipulation'],
+  '269':  ['graph','topological-sort'],
+  '270':  ['binary-search','tree'],
+  '271':  ['string'],
+  '272':  ['stack','tree'],
+  '273':  ['math','string'],
+  '274':  ['hash-table','sort'],
+  '275':  ['binary-search'],
+  '276':  ['dynamic-programming'],
+  '277':  ['array'],
+  '278':  ['binary-search'],
+  '279':  ['math','dynamic-programming','breadth-first-search'],
+  '280':  ['array','sort'],
+  '281':  ['design'],
+  '282':  ['divide-and-conquer'],
+  '283':  ['array','two-pointers'],
+  '284':  ['design'],
+  '285':  ['tree'],
+  '286':  ['breadth-first-search'],
+  '287':  ['array','two-pointers','binary-search'],
+  '288':  ['hash-table','design'],
+  '289':  ['array'],
+  '290':  ['hash-table'],
+  '291':  ['backtracking'],
+  '292':  ['brainteaser','minimax'],
+  '293':  ['string'],
+  '294':  ['backtracking','minimax'],
+  '295':  ['heap','design'],
+  '296':  ['math','sort'],
+  '297':  ['tree','design'],
+  '298':  ['tree'],
+  '299':  ['hash-table'],
+  '300':  ['binary-search','dynamic-programming'],
+  '301':  ['depth-first-search','breadth-first-search'],
+  '302':  ['binary-search'],
+  '303':  ['dynamic-programming'],
+  '304':  ['dynamic-programming'],
+  '305':  ['union-find'],
+  '306':  ['backtracking'],
+  '307':  ['binary-indexed-tree','segment-tree'],
+  '308':  ['binary-indexed-tree','segment-tree'],
+  '309':  ['dynamic-programming'],
+  '310':  ['breadth-first-search','graph'],
+  '311':  ['hash-table'],
+  '312':  ['divide-and-conquer','dynamic-programming'],
+  '313':  ['math','heap'],
+  '314':  ['hash-table'],
+  '315':  ['binary-search','divide-and-conquer','sort','binary-indexed-tree','segment-tree'],
+  '316':  ['stack','greedy'],
+  '317':  ['breadth-first-search'],
+  '318':  ['bit-manipulation'],
+  '319':  ['math','brainteaser'],
+  '320':  ['backtracking','bit-manipulation'],
+  '321':  ['dynamic-programming','greedy'],
+  '322':  ['dynamic-programming'],
+  '323':  ['depth-first-search','breadth-first-search','union-find','graph'],
+  '324':  ['sort'],
+  '325':  ['hash-table'],
+  '326':  ['math'],
+  '327':  ['binary-search','divide-and-conquer','sort','binary-indexed-tree','segment-tree'],
+  '328':  ['linked-list'],
+  '329':  ['depth-first-search','topological-sort','memoization'],
+  '330':  ['greedy'],
+  '331':  ['stack'],
+  '332':  ['depth-first-search','graph'],
+  '333':  ['tree'],
+  '335':  ['math'],
+  '336':  ['hash-table','string','trie'],
+  '337':  ['tree','depth-first-search'],
+  '338':  ['dynamic-programming','bit-manipulation'],
+  '339':  ['depth-first-search'],
+  '340':  ['hash-table','string','sliding-window'],
+  '341':  ['stack','design'],
+  '342':  ['bit-manipulation'],
+  '343':  ['math','dynamic-programming'],
+  '344':  ['two-pointers','string'],
+  '345':  ['two-pointers','string'],
+  '346':  ['design','queue'],
+  '347':  ['hash-table','heap'],
+  '348':  ['design'],
+  '349':  ['hash-table','two-pointers','binary-search','sort'],
+  '350':  ['hash-table','two-pointers','binary-search','sort'],
+  '351':  ['dynamic-programming','backtracking'],
+  '352':  ['binary-search','ordered-map'],
+  '353':  ['design','queue'],
+  '354':  ['binary-search','dynamic-programming'],
+  '355':  ['hash-table','heap','design'],
+  '356':  ['hash-table','math'],
+  '357':  ['math','dynamic-programming','backtracking'],
+  '358':  ['hash-table','heap','greedy'],
+  '359':  ['hash-table','design'],
+  '360':  ['math','two-pointers'],
+  '361':  ['dynamic-programming'],
+  '362':  ['design'],
+  '363':  ['binary-search','dynamic-programming','queue'],
+  '364':  ['depth-first-search'],
+  '365':  ['math'],
+  '366':  ['tree','depth-first-search'],
+  '367':  ['math','binary-search'],
+  '368':  ['math','dynamic-programming'],
+  '369':  ['linked-list'],
+  '370':  ['array'],
+  '371':  ['bit-manipulation'],
+  '372':  ['math'],
+  '373':  ['heap'],
+  '374':  ['binary-search'],
+  '375':  ['dynamic-programming','minimax'],
+  '376':  ['dynamic-programming','greedy'],
+  '377':  ['dynamic-programming'],
+  '378':  ['binary-search','heap'],
+  '379':  ['linked-list','design'],
+  '380':  ['array','hash-table','design'],
+  '381':  ['array','hash-table','design'],
+  '382':  ['reservoir-sampling'],
+  '383':  ['string'],
+  '385':  ['string','stack'],
+  '387':  ['hash-table','string'],
+  '389':  ['hash-table','bit-manipulation'],
+  '391':  ['line-sweep'],
+  '392':  ['binary-search','dynamic-programming','greedy'],
+  '393':  ['bit-manipulation'],
+  '394':  ['stack','depth-first-search'],
+  '396':  ['math'],
+  '397':  ['math','bit-manipulation'],
+  '398':  ['reservoir-sampling'],
+  '399':  ['union-find','graph'],
+  '400':  ['math'],
+  '401':  ['backtracking','bit-manipulation'],
+  '402':  ['stack','greedy'],
+  '403':  ['dynamic-programming'],
+  '404':  ['tree'],
+  '405':  ['bit-manipulation'],
+  '406':  ['greedy'],
+  '407':  ['heap','breadth-first-search'],
+  '408':  ['string'],
+  '409':  ['hash-table'],
+  '410':  ['binary-search','dynamic-programming'],
+  '411':  ['backtracking','bit-manipulation'],
+  '413':  ['math','dynamic-programming'],
+  '414':  ['array'],
+  '415':  ['string'],
+  '416':  ['dynamic-programming'],
+  '417':  ['depth-first-search','breadth-first-search'],
+  '418':  ['dynamic-programming'],
+  '421':  ['bit-manipulation','trie'],
+  '423':  ['math'],
+  '424':  ['two-pointers','sliding-window'],
+  '425':  ['backtracking','trie'],
+  '432':  ['design'],
+  '434':  ['string'],
+  '435':  ['greedy'],
+  '436':  ['binary-search'],
+  '437':  ['tree'],
+  '438':  ['hash-table'],
+  '439':  ['stack','depth-first-search'],
+  '441':  ['math','binary-search'],
+  '442':  ['array'],
+  '443':  ['string'],
+  '444':  ['graph','topological-sort'],
+  '445':  ['linked-list'],
+  '446':  ['dynamic-programming'],
+  '447':  ['hash-table'],
+  '448':  ['array'],
+  '449':  ['tree'],
+  '450':  ['tree'],
+  '451':  ['hash-table','heap'],
+  '452':  ['greedy'],
+  '453':  ['math'],
+  '454':  ['hash-table','binary-search'],
+  '455':  ['greedy'],
+  '456':  ['stack'],
+  '457':  ['array','two-pointers'],
+  '458':  ['math'],
+  '459':  ['string'],
+  '460':  ['design'],
+  '461':  ['bit-manipulation'],
+  '462':  ['math'],
+  '463':  ['hash-table'],
+  '464':  ['dynamic-programming','minimax'],
+  '466':  ['dynamic-programming'],
+  '467':  ['dynamic-programming'],
+  '468':  ['string'],
+  '469':  ['math'],
+  '471':  ['dynamic-programming'],
+  '472':  ['dynamic-programming','depth-first-search','trie'],
+  '473':  ['depth-first-search'],
+  '474':  ['dynamic-programming'],
+  '475':  ['binary-search'],
+  '476':  ['bit-manipulation'],
+  '477':  ['bit-manipulation'],
+  '480':  ['sliding-window'],
+  '483':  ['math','binary-search'],
+  '484':  ['greedy'],
+  '485':  ['array'],
+  '486':  ['dynamic-programming','minimax'],
+  '487':  ['two-pointers'],
+  '488':  ['depth-first-search'],
+  '490':  ['depth-first-search','breadth-first-search'],
+  '491':  ['depth-first-search'],
+  '493':  ['binary-search','divide-and-conquer','sort','binary-indexed-tree','segment-tree'],
+  '494':  ['dynamic-programming','depth-first-search'],
+  '495':  ['array'],
+  '496':  ['stack'],
+  '499':  ['depth-first-search','breadth-first-search'],
+  '500':  ['hash-table'],
+  '501':  ['tree'],
+  '502':  ['heap','greedy'],
+  '503':  ['stack'],
+  '505':  ['depth-first-search','breadth-first-search'],
+  '507':  ['math'],
+  '508':  ['hash-table','tree'],
+  '509':  ['tree'],
+  '511':  ['depth-first-search','graph'],
+  '513':  ['tree','depth-first-search','breadth-first-search'],
+  '514':  ['divide-and-conquer','dynamic-programming','depth-first-search'],
+  '515':  ['tree','depth-first-search','breadth-first-search'],
+  '516':  ['dynamic-programming'],
+  '517':  ['math','dynamic-programming'],
+  '520':  ['string'],
+  '521':  ['string'],
+  '522':  ['string'],
+  '523':  ['math','dynamic-programming'],
+  '524':  ['two-pointers','sort'],
+  '525':  ['hash-table'],
+  '526':  ['backtracking'],
+  '527':  ['string','sort'],
+  '529':  ['depth-first-search','breadth-first-search'],
+  '530':  ['tree'],
+  '531':  ['array','depth-first-search'],
+  '532':  ['array','two-pointers'],
+  '533':  ['array','depth-first-search'],
+  '535':  ['hash-table','math'],
+  '536':  ['string','tree'],
+  '537':  ['math','string'],
+  '538':  ['tree'],
+  '539':  ['string'],
+  '541':  ['string'],
+  '542':  ['depth-first-search','breadth-first-search'],
+  '543':  ['tree'],
+  '544':  ['string','recursion'],
+  '545':  ['tree'],
+  '546':  ['dynamic-programming','depth-first-search'],
+  '547':  ['depth-first-search','union-find'],
+  '548':  ['array'],
+  '549':  ['tree'],
+  '551':  ['string'],
+  '552':  ['dynamic-programming'],
+  '553':  ['math','string'],
+  '554':  ['hash-table'],
+  '555':  ['string'],
+  '556':  ['string'],
+  '557':  ['string'],
+  '560':  ['array','hash-table'],
+  '561':  ['array'],
+  '562':  ['array'],
+  '563':  ['tree'],
+  '564':  ['string'],
+  '565':  ['array'],
+  '566':  ['array'],
+  '567':  ['two-pointers','sliding-window'],
+  '568':  ['dynamic-programming'],
+  '572':  ['tree'],
+  '573':  ['math'],
+  '575':  ['hash-table'],
+  '576':  ['dynamic-programming','depth-first-search'],
+  '581':  ['array'],
+  '582':  ['tree','queue'],
+  '583':  ['string'],
+  '587':  ['geometry'],
+  '588':  ['design'],
+  '591':  ['string','stack'],
+  '592':  ['math'],
+  '593':  ['math'],
+  '594':  ['hash-table'],
+  '598':  ['math'],
+  '599':  ['hash-table'],
+  '600':  ['dynamic-programming'],
+  '604':  ['design'],
+  '605':  ['array'],
+  '606':  ['string','tree'],
+  '609':  ['hash-table','string'],
+  '611':  ['array'],
+  '616':  ['string'],
+  '617':  ['tree'],
+  '621':  ['array','greedy','queue'],
+  '623':  ['tree'],
+  '624':  ['array','hash-table'],
+  '625':  ['math','recursion'],
+  '628':  ['array','math'],
+  '629':  ['dynamic-programming'],
+  '630':  ['greedy'],
+  '631':  ['design'],
+  '632':  ['hash-table','two-pointers','string'],
+  '633':  ['math'],
+  '634':  ['math'],
+  '635':  ['string','design'],
+  '636':  ['stack'],
+  '637':  ['tree'],
+  '638':  ['dynamic-programming','depth-first-search'],
+  '639':  ['dynamic-programming'],
+  '640':  ['math'],
+  '642':  ['design','trie'],
+  '643':  ['array'],
+  '644':  ['array','binary-search'],
+  '645':  ['hash-table','math'],
+  '646':  ['dynamic-programming'],
+  '647':  ['string','dynamic-programming'],
+  '648':  ['hash-table','trie'],
+  '649':  ['greedy'],
+  '650':  ['dynamic-programming'],
+  '651':  ['math','dynamic-programming','greedy'],
+  '652':  ['tree'],
+  '653':  ['tree'],
+  '654':  ['tree'],
+  '655':  ['tree'],
+  '656':  ['dynamic-programming'],
+  '657':  ['string'],
+  '658':  ['binary-search'],
+  '659':  ['heap','greedy'],
+  '660':  ['math'],
+  '661':  ['array'],
+  '662':  ['tree'],
+  '663':  ['tree'],
+  '664':  ['dynamic-programming','depth-first-search'],
+  '665':  ['array'],
+  '666':  ['tree'],
+  '667':  ['array'],
+  '668':  ['binary-search'],
+  '669':  ['tree'],
+  '670':  ['array','math'],
+  '671':  ['tree'],
+  '672':  ['math'],
+  '673':  ['dynamic-programming'],
+  '674':  ['array'],
+  '675':  ['breadth-first-search'],
+  '676':  ['hash-table','trie'],
+  '677':  ['trie'],
+  '678':  ['string'],
+  '679':  ['depth-first-search'],
+  '680':  ['string'],
+  '681':  ['string'],
+  '682':  ['stack'],
+  '683':  ['ordered-map'],
+  '684':  ['tree','union-find','graph'],
+  '685':  ['tree','depth-first-search','union-find','graph'],
+  '686':  ['string'],
+  '687':  ['tree','recursion'],
+  '688':  ['dynamic-programming'],
+  '689':  ['array','dynamic-programming'],
+  '690':  ['hash-table','depth-first-search','breadth-first-search'],
+  '691':  ['dynamic-programming','backtracking'],
+  '692':  ['hash-table','heap','trie'],
+  '693':  ['bit-manipulation'],
+  '694':  ['hash-table','depth-first-search'],
+  '695':  ['array','depth-first-search'],
+  '696':  ['string'],
+  '697':  ['array'],
+  '698':  ['dynamic-programming','recursion'],
+  '699':  ['segment-tree','ordered-map'],
+  '711':  ['hash-table','depth-first-search'],
+  '712':  ['dynamic-programming'],
+  '713':  ['array','two-pointers'],
+  '714':  ['array','dynamic-programming','greedy'],
+  '715':  ['segment-tree','ordered-map'],
+  '716':  ['design'],
+  '717':  ['array'],
+  '718':  ['array','hash-table','binary-search','dynamic-programming'],
+  '719':  ['array','binary-search','heap'],
+  '720':  ['hash-table','trie'],
+  '721':  ['depth-first-search','union-find'],
+  '722':  ['string'],
+  '723':  ['array','two-pointers'],
+  '724':  ['array'],
+  '725':  ['linked-list'],
+  '726':  ['hash-table','stack','recursion'],
+  '727':  ['dynamic-programming','sliding-window'],
+  '728':  ['math'],
+  '729':  ['array'],
+  '730':  ['string','dynamic-programming'],
+  '731':  ['ordered-map'],
+  '732':  ['segment-tree','ordered-map'],
+  '733':  ['depth-first-search'],
+  '734':  ['hash-table'],
+  '735':  ['stack'],
+  '736':  ['string'],
+  '737':  ['depth-first-search','union-find'],
+  '738':  ['greedy'],
+  '739':  ['hash-table','stack'],
+  '740':  ['dynamic-programming'],
+  '741':  ['dynamic-programming'],
+  '742':  ['string'],
+  '743':  ['tree'],
+  '744':  ['heap','depth-first-search','breadth-first-search','graph'],
+  '745':  ['binary-search'],
+  '746':  ['trie'],
+  '747':  ['array','dynamic-programming'],
+  '748':  ['array'],
+  '749':  ['hash-table'],
+  '750':  ['depth-first-search'],
+  '751':  ['dynamic-programming'],
+  '752':  ['bit-manipulation'],
+  '753':  ['breadth-first-search'],
+  '754':  ['math','depth-first-search'],
+  '755':  ['math'],
+  '756':  ['array'],
+  '757':  ['bit-manipulation','depth-first-search'],
+  '758':  ['linked-list','divide-and-conquer','tree'],
+  '759':  ['greedy'],
+  '760':  ['string'],
+  '761':  ['heap','greedy'],
+  '762':  ['hash-table'],
+  '763':  ['string','recursion'],
+  '764':  ['tree','breadth-first-search'],
+  '765':  ['tree'],
+  '766':  ['linked-list','depth-first-search'],
+  '767':  ['bit-manipulation'],
+  '768':  ['two-pointers','greedy'],
+  '769':  ['dynamic-programming'],
+  '770':  ['greedy','union-find','graph'],
+  '771':  ['tree'],
+  '774':  ['tree','depth-first-search','breadth-first-search'],
+  '775':  ['tree'],
+  '776':  ['tree'],
+  '777':  ['array'],
+  '778':  ['string','heap','greedy','sort'],
+  '779':  ['array'],
+  '780':  ['array'],
+  '781':  ['hash-table','string','stack'],
+  '782':  ['hash-table'],
+  '783':  ['tree'],
+  '784':  ['tree'],
+  '785':  ['string','stack'],
+  '786':  ['binary-search'],
+  '787':  ['breadth-first-search'],
+  '788':  ['binary-search'],
+  '789':  ['heap'],
+  '790':  ['array','math'],
+  '791':  ['tree','recursion'],
+  '792':  ['binary-search'],
+  '793':  ['brainteaser'],
+  '794':  ['binary-search','heap','depth-first-search','union-find'],
+  '795':  ['recursion'],
+  '796':  ['math'],
+  '797':  ['hash-table','math'],
+  '798':  ['array','math'],
+  '799':  ['tree','recursion'],
+  '800':  ['backtracking','bit-manipulation'],
+  '801':  ['depth-first-search','breadth-first-search','graph'],
+  '802':  ['binary-search','heap'],
+  '803':  ['dynamic-programming','heap','breadth-first-search'],
+  '804':  ['string'],
+  '805':  ['math'],
+  '806':  ['dynamic-programming'],
+  '807':  ['string'],
+  '808':  ['array'],
+  '809':  ['binary-search'],
+  '810':  ['math','recursion'],
+  '811':  ['array'],
+  '816':  ['hash-table','design'],
+  '817':  ['hash-table','design'],
+  '818':  ['math','string'],
+  '819':  ['dynamic-programming'],
+  '820':  ['depth-first-search','graph'],
+  '821':  ['union-find'],
+  '822':  ['string'],
+  '823':  ['math'],
+  '826':  ['dynamic-programming'],
+  '827':  ['string'],
+  '828':  ['math'],
+  '829':  ['hash-table'],
+  '830':  ['math'],
+  '831':  ['dynamic-programming'],
+  '832':  ['tree'],
+  '833':  ['breadth-first-search'],
+  '834':  ['string'],
+  '835':  ['linked-list'],
+  '836':  ['dynamic-programming','heap'],
+  '837':  ['string'],
+  '838':  ['linked-list','design'],
+  '850':  ['linked-list'],
+  '851':  ['string'],
+  '852':  ['array'],
+  '853':  ['two-pointers'],
+  '854':  ['depth-first-search'],
+  '855':  ['two-pointers'],
+  '856':  ['math'],
+  '857':  ['array'],
+  '858':  ['string'],
+  '859':  ['design','queue'],
+  '860':  ['design','queue'],
+  '861':  ['array'],
+  '862':  ['string'],
+  '863':  ['tree','depth-first-search'],
+  '864':  ['array'],
+  '865':  ['depth-first-search'],
+  '866':  ['math'],
+  '867':  ['dynamic-programming'],
+  '868':  ['two-pointers','dynamic-programming'],
+  '869':  ['depth-first-search','union-find','graph'],
+  '870':  ['array'],
+  '871':  ['depth-first-search','graph'],
+  '872':  ['string','backtracking','greedy'],
+  '873':  ['minimax'],
+  '874':  ['two-pointers','stack'],
+  '875':  ['two-pointers'],
+  '876':  ['ordered-map'],
+  '877':  ['dynamic-programming','breadth-first-search'],
+  '878':  ['string'],
+  '879':  ['array'],
+  '880':  ['segment-tree','line-sweep'],
+  '881':  ['depth-first-search'],
+  '882':  ['binary-search'],
+  '883':  ['sort'],
+  '884':  ['breadth-first-search','graph'],
+  '885':  ['ordered-map'],
+  '886':  ['string','stack'],
+  '887':  ['heap'],
+  '888':  ['math'],
+  '889':  ['string'],
+  '890':  ['greedy'],
+  '891':  ['greedy'],
+  '892':  ['binary-search','queue'],
+  '893':  ['tree','depth-first-search','breadth-first-search'],
+  '894':  ['hash-table','binary-search','sort','random'],
+  '895':  ['heap','breadth-first-search'],
+  '896':  ['tree'],
+  '897':  ['math'],
+  '898':  ['array'],
+  '899':  ['math'],
+  '900':  ['math'],
+  '901':  ['array','greedy'],
+  '902':  ['dynamic-programming','heap'],
+  '903':  ['random','rejection-sampling'],
+  '904':  ['tree','depth-first-search'],
+  '905':  ['array','dynamic-programming'],
+  '906':  ['greedy'],
+  '907':  ['binary-search'],
+  '908':  ['linked-list'],
+  '909':  ['math','dynamic-programming','minimax'],
+  '910':  ['math','binary-search'],
+  '911':  ['dynamic-programming'],
+  '912':  ['binary-search','random'],
+  '913':  ['random'],
+  '914':  ['binary-search','random'],
+  '915':  ['math','random','rejection-sampling'],
+  '916':  ['stack'],
+  '917':  ['two-pointers','greedy'],
+  '918':  ['heap'],
+  '919':  ['math'],
+  '920':  ['hash-table'],
+  '921':  ['math'],
+  '922':  ['depth-first-search'],
+  '923':  ['math','binary-search','dynamic-programming'],
+  '924':  ['array'],
+  '925':  ['tree'],
+  '926':  ['string'],
+  '927':  ['array','math'],
+  '928':  ['math','geometry'],
+  '929':  ['string'],
+  '930':  ['tree','recursion'],
+  '931':  ['hash-table','stack'],
+  '932':  ['array'],
+  '933':  ['tree','depth-first-search'],
+  '934':  ['dynamic-programming','bit-manipulation'],
+  '935':  ['math','string'],
+  '936':  ['array'],
+  '937':  ['stack'],
+  '938':  ['math','dynamic-programming'],
+  '939':  ['divide-and-conquer','dynamic-programming'],
+  '940':  ['two-pointers'],
+  '941':  ['array'],
+  '942':  ['math'],
+  '943':  ['array','stack'],
+  '944':  ['math'],
+  '945':  ['breadth-first-search'],
+  '946':  ['math','greedy'],
+  '947':  ['binary-search'],
+  '949':  ['breadth-first-search','minimax'],
+  '950':  ['array','math'],
+  '951':  ['array'],
+  '952':  ['string'],
+  '953':  ['string'],
+  '954':  ['array'],
+  '955':  ['tree'],
+  '956':  ['dynamic-programming'],
+  '957':  ['stack','greedy'],
+  '958':  ['array','sort'],
+  '959':  ['two-pointers'],
+  '960':  ['depth-first-search','union-find'],
+  '961':  ['two-pointers','string'],
+  '962':  ['array'],
+  '963':  ['math','binary-search','greedy'],
+  '964':  ['depth-first-search','union-find','graph'],
+  '965':  ['string'],
+  '966':  ['hash-table','two-pointers'],
+  '967':  ['dynamic-programming'],
+  '968':  ['divide-and-conquer'],
+  '969':  ['queue'],
+  '971':  ['depth-first-search','breadth-first-search'],
+  '972':  ['dynamic-programming'],
+  '973':  ['string','greedy'],
+  '974':  ['string'],
+  '975':  ['tree','recursion'],
+  '976':  ['hash-table'],
+  '977':  ['dynamic-programming'],
+  '978':  ['array'],
+  '979':  ['math'],
+  '980':  ['dynamic-programming'],
+  '981':  ['greedy'],
+  '982':  ['array'],
+  '983':  ['stack'],
+  '984':  ['depth-first-search','union-find'],
+  '985':  ['greedy'],
+  '986':  ['math'],
+  '987':  ['array'],
+  '988':  ['tree'],
+  '989':  ['math','union-find'],
+  '990':  ['hash-table'],
+  '991':  ['array','hash-table'],
+  '992':  ['greedy'],
+  '993':  ['dynamic-programming'],
+  '994':  ['hash-table'],
+  '998':  ['tree'],
+  '999':  ['depth-first-search','union-find','graph'],
+  '1000': ['dynamic-programming'],
+  '1001': ['hash-table'],
+  '1002': ['array'],
+  '1003': ['math','geometry'],
+  '1004': ['math','dynamic-programming'],
+  '1005': ['tree'],
+  '1006': ['hash-table','string'],
+  '1007': ['dynamic-programming'],
+  '1008': ['dynamic-programming','tree','depth-first-search'],
+  '1009': ['array','sort'],
+  '1010': ['hash-table','math'],
+  '1011': ['tree','depth-first-search'],
+  '1012': ['math'],
+  '1013': ['array'],
+  '1014': ['divide-and-conquer','heap','sort'],
+  '1016': ['array','hash-table'],
+  '1017': ['dynamic-programming','stack','ordered-map'],
+  '1018': ['math','sort'],
+  '1019': ['array','two-pointers'],
+  '1020': ['array','dynamic-programming','sliding-window'],
+  '1021': ['tree','depth-first-search'],
+  '1022': ['backtracking','depth-first-search'],
+  '1023': ['hash-table','binary-search'],
+  '1024': ['dynamic-programming'],
+  '1025': ['dynamic-programming'],
+  '1026': ['greedy'],
+  '1027': ['array'],
+  '1028': ['two-pointers'],
+  '1029': ['hash-table','tree'],
+  '1030': ['tree','depth-first-search'],
+  '1031': ['array'],
+  '1032': ['union-find','graph'],
+  '1033': ['math','greedy'],
+  '1034': ['hash-table','two-pointers','sliding-window'],
+  '1035': ['tree','breadth-first-search'],
+  '1036': ['breadth-first-search'],
+  '1037': ['greedy','sliding-window'],
+  '1038': ['math','backtracking','graph'],
+  '1039': ['graph'],
+  '1040': ['tree'],
+  '1041': ['array'],
+  '1042': ['dynamic-programming'],
+  '1043': ['hash-table'],
+  '1044': ['array','hash-table'],
+  '1045': ['string','stack'],
+  '1046': ['two-pointers','sliding-window'],
+  '1047': ['greedy'],
+  '1048': ['math'],
+  '1049': ['array','greedy'],
+  '1050': ['tree'],
+  '1051': ['dynamic-programming','greedy'],
+  '1052': ['greedy','sort'],
+  '1053': ['math','dynamic-programming','greedy'],
+  '1054': ['math'],
+  '1055': ['array'],
+  '1056': ['array','binary-search'],
+  '1057': ['math','dynamic-programming'],
+  '1058': ['depth-first-search','union-find'],
+  '1059': ['binary-search'],
+  '1060': ['string'],
+  '1061': ['stack'],
+  '1062': ['array'],
+  '1063': ['array'],
+  '1064': ['math'],
+  '1065': ['string'],
+  '1066': ['array','binary-search'],
+  '1067': ['dynamic-programming','backtracking'],
+  '1068': ['math','dynamic-programming'],
+  '1069': ['math'],
+  '1070': ['math'],
+  '1071': ['array'],
+  '1072': ['linked-list','stack'],
+  '1073': ['depth-first-search'],
+  '1075': ['string','trie'],
+  '1078': ['stack'],
+  '1079': ['tree'],
+  '1080': ['string','trie'],
+  '1081': ['dynamic-programming'],
+  '1086': ['math','dynamic-programming'],
+  '1087': ['dynamic-programming'],
+  '1092': ['tree','depth-first-search'],
+  '1093': ['tree','depth-first-search'],
+  '1094': ['sort'],
+  '1095': ['greedy'],
+  '1096': ['array'],
+  '1097': ['trie'],
+  '1103': ['brainteaser'],
+  '1104': ['depth-first-search'],
+  '1105': ['array'],
+  '1106': ['breadth-first-search'],
+  '1111': ['dynamic-programming'],
+  '1113': ['array','sliding-window'],
+  '1114': ['binary-search-tree'],
+  '1115': ['math'],
+  '1119': ['math'],
+  '1120': ['graph'],
+  '1121': ['graph'],
+  '1122': ['hash-table','binary-search'],
+  '1127': ['heap','greedy'],
+  '1128': ['stack'],
+  '1129': ['hash-table','dynamic-programming'],
+  '1130': ['dynamic-programming'],
+  '1137': ['array'],
+  '1138': ['array','sliding-window'],
+  '1139': ['array','greedy'],
+  '1140': ['heap','sort'],
+  '1145': ['array','dynamic-programming','sliding-window'],
+  '1146': ['string'],
+  '1147': ['hash-table'],
+  '1148': ['math']
+};
+
+plugin.getProblems = function(needTranslation, cb) {
+  plugin.next.getProblems(needTranslation, function(e, problems) {
+    if (e) return cb(e);
+
+    problems.forEach(function(problem) {
+      var id = String(problem.id);
+      if (id in COMPONIES) {
+        problem.companies = (problem.companies || []).concat(COMPONIES[id]);
+      }
+      if (id in TAGS) {
+        problem.tags = (problem.tags || []).concat(TAGS[id]);
+      }
+    });
+    return cb(null, problems);
+  });
+};
+
+module.exports = plugin;
diff --git a/lib/plugins/leetcode.cn.js b/lib/plugins/leetcode.cn.js
new file mode 100644
index 00000000..bf2eac2a
--- /dev/null
+++ b/lib/plugins/leetcode.cn.js
@@ -0,0 +1,172 @@
+'use strict';
+var request = require('../http');
+
+var config = require('../config');
+var h = require('../helper');
+var log = require('../log');
+var Plugin = require('../plugin');
+var session = require('../session');
+
+//
+// [Usage]
+//
+// https://github.com/skygragon/leetcode-cli-plugins/blob/master/docs/leetcode.cn.md
+//
+var plugin = new Plugin(15, 'leetcode.cn', '2018.11.25',
+    'Plugin to talk with leetcode-cn APIs.');
+
+plugin.init = function() {
+  config.app = 'leetcode.cn';
+  config.sys.urls.base              = 'https://leetcode.cn';
+  config.sys.urls.login             = 'https://leetcode.cn/accounts/login/';
+  config.sys.urls.problems          = 'https://leetcode.cn/api/problems/$category/';
+  config.sys.urls.problem           = 'https://leetcode.cn/problems/$slug/description/';
+  config.sys.urls.graphql           = 'https://leetcode.cn/graphql';
+  config.sys.urls.problem_detail    = 'https://leetcode.cn/graphql';
+  config.sys.urls.test              = 'https://leetcode.cn/problems/$slug/interpret_solution/';
+  config.sys.urls.session           = 'https://leetcode.cn/session/';
+  config.sys.urls.submit            = 'https://leetcode.cn/problems/$slug/submit/';
+  config.sys.urls.submissions       = 'https://leetcode.cn/api/submissions/$slug';
+  config.sys.urls.submission        = 'https://leetcode.cn/submissions/detail/$id/';
+  config.sys.urls.verify            = 'https://leetcode.cn/submissions/detail/$id/check/';
+  config.sys.urls.favorites         = 'https://leetcode.cn/list/api/questions';
+  config.sys.urls.favorite_delete   = 'https://leetcode.cn/list/api/questions/$hash/$id';
+  // third parties
+  config.sys.urls.github_login      = 'https://leetcode.cn/accounts/github/login/?next=%2F';
+  config.sys.urls.linkedin_login    = 'https://leetcode.cn/accounts/linkedin_oauth2/login/?next=%2F';
+  config.sys.urls.leetcode_redirect = 'https://leetcode.cn/';
+};
+
+// FIXME: refactor those
+// update options with user credentials
+function signOpts(opts, user) {
+  opts.headers.Cookie = 'LEETCODE_SESSION=' + user.sessionId +
+                        ';csrftoken=' + user.sessionCSRF + ';';
+  opts.headers['X-CSRFToken'] = user.sessionCSRF;
+  opts.headers['X-Requested-With'] = 'XMLHttpRequest';
+}
+
+function makeOpts(url) {
+  const opts = {};
+  opts.url = url;
+  opts.headers = {};
+
+  if (session.isLogin())
+    signOpts(opts, session.getUser());
+  return opts;
+}
+
+function checkError(e, resp, expectedStatus) {
+  if (!e && resp && resp.statusCode !== expectedStatus) {
+    const code = resp.statusCode;
+    log.debug('http error: ' + code);
+
+    if (code === 403 || code === 401) {
+      e = session.errors.EXPIRED;
+    } else {
+      e = {msg: 'http error', statusCode: code};
+    }
+  }
+  return e;
+}
+
+// overloading getProblems here to make sure everything related 
+//   to listing out problems can have a chance to be translated. 
+// NOTE: Details of the problem is translated inside leetcode.js
+plugin.getProblems = function (needTranslation, cb) {
+  plugin.next.getProblems(needTranslation, function(e, problems) {
+    if (e) return cb(e);
+
+    if (needTranslation) {
+      // only translate titles of the list if user requested
+      plugin.getProblemsTitle(function (e, titles) {
+        if (e) return cb(e);
+
+        problems.forEach(function (problem) {
+          const title = titles[problem.id];
+          if (title)
+            problem.name = title;
+        });
+
+        return cb(null, problems);
+      });
+    } else {
+      return cb(null, problems);
+    }
+  });
+};
+
+plugin.getProblemsTitle = function(cb) {
+  log.debug('running leetcode.cn.getProblemNames');
+
+  const opts = makeOpts(config.sys.urls.graphql);
+  opts.headers.Origin = config.sys.urls.base;
+  opts.headers.Referer = 'https://leetcode.cn/api/problems/algorithms/';
+
+  opts.json = true;
+  opts.body = {
+    query: [
+      'query getQuestionTranslation($lang: String) {',
+      '  translations: allAppliedQuestionTranslations(lang: $lang) {',
+      '    title',
+      '    questionId',
+      '    __typename',
+      '    }',
+      '}'
+    ].join('\n'),
+    variables:     {},
+    operationName: 'getQuestionTranslation'
+  };
+
+  const spin = h.spin('Downloading questions titles');
+  request.post(opts, function(e, resp, body) {
+    spin.stop();
+    e = checkError(e, resp, 200);
+    if (e) return cb(e);
+
+    const titles = [];
+    body.data.translations.forEach(function(x) {
+      titles[x.questionId] = x.title;
+    });
+
+    return cb(null, titles);
+  });
+};
+
+// the .com daily query (activeDailyCodingChallengeQuestion) doesn't exist in
+// leetcode.cn's GraphQL schema, which made `show -d` fail with http error 400.
+plugin.getProblemOfToday = function(needTranslation, cb) {
+  log.debug('running leetcode.cn.getProblemOfToday');
+
+  const opts = makeOpts(config.sys.urls.graphql);
+  opts.headers.Origin = config.sys.urls.base;
+  opts.headers.Referer = config.sys.urls.base;
+
+  opts.json = true;
+  opts.body = {
+    query: [
+      'query todayRecord {',
+      '  todayRecord {',
+      '    question {',
+      '      titleSlug',
+      '    }',
+      '  }',
+      '}'
+    ].join('\n'),
+    variables:     {},
+    operationName: 'todayRecord'
+  };
+
+  const spin = h.spin('Getting problem of today');
+  request.post(opts, function(e, resp, body) {
+    spin.stop();
+    e = checkError(e, resp, 200);
+    if (e) return cb(e);
+
+    const record = body.data && body.data.todayRecord && body.data.todayRecord[0];
+    if (!record || !record.question) return cb('failed to load problem of today!');
+    return cb(null, record.question.titleSlug);
+  });
+};
+
+module.exports = plugin;
diff --git a/lib/plugins/leetcode.js b/lib/plugins/leetcode.js
index 24331ec6..9ea80198 100644
--- a/lib/plugins/leetcode.js
+++ b/lib/plugins/leetcode.js
@@ -2,9 +2,7 @@
 var util = require('util');
 
 var _ = require('underscore');
-var cheerio = require('cheerio');
-var he = require('he');
-var request = require('request');
+var request = require('../http');
 
 var config = require('../config');
 var h = require('../helper');
@@ -19,6 +17,10 @@ const plugin = new Plugin(10, 'leetcode', '',
 
 var spin;
 
+// the REST problem list carries no tags; fetch them from the paged
+// problemset graphql endpoint and merge them into the list
+const TAG_PAGE_SIZE = 100;
+
 // update options with user credentials
 plugin.signOpts = function(opts, user) {
   opts.headers.Cookie = 'LEETCODE_SESSION=' + user.sessionId +
@@ -42,8 +44,13 @@ plugin.checkError = function(e, resp, expectedStatus) {
     const code = resp.statusCode;
     log.debug('http error: ' + code);
 
-    if (code === 403 || code === 401) {
+    // leetcode signals auth failures with 401 (REST) or 200 + empty user
+    // fields (GraphQL / problem list); a 403/429 is cloudflare blocking or
+    // rate limiting the client, not a session problem.
+    if (code === 401) {
       e = session.errors.EXPIRED;
+    } else if (code === 403 || code === 429) {
+      e = session.errors.BLOCKED;
     } else {
       e = {msg: 'http error', statusCode: code};
     }
@@ -53,9 +60,39 @@ plugin.checkError = function(e, resp, expectedStatus) {
 
 plugin.init = function() {
   config.app = 'leetcode';
-}
+};
+
+// resolve {fid: [tagSlug]} for the whole problem set
+plugin.getTags = function(cb) {
+  const map = {};
+  const fetchPage = function(skip) {
+    const opts = plugin.makeOpts(config.sys.urls.graphql);
+    opts.headers.Origin = config.sys.urls.base;
+    opts.headers.Referer = config.sys.urls.base;
+    opts.json = true;
+    opts.body = {
+      query: 'query problemTags($limit:Int!,$skip:Int!){' +
+             'problemsetQuestionListV2(limit:$limit,skip:$skip,' +
+             'filters:{filterCombineType:ALL}){hasMore questions{' +
+             'questionFrontendId topicTags{slug}}}}',
+      variables: {limit: TAG_PAGE_SIZE, skip: skip}
+    };
+    request.post(opts, function(e, resp, body) {
+      e = plugin.checkError(e, resp, 200);
+      if (e) return cb(e);
+
+      const page = body.data.problemsetQuestionListV2;
+      for (let q of page.questions) {
+        map[+q.questionFrontendId] = q.topicTags.map(t => t.slug);
+      }
+      if (page.hasMore) return fetchPage(skip + TAG_PAGE_SIZE);
+      return cb(null, map);
+    });
+  };
+  fetchPage(0);
+};
 
-plugin.getProblems = function(cb) {
+plugin.getProblems = function (needTranslation, cb) {
   log.debug('running leetcode.getProblems');
   let problems = [];
   const getCategory = function(category, queue, cb) {
@@ -74,7 +111,17 @@ plugin.getProblems = function(cb) {
   const q = new Queue(config.sys.categories, {}, getCategory);
   q.run(null, function(e) {
     spin.stop();
-    return cb(e, problems);
+    if (e) return cb(e, problems);
+
+    plugin.getTags(function(e, tags) {
+      if (e) {
+        // the list is still useful without tags, make the gap visible
+        log.warn('Failed to fetch problem tags: ' + (e.msg || e));
+      } else {
+        for (let p of problems) p.tags = tags[p.fid] || [];
+      }
+      return cb(null, problems);
+    });
   });
 };
 
@@ -97,7 +144,7 @@ plugin.getCategoryProblems = function(category, cb) {
     }
 
     const problems = json.stat_status_pairs
-        .filter(p => !p.stat.question__hide)
+        .filter((p) => !p.stat.question__hide)
         .map(function(p) {
           return {
             state:    p.status || 'None',
@@ -118,7 +165,33 @@ plugin.getCategoryProblems = function(category, cb) {
   });
 };
 
-plugin.getProblem = function(problem, cb) {
+// Daily challenge for leetcode.com
+plugin.getProblemOfToday = function(needTranslation, cb) {
+  log.debug('running leetcode.getProblemOfToday');
+  const opts = plugin.makeOpts(config.sys.urls.graphql);
+  opts.headers.Origin = config.sys.urls.base;
+  opts.headers.Referer = config.sys.urls.base;
+
+  opts.json = true;
+  opts.body = {
+    query:         'query questionOfToday { activeDailyCodingChallengeQuestion { question { titleSlug } } }',
+    variables:     {},
+    operationName: 'questionOfToday'
+  };
+
+  const spin = h.spin('Getting problem of today');
+  request.post(opts, function(e, resp, body) {
+    spin.stop();
+    e = plugin.checkError(e, resp, 200);
+    if (e) return cb(e);
+
+    const daily = body.data.activeDailyCodingChallengeQuestion;
+    if (!daily) return cb('failed to load problem of today!');
+    return cb(null, daily.question.titleSlug);
+  });
+};
+
+plugin.getProblem = function(problem, needTranslation, cb) {
   log.debug('running leetcode.getProblem');
   const user = session.getUser();
   if (problem.locked && !user.paid) return cb('failed to load locked problem!');
@@ -134,11 +207,14 @@ plugin.getProblem = function(problem, cb) {
       '  question(titleSlug: $titleSlug) {',
       '    content',
       '    stats',
+      '    likes',
+      '    dislikes',
       '    codeDefinition',
       '    sampleTestCase',
       '    enableRunCode',
       '    metaData',
       '    translatedContent',
+      '    hints',
       '  }',
       '}'
     ].join('\n'),
@@ -157,18 +233,18 @@ plugin.getProblem = function(problem, cb) {
 
     problem.totalAC = JSON.parse(q.stats).totalAccepted;
     problem.totalSubmit = JSON.parse(q.stats).totalSubmission;
+    problem.likes = q.likes;
+    problem.dislikes = q.dislikes;
 
-    let content = q.translatedContent ? q.translatedContent : q.content;
-    // Replace  with '^' as the power operator
-    content = content.replace(/<\/sup>/gm, '').replace(//gm, '^');
-    problem.desc = he.decode(cheerio.load(content).root().text());
+    problem.desc = (q.translatedContent && needTranslation) ? q.translatedContent : q.content;
 
     problem.templates = JSON.parse(q.codeDefinition);
     problem.testcase = q.sampleTestCase;
     problem.testable = q.enableRunCode;
     problem.templateMeta = JSON.parse(q.metaData);
+    problem.hints = q.hints;
     // @si-yao: seems below property is never used.
-    //problem.discuss =  q.discussCategoryId;
+    // problem.discuss =  q.discussCategoryId;
 
     return cb(null, problem);
   });
@@ -186,7 +262,7 @@ function runCode(opts, problem, cb) {
     lang:        problem.lang,
     question_id: parseInt(problem.id, 10),
     test_mode:   false,
-    typed_code:  file.data(problem.file)
+    typed_code:  file.codeData(problem.file)
   });
 
   const spin = h.spin('Sending code to judge');
@@ -242,32 +318,38 @@ function verifyResult(task, queue, cb) {
 
 function formatResult(result) {
   const x = {
-    ok:       result.run_success,
-    answer:   result.code_answer || '',
-    runtime:  result.status_runtime || '',
-    state:    h.statusToName(result.status_code),
-    testcase: util.inspect(result.input || result.last_testcase || ''),
-    passed:   result.total_correct || 0,
-    total:    result.total_testcases || 0
+    ok:                 result.run_success,
+    lang:               result.lang,
+    runtime:            result.status_runtime || '',
+    runtime_percentile: result.runtime_percentile || '',
+    memory:             result.status_memory || '',
+    memory_percentile:  result.memory_percentile || '',
+    state:              result.status_msg,
+    testcase:           util.inspect(result.input || result.last_testcase || ''),
+    passed:             result.total_correct || 0,
+    total:              result.total_testcases || 0
   };
 
   x.error = _.chain(result)
-    .pick((v, k) => /_error$/.test(k) && v.length > 0)
-    .values()
-    .value();
-
-  if (result.judge_type === 'large') {
+      .pick((v, k) => /_error$/.test(k) && v.length > 0)
+      .values()
+      .value();
+
+  if (/[runcode|interpret].*/.test(result.submission_id)) {
+    // It's testing
+    let output = result.code_output || [];
+    if (Array.isArray(output)) {
+      output = output.join('\n');
+    }
+    x.stdout = util.inspect(output);
+    x.answer = result.code_answer;
+    // LeetCode use 'expected_code_answer' to store the expected answer
+    x.expected_answer = result.expected_code_answer;
+  } else {
+    // It's submitting
     x.answer = result.code_output;
     x.expected_answer = result.expected_output;
     x.stdout = result.std_output;
-  } else {
-    if (typeof(result.code_output) === 'string') {
-        x.stdout = util.inspect(result.code_output);
-    } else if (Array.isArray(result.code_output)) {
-        x.stdout = util.inspect(result.code_output.join('\n'));
-    } else {
-        x.stdout = util.inspect('');
-    }
   }
 
   // make sure we pass eveything!
@@ -288,8 +370,12 @@ plugin.testProblem = function(problem, cb) {
 
     const tasks = [
       {type: 'Actual', id: task.interpret_id},
-      {type: 'Expected', id: task.interpret_expected_id}
     ];
+
+    // Used by LeetCode-CN
+    if (task.interpret_expected_id) {
+      tasks.push({type: 'Expected', id: task.interpret_expected_id});
+    }
     const q = new Queue(tasks, {opts: opts, results: []}, verifyResult);
     q.run(null, function(e, ctx) {
       return cb(e, ctx.results);
@@ -324,7 +410,7 @@ plugin.getSubmissions = function(problem, cb) {
 
     // FIXME: this only return the 1st 20 submissions, we should get next if necessary.
     const submissions = JSON.parse(body).submissions_dump;
-    for (let submission of submissions)
+    for (const submission of submissions)
       submission.id = _.last(_.compact(submission.url.split('/')));
 
     return cb(null, submissions);
@@ -350,31 +436,25 @@ plugin.getSubmission = function(submission, cb) {
 
 plugin.starProblem = function(problem, starred, cb) {
   log.debug('running leetcode.starProblem');
-  const opts = plugin.makeOpts();
+  const user = session.getUser();
+  const operationName = starred ? 'addQuestionToFavorite' : 'removeQuestionFromFavorite';
+  const opts = plugin.makeOpts(config.sys.urls.graphql);
   opts.headers.Origin = config.sys.urls.base;
   opts.headers.Referer = problem.link;
 
-  const user = session.getUser();
-  if (starred) {
-    opts.url = config.sys.urls.favorites;
-    opts.method = 'POST';
-    opts.json = true;
-    opts.body = {
-      favorite_id_hash: user.hash,
-      question_id:      problem.id
-    };
-  } else {
-    opts.url = config.sys.urls.favorite_delete
-      .replace('$hash', user.hash)
-      .replace('$id', problem.id);
-    opts.method = 'DELETE';
-  }
+  opts.json = true;
+  opts.body = {
+    query:         `mutation ${operationName}($favoriteIdHash: String!, $questionId: String!) {\n  ${operationName}(favoriteIdHash: $favoriteIdHash, questionId: $questionId) {\n    ok\n    error\n    favoriteIdHash\n    questionId\n    __typename\n  }\n}\n`,
+    variables:     {favoriteIdHash: user.hash, questionId: '' + problem.id},
+    operationName: operationName
+  };
 
-  request(opts, function(e, resp, body) {
-    e = plugin.checkError(e, resp, 204);
+  const spin = h.spin(starred? 'star': 'unstar' + 'problem');
+  request.post(opts, function(e, resp, body) {
+    spin.stop();
+    e = plugin.checkError(e, resp, 200);
     if (e) return cb(e);
-
-    cb(null, starred);
+    return cb(null, starred);
   });
 };
 
@@ -402,9 +482,9 @@ plugin.getUserInfo = function(cb) {
   opts.body = {
     query: [
       '{',
-      '  user {',
+      '  userStatus {',
       '    username',
-      '    isCurrentUserPremium',
+      '    isPremium',
       '  }',
       '}'
     ].join('\n'),
@@ -417,8 +497,11 @@ plugin.getUserInfo = function(cb) {
     e = plugin.checkError(e, resp, 200);
     if (e) return cb(e);
 
-    const user = body.data.user;
-    return cb(null, user);
+    // userStatus works on both leetcode.com and leetcode.cn, while the old
+    // `user { isCurrentUserPremium }` query returns http 400 on leetcode.cn.
+    const userStatus = body.data.userStatus;
+    if (!userStatus) return cb('failed to load user status!');
+    return cb(null, userStatus);
   });
 };
 
@@ -462,8 +545,8 @@ plugin.deleteSession = function(session, cb) {
 };
 
 plugin.signin = function(user, cb) {
-  log.debug('running leetcode.signin');
-  const spin = h.spin('Signing in leetcode.com');
+  const isCN = config.app === 'leetcode.cn';
+  const spin = isCN ? h.spin('Signing in leetcode.cn') : h.spin('Signing in leetcode.com');
   request(config.sys.urls.login, function(e, resp, body) {
     spin.stop();
     e = plugin.checkError(e, resp, 200);
@@ -486,7 +569,10 @@ plugin.signin = function(user, cb) {
     };
     request.post(opts, function(e, resp, body) {
       if (e) return cb(e);
-      if (resp.statusCode !== 302) return cb('invalid password?');
+      if (resp.statusCode !== 302) {
+        return cb('password login is rejected by leetcode.com, please use ' +
+                  'cookie login instead (leetcode user -c)');
+      }
 
       user.sessionCSRF = h.getSetCookieValue(resp, 'csrftoken');
       user.sessionId = h.getSetCookieValue(resp, 'LEETCODE_SESSION');
@@ -499,7 +585,7 @@ plugin.signin = function(user, cb) {
 plugin.getUser = function(user, cb) {
   plugin.getFavorites(function(e, favorites) {
     if (!e) {
-      const f = favorites.favorites.private_favorites.find(f => f.name === 'Favorite');
+      const f = favorites.favorites.private_favorites.find((f) => f.name === 'Favorite');
       if (f) {
         user.hash = f.id_hash;
         user.name = favorites.user_name;
@@ -510,10 +596,13 @@ plugin.getUser = function(user, cb) {
       log.warn('Failed to retrieve user favorites: ' + e);
     }
 
-    plugin.getUserInfo(function(e, _user) {
-      if (!e) {
-        user.paid = _user.isCurrentUserPremium;
-        user.name = _user.username;
+    plugin.getUserInfo(function(e, userStatus) {
+      if (e) {
+        // the session itself is fine, keep the login but make the gap visible
+        log.warn('Failed to retrieve user info: ' + (e.msg || e));
+      } else {
+        user.paid = userStatus.isPremium;
+        user.name = userStatus.username;
       }
       session.saveUser(user);
       return cb(null, user);
@@ -529,4 +618,177 @@ plugin.login = function(user, cb) {
   });
 };
 
+function parseCookie(cookie) {
+  if (!cookie) return null;
+
+  const SessionPattern = /LEETCODE_SESSION=(.+?)(;|$)/;
+  const csrfPattern = /csrftoken=(.+?)(;|$)/;
+  const reCsrfResult = csrfPattern.exec(cookie);
+  const reSessionResult = SessionPattern.exec(cookie);
+  if (reSessionResult === null || reCsrfResult === null) {
+    return null;
+  }
+  return {
+    sessionId:   reSessionResult[1],
+    sessionCSRF: reCsrfResult[1],
+  };
+}
+
+function requestLeetcodeAndSave(request, leetcodeUrl, user, cb) {
+  request.get({url: leetcodeUrl}, function(e, resp, body) {
+    const redirectUri = resp.request.uri.href;
+    if (redirectUri !== config.sys.urls.leetcode_redirect) {
+      return cb('Login failed. Please make sure the credential is correct.');
+    }
+    const cookieData = parseCookie(resp.request.headers.cookie);
+    if (!cookieData) return cb('invalid cookie?');
+    user.sessionId = cookieData.sessionId;
+    user.sessionCSRF = cookieData.sessionCSRF;
+    session.saveUser(user);
+    plugin.getUser(user, cb);
+  });
+}
+
+plugin.cookieLogin = function(user, cb) {
+  const cookieData = parseCookie(user.cookie);
+  if (!cookieData) return cb('invalid cookie?');
+  user.sessionId = cookieData.sessionId;
+  user.sessionCSRF = cookieData.sessionCSRF;
+  session.saveUser(user);
+  plugin.getUser(user, cb);
+};
+
+plugin.githubLogin = function(user, cb) {
+  const urls = config.sys.urls;
+  const leetcodeUrl = urls.github_login;
+  const _request = request.defaults({jar: true});
+  _request(urls.github_login_request, function(e, resp, body) {
+    const authenticityToken = body.match(/name="authenticity_token" value="(.*?)"/);
+    let gaId = body.match(/name="ga_id" value="(.*?)"/);
+    if (!gaId) {
+      gaId = '';
+    }
+    let requiredField = body.match(/name="required_field_(.*?)"/);
+    const timestamp = body.match(/name="timestamp" value="(.*?)"/);
+    const timestampSecret = body.match(/name="timestamp_secret" value="(.*?)"/);
+
+    if (!(authenticityToken && timestamp && timestampSecret && requiredField)) {
+      return cb('Get GitHub payload failed');
+    }
+    requiredField = 'required_field_' + requiredField[1];
+    const options = {
+      url:     urls.github_session_request,
+      method:  'POST',
+      headers: {
+        'Content-Type': 'application/x-www-form-urlencoded',
+      },
+      followAllRedirects: true,
+      form:               {
+        'login':                   user.login,
+        'password':                user.pass,
+        'authenticity_token':      authenticityToken[1],
+        'commit':                  encodeURIComponent('Sign in'),
+        'ga_id':                   gaId,
+        'webauthn-support':        'supported',
+        'webauthn-iuvpaa-support': 'unsupported',
+        'return_to':               '',
+        'requiredField':           '',
+        'timestamp':               timestamp[1],
+        'timestamp_secret':        timestampSecret[1],
+      },
+    };
+    _request(options, function(e, resp, body) {
+      if (resp.statusCode !== 200) {
+        return cb('GitHub login failed');
+      }
+      if (resp.request.uri.href !== urls.github_tf_redirect) {
+        return requestLeetcodeAndSave(_request, leetcodeUrl, user, cb);
+      }
+      h.readInput([
+        {name: 'twoFactorCode'}
+      ], function(e, result) {
+        if (e) return log.fail(e);
+        const authenticityTokenTwoFactor = body.match(/name="authenticity_token" value="(.*?)"/);
+        if (authenticityTokenTwoFactor === null) {
+          return cb('Get GitHub two-factor token failed');
+        }
+        const optionsTwoFactor = {
+          url:     urls.github_tf_session_request,
+          method:  'POST',
+          headers: {
+            'Content-Type': 'application/x-www-form-urlencoded',
+          },
+          followAllRedirects: true,
+          form:               {
+            'otp':                result.twoFactorCode,
+            'authenticity_token': authenticityTokenTwoFactor[1],
+            'utf8':               encodeURIComponent('✓'),
+          },
+        };
+        _request(optionsTwoFactor, function(e, resp, body) {
+          if (resp.request.uri.href === urls.github_tf_session_request) {
+            return cb('Invalid two-factor code please check');
+          }
+          requestLeetcodeAndSave(_request, leetcodeUrl, user, cb);
+        });
+      });
+    });
+  });
+};
+
+plugin.linkedinLogin = function(user, cb) {
+  const urls = config.sys.urls;
+  const leetcodeUrl = urls.linkedin_login;
+  const _request = request.defaults({
+    jar:     true,
+    headers: {
+      'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
+    }
+  });
+  _request(urls.linkedin_login_request, function(e, resp, body) {
+    if ( resp.statusCode !== 200) {
+      return cb('Get LinkedIn session failed');
+    }
+    const csrfToken = body.match(/input type="hidden" name="csrfToken" value="(.*?)"/);
+    const loginCsrfToken = body.match(/input type="hidden" name="loginCsrfParam" value="(.*?)"/);
+    const sIdString = body.match(/input type="hidden" name="sIdString" value="(.*?)"/);
+    const pageInstance = body.match(/input type="hidden" name="pageInstance" value="(.*?)"/);
+    if (!(csrfToken && loginCsrfToken && sIdString && pageInstance)) {
+      return cb('Get LinkedIn payload failed');
+    }
+    const options = {
+      url:     urls.linkedin_session_request,
+      method:  'POST',
+      headers: {
+        'Content-Type': 'application/x-www-form-urlencoded',
+      },
+      followAllRedirects: true,
+      form:               {
+        'csrfToken':             csrfToken[1],
+        'session_key':           user.login,
+        'ac':                    2,
+        'sIdString':             sIdString[1],
+        'parentPageKey':         'd_checkpoint_lg_consumerLogin',
+        'pageInstance':          pageInstance[1],
+        'trk':                   'public_profile_nav-header-signin',
+        'authUUID':              '',
+        'session_redirect':      'https://www.linkedin.com/feed/',
+        'loginCsrfParam':        loginCsrfToken[1],
+        'fp_data':               'default',
+        '_d':                    'd',
+        'showGoogleOneTapLogin': true,
+        'controlId':             'd_checkpoint_lg_consumerLogin-login_submit_button',
+        'session_password':      user.pass,
+        'loginFlow':             'REMEMBER_ME_OPTIN'
+      },
+    };
+    _request(options, function(e, resp, body) {
+      if (resp.statusCode !== 200) {
+        return cb('LinkedIn login failed');
+      }
+      requestLeetcodeAndSave(_request, leetcodeUrl, user, cb);
+    });
+  });
+};
+
 module.exports = plugin;
diff --git a/lib/plugins/retry.js b/lib/plugins/retry.js
index 5dcf35e0..b5f29633 100644
--- a/lib/plugins/retry.js
+++ b/lib/plugins/retry.js
@@ -70,6 +70,12 @@ plugin.relogin = function(cb) {
     log.debug('relogin failed: no user found, please login again');
     return cb();
   }
+  if (!user.pass) {
+    // nothing to auto login with (e.g. cookie login); signin would only
+    // burn the retries with "invalid password?"
+    log.warn('no saved password for auto login, please re-login manually (e.g. leetcode user -c)');
+    return cb();
+  }
 
   this.login(user, function(e) {
     if (e) {
diff --git a/lib/plugins/solution.discuss.js b/lib/plugins/solution.discuss.js
new file mode 100644
index 00000000..955a8cd5
--- /dev/null
+++ b/lib/plugins/solution.discuss.js
@@ -0,0 +1,102 @@
+var request = require('../http');
+
+var log = require('../log');
+var chalk = require('../chalk');
+var Plugin = require('../plugin');
+var session = require('../session');
+
+//
+// [Usage]
+//
+// https://github.com/skygragon/leetcode-cli-plugins/blob/master/docs/solution.discuss.md
+//
+var plugin = new Plugin(200, 'solution.discuss', '2019.02.03',
+    'Plugin to fetch most voted solution in discussions.');
+
+var URL_DISCUSSES = 'https://leetcode.com/graphql';
+var URL_DISCUSS = 'https://leetcode.com/problems/$slug/solutions/$id';
+
+function getSolution(problem, lang, cb) {
+  if (!problem) return cb();
+
+  if (lang === 'python3') lang = 'python';
+
+  var opts = {
+    url:  URL_DISCUSSES,
+    json: true,
+    body: {
+      query: [
+        'query questionTopicsList($questionId: String!, $orderBy: TopicSortingOption, $skip: Int, $query: String, $first: Int!, $tags: [String!]) {',
+        '  questionTopicsList(questionId: $questionId, orderBy: $orderBy, skip: $skip, query: $query, first: $first, tags: $tags) {',
+        '    ...TopicsList',
+        '  }',
+        '}',
+        'fragment TopicsList on TopicConnection {',
+        '  totalNum',
+        '  edges {',
+        '    node {',
+        '      id',
+        '      title',
+        '      post {',
+        '        content',
+        '        voteCount',
+        '        author {',
+        '          username',
+        '        }',
+        '      }',
+        '    }',
+        '  }',
+        '}'
+      ].join('\n'),
+
+      operationName: 'questionTopicsList',
+      variables:     JSON.stringify({
+        query:      '',
+        first:      1,
+        skip:       0,
+        orderBy:    'most_votes',
+        questionId: '' + problem.id,
+        tags:       [lang]
+      })
+    }
+  };
+  request(opts, function(e, resp, body) {
+    if (e) return cb(e);
+    if (resp.statusCode !== 200)
+      return cb({msg: 'http error', statusCode: resp.statusCode});
+
+    const solutions = body.data.questionTopicsList.edges;
+    const solution = solutions.length > 0 ? solutions[0].node : null;
+    return cb(null, solution);
+  });
+}
+
+plugin.getProblem = function(problem, needTranslation, cb) {
+  plugin.next.getProblem(problem, needTranslation, function(e, problem) {
+    if (e || !session.argv.solution) return cb(e, problem);
+
+    var lang = session.argv.lang;
+    getSolution(problem, lang, function(e, solution) {
+      if (e) return cb(e);
+      if (!solution) return log.error('Solution not found for ' + lang);
+
+      var link = URL_DISCUSS.replace('$slug', problem.slug).replace('$id', solution.id);
+      var content = solution.post.content.replace(/\\n/g, '\n').replace(/\\t/g, '\t');
+
+      log.info();
+      log.info(problem.name);
+      log.info();
+      log.info(solution.title);
+      log.info();
+      log.info(chalk.underline(link));
+      log.info();
+      log.info('* Lang:    ' + lang);
+      log.info('* Author:  ' + solution.post.author.username);
+      log.info('* Votes:   ' + solution.post.voteCount);
+      log.info();
+      log.info(content);
+    });
+  });
+};
+
+module.exports = plugin;
diff --git a/lib/session.js b/lib/session.js
index 6e70ed90..803aa9e1 100644
--- a/lib/session.js
+++ b/lib/session.js
@@ -1,17 +1,22 @@
 'use strict';
+var fs = require('fs');
 var moment = require('moment');
 var _ = require('underscore');
 
 var cache = require('./cache');
 var config = require('./config');
+var file = require('./file');
 var h = require('./helper');
 
 const session = {};
 
 session.errors = {
   EXPIRED: {
-    msg:        'session expired, please login again',
+    msg:        'session expired, please re-login via cookie (leetcode user -c)',
     statusCode: -1
+  },
+  BLOCKED: {
+    msg: 'blocked by leetcode (cloudflare/rate-limit), please retry later'
   }
 };
 
@@ -24,6 +29,8 @@ session.saveUser = function(user) {
   // otherwise don't dump password for the sake of security.
   const _user = _.omit(user, config.autologin.enable ? [] : ['pass']);
   cache.set(h.KEYS.user, _user);
+  // the file holds a live session cookie, keep it private
+  fs.chmodSync(file.cacheFile(h.KEYS.user), 0o600);
 };
 
 session.deleteUser = function() {
@@ -32,6 +39,7 @@ session.deleteUser = function() {
 
 session.deleteCodingSession = function() {
   cache.del(h.KEYS.problems);
+  cache.del(h.KEYS.problemsMeta);
 };
 
 session.isLogin = function() {
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 00000000..82ed71f7
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,6178 @@
+{
+  "name": "@supergui/leetcode-cli",
+  "version": "3.0.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "@supergui/leetcode-cli",
+      "version": "3.0.0",
+      "license": "MIT",
+      "dependencies": {
+        "ansi-styles": "^3.2.1",
+        "cheerio": "0.22.0",
+        "he": "1.2.0",
+        "keytar": "^7.9.0",
+        "mkdirp": "3.0.1",
+        "moment": "^2.30.1",
+        "nconf": "0.12.1",
+        "ora": "^3.4.0",
+        "prompt": "1.3.0",
+        "request": "2.88.0",
+        "sqlite3": "^5.1.7",
+        "supports-color": "^5.5.0",
+        "underscore": "1.13.6",
+        "wordwrap": "1.0.0",
+        "yargs": "17.7.2"
+      },
+      "bin": {
+        "leetcode": "bin/leetcode"
+      },
+      "devDependencies": {
+        "chai": "5.0.0",
+        "eslint": "8.56.0",
+        "eslint-config-google": "0.14.0",
+        "mocha": "10.2.0",
+        "nock": "13.5.0",
+        "nyc": "15.1.0",
+        "pkg": "^5.8.1",
+        "rewire": "7.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@aashutoshrathi/word-wrap": {
+      "version": "1.2.6",
+      "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+      "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/@ampproject/remapping": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
+      "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.0",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/code-frame": {
+      "version": "7.23.5",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
+      "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/highlight": "^7.23.4",
+        "chalk": "^2.4.2"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/code-frame/node_modules/chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@babel/code-frame/node_modules/escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/@babel/compat-data": {
+      "version": "7.23.5",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz",
+      "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/core": {
+      "version": "7.23.7",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz",
+      "integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==",
+      "dev": true,
+      "dependencies": {
+        "@ampproject/remapping": "^2.2.0",
+        "@babel/code-frame": "^7.23.5",
+        "@babel/generator": "^7.23.6",
+        "@babel/helper-compilation-targets": "^7.23.6",
+        "@babel/helper-module-transforms": "^7.23.3",
+        "@babel/helpers": "^7.23.7",
+        "@babel/parser": "^7.23.6",
+        "@babel/template": "^7.22.15",
+        "@babel/traverse": "^7.23.7",
+        "@babel/types": "^7.23.6",
+        "convert-source-map": "^2.0.0",
+        "debug": "^4.1.0",
+        "gensync": "^1.0.0-beta.2",
+        "json5": "^2.2.3",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/babel"
+      }
+    },
+    "node_modules/@babel/core/node_modules/convert-source-map": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+      "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+      "dev": true
+    },
+    "node_modules/@babel/generator": {
+      "version": "7.23.6",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz",
+      "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.23.6",
+        "@jridgewell/gen-mapping": "^0.3.2",
+        "@jridgewell/trace-mapping": "^0.3.17",
+        "jsesc": "^2.5.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-compilation-targets": {
+      "version": "7.23.6",
+      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz",
+      "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/compat-data": "^7.23.5",
+        "@babel/helper-validator-option": "^7.23.5",
+        "browserslist": "^4.22.2",
+        "lru-cache": "^5.1.1",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-environment-visitor": {
+      "version": "7.22.20",
+      "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
+      "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-function-name": {
+      "version": "7.23.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
+      "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/template": "^7.22.15",
+        "@babel/types": "^7.23.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-hoist-variables": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
+      "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-imports": {
+      "version": "7.22.15",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
+      "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.22.15"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-transforms": {
+      "version": "7.23.3",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz",
+      "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-environment-visitor": "^7.22.20",
+        "@babel/helper-module-imports": "^7.22.15",
+        "@babel/helper-simple-access": "^7.22.5",
+        "@babel/helper-split-export-declaration": "^7.22.6",
+        "@babel/helper-validator-identifier": "^7.22.20"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-simple-access": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
+      "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-split-export-declaration": {
+      "version": "7.22.6",
+      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
+      "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-string-parser": {
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz",
+      "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.22.20",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
+      "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-option": {
+      "version": "7.23.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz",
+      "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helpers": {
+      "version": "7.23.8",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.8.tgz",
+      "integrity": "sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/template": "^7.22.15",
+        "@babel/traverse": "^7.23.7",
+        "@babel/types": "^7.23.6"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/highlight": {
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz",
+      "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-validator-identifier": "^7.22.20",
+        "chalk": "^2.4.2",
+        "js-tokens": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/highlight/node_modules/chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@babel/highlight/node_modules/escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.23.6",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz",
+      "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==",
+      "dev": true,
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/template": {
+      "version": "7.22.15",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+      "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+      "dev": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.22.13",
+        "@babel/parser": "^7.22.15",
+        "@babel/types": "^7.22.15"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/traverse": {
+      "version": "7.23.7",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz",
+      "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.23.5",
+        "@babel/generator": "^7.23.6",
+        "@babel/helper-environment-visitor": "^7.22.20",
+        "@babel/helper-function-name": "^7.23.0",
+        "@babel/helper-hoist-variables": "^7.22.5",
+        "@babel/helper-split-export-declaration": "^7.22.6",
+        "@babel/parser": "^7.23.6",
+        "@babel/types": "^7.23.6",
+        "debug": "^4.3.1",
+        "globals": "^11.1.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/traverse/node_modules/globals": {
+      "version": "11.12.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+      "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@babel/types": {
+      "version": "7.23.6",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz",
+      "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.23.4",
+        "@babel/helper-validator-identifier": "^7.22.20",
+        "to-fast-properties": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@colors/colors": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
+      "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
+      "engines": {
+        "node": ">=0.1.90"
+      }
+    },
+    "node_modules/@eslint-community/eslint-utils": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+      "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+      "dev": true,
+      "dependencies": {
+        "eslint-visitor-keys": "^3.3.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "peerDependencies": {
+        "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+      }
+    },
+    "node_modules/@eslint-community/regexpp": {
+      "version": "4.10.0",
+      "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
+      "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
+      "dev": true,
+      "engines": {
+        "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+      }
+    },
+    "node_modules/@eslint/eslintrc": {
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+      "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+      "dev": true,
+      "dependencies": {
+        "ajv": "^6.12.4",
+        "debug": "^4.3.2",
+        "espree": "^9.6.0",
+        "globals": "^13.19.0",
+        "ignore": "^5.2.0",
+        "import-fresh": "^3.2.1",
+        "js-yaml": "^4.1.0",
+        "minimatch": "^3.1.2",
+        "strip-json-comments": "^3.1.1"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/@eslint/js": {
+      "version": "8.56.0",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz",
+      "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==",
+      "dev": true,
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      }
+    },
+    "node_modules/@gar/promisify": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
+      "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/@humanwhocodes/config-array": {
+      "version": "0.11.14",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
+      "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
+      "dev": true,
+      "dependencies": {
+        "@humanwhocodes/object-schema": "^2.0.2",
+        "debug": "^4.3.1",
+        "minimatch": "^3.0.5"
+      },
+      "engines": {
+        "node": ">=10.10.0"
+      }
+    },
+    "node_modules/@humanwhocodes/module-importer": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+      "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+      "dev": true,
+      "engines": {
+        "node": ">=12.22"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/nzakas"
+      }
+    },
+    "node_modules/@humanwhocodes/object-schema": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz",
+      "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==",
+      "dev": true
+    },
+    "node_modules/@istanbuljs/load-nyc-config": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+      "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+      "dev": true,
+      "dependencies": {
+        "camelcase": "^5.3.1",
+        "find-up": "^4.1.0",
+        "get-package-type": "^0.1.0",
+        "js-yaml": "^3.13.1",
+        "resolve-from": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "dev": true,
+      "dependencies": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
+    "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "dev": true,
+      "dependencies": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
+      "version": "3.14.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+      "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+      "dev": true,
+      "dependencies": {
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
+    "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "dev": true,
+      "dependencies": {
+        "p-locate": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "dev": true,
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "dev": true,
+      "dependencies": {
+        "p-limit": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@istanbuljs/schema": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+      "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@jridgewell/gen-mapping": {
+      "version": "0.3.3",
+      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
+      "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/set-array": "^1.0.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
+      "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/set-array": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+      "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.4.15",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+      "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
+      "dev": true
+    },
+    "node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.21",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.21.tgz",
+      "integrity": "sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/resolve-uri": "^3.1.0",
+        "@jridgewell/sourcemap-codec": "^1.4.14"
+      }
+    },
+    "node_modules/@nodelib/fs.scandir": {
+      "version": "2.1.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+      "dev": true,
+      "dependencies": {
+        "@nodelib/fs.stat": "2.0.5",
+        "run-parallel": "^1.1.9"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@nodelib/fs.stat": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+      "dev": true,
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@nodelib/fs.walk": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+      "dev": true,
+      "dependencies": {
+        "@nodelib/fs.scandir": "2.1.5",
+        "fastq": "^1.6.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@npmcli/fs": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz",
+      "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "@gar/promisify": "^1.0.1",
+        "semver": "^7.3.5"
+      }
+    },
+    "node_modules/@npmcli/fs/node_modules/semver": {
+      "version": "7.6.3",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+      "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+      "license": "ISC",
+      "optional": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/@npmcli/move-file": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz",
+      "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==",
+      "deprecated": "This functionality has been moved to @npmcli/fs",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "mkdirp": "^1.0.4",
+        "rimraf": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/@npmcli/move-file/node_modules/mkdirp": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+      "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+      "license": "MIT",
+      "optional": true,
+      "bin": {
+        "mkdirp": "bin/cmd.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/@tootallnate/once": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
+      "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/@ungap/structured-clone": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
+      "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
+      "dev": true
+    },
+    "node_modules/abbrev": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+      "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/acorn": {
+      "version": "8.11.3",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
+      "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
+      "dev": true,
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/acorn-jsx": {
+      "version": "5.3.2",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+      "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+      "dev": true,
+      "peerDependencies": {
+        "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+      }
+    },
+    "node_modules/agent-base": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+      "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+      "devOptional": true,
+      "dependencies": {
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6.0.0"
+      }
+    },
+    "node_modules/agentkeepalive": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz",
+      "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "humanize-ms": "^1.2.1"
+      },
+      "engines": {
+        "node": ">= 8.0.0"
+      }
+    },
+    "node_modules/aggregate-error": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+      "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+      "devOptional": true,
+      "dependencies": {
+        "clean-stack": "^2.0.0",
+        "indent-string": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/ajv": {
+      "version": "6.12.6",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+      "dependencies": {
+        "fast-deep-equal": "^3.1.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/ansi-colors": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+      "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dependencies": {
+        "color-convert": "^1.9.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/anymatch": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+      "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+      "dev": true,
+      "dependencies": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/append-transform": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz",
+      "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==",
+      "dev": true,
+      "dependencies": {
+        "default-require-extensions": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/aproba": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+      "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/archy": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
+      "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==",
+      "dev": true
+    },
+    "node_modules/are-we-there-yet": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz",
+      "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==",
+      "deprecated": "This package is no longer supported.",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "delegates": "^1.0.0",
+        "readable-stream": "^3.6.0"
+      },
+      "engines": {
+        "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+      }
+    },
+    "node_modules/argparse": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+      "dev": true
+    },
+    "node_modules/array-union": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+      "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/asn1": {
+      "version": "0.2.6",
+      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
+      "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
+      "dependencies": {
+        "safer-buffer": "~2.1.0"
+      }
+    },
+    "node_modules/assert-plus": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+      "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/assertion-error": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
+      "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/async": {
+      "version": "3.2.5",
+      "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
+      "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg=="
+    },
+    "node_modules/asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+    },
+    "node_modules/at-least-node": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
+      "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 4.0.0"
+      }
+    },
+    "node_modules/aws-sign2": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+      "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/aws4": {
+      "version": "1.12.0",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz",
+      "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg=="
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "devOptional": true
+    },
+    "node_modules/base64-js": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/bcrypt-pbkdf": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+      "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
+      "dependencies": {
+        "tweetnacl": "^0.14.3"
+      }
+    },
+    "node_modules/binary-extensions": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/bindings": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+      "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+      "license": "MIT",
+      "dependencies": {
+        "file-uri-to-path": "1.0.0"
+      }
+    },
+    "node_modules/bl": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+      "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+      "dependencies": {
+        "buffer": "^5.5.0",
+        "inherits": "^2.0.4",
+        "readable-stream": "^3.4.0"
+      }
+    },
+    "node_modules/boolbase": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+      "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
+    },
+    "node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "devOptional": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/braces": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+      "dev": true,
+      "dependencies": {
+        "fill-range": "^7.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/browser-stdout": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+      "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+      "dev": true
+    },
+    "node_modules/browserslist": {
+      "version": "4.22.2",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz",
+      "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "dependencies": {
+        "caniuse-lite": "^1.0.30001565",
+        "electron-to-chromium": "^1.4.601",
+        "node-releases": "^2.0.14",
+        "update-browserslist-db": "^1.0.13"
+      },
+      "bin": {
+        "browserslist": "cli.js"
+      },
+      "engines": {
+        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+      }
+    },
+    "node_modules/buffer": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+      "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "dependencies": {
+        "base64-js": "^1.3.1",
+        "ieee754": "^1.1.13"
+      }
+    },
+    "node_modules/cacache": {
+      "version": "15.3.0",
+      "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz",
+      "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "@npmcli/fs": "^1.0.0",
+        "@npmcli/move-file": "^1.0.1",
+        "chownr": "^2.0.0",
+        "fs-minipass": "^2.0.0",
+        "glob": "^7.1.4",
+        "infer-owner": "^1.0.4",
+        "lru-cache": "^6.0.0",
+        "minipass": "^3.1.1",
+        "minipass-collect": "^1.0.2",
+        "minipass-flush": "^1.0.5",
+        "minipass-pipeline": "^1.2.2",
+        "mkdirp": "^1.0.3",
+        "p-map": "^4.0.0",
+        "promise-inflight": "^1.0.1",
+        "rimraf": "^3.0.2",
+        "ssri": "^8.0.1",
+        "tar": "^6.0.2",
+        "unique-filename": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/cacache/node_modules/chownr": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+      "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+      "license": "ISC",
+      "optional": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/cacache/node_modules/lru-cache": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/cacache/node_modules/mkdirp": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+      "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+      "license": "MIT",
+      "optional": true,
+      "bin": {
+        "mkdirp": "bin/cmd.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/cacache/node_modules/p-map": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+      "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "aggregate-error": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/cacache/node_modules/yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/caching-transform": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz",
+      "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==",
+      "dev": true,
+      "dependencies": {
+        "hasha": "^5.0.0",
+        "make-dir": "^3.0.0",
+        "package-hash": "^4.0.0",
+        "write-file-atomic": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/callsites": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/camelcase": {
+      "version": "5.3.1",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/caniuse-lite": {
+      "version": "1.0.30001578",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001578.tgz",
+      "integrity": "sha512-J/jkFgsQ3NEl4w2lCoM9ZPxrD+FoBNJ7uJUpGVjIg/j0OwJosWM36EPDv+Yyi0V4twBk9pPmlFS+PLykgEvUmg==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ]
+    },
+    "node_modules/caseless": {
+      "version": "0.12.0",
+      "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+      "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
+    },
+    "node_modules/chai": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/chai/-/chai-5.0.0.tgz",
+      "integrity": "sha512-HO5p0oEKd5M6HEcwOkNAThAE3j960vIZvVcc0t2tI06Dd0ATu69cEnMB2wOhC5/ZyQ6m67w3ePjU/HzXsSsdBA==",
+      "dev": true,
+      "dependencies": {
+        "assertion-error": "^2.0.1",
+        "check-error": "^2.0.0",
+        "deep-eql": "^5.0.1",
+        "loupe": "^3.0.0",
+        "pathval": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/chalk": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/chalk/node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "dev": true,
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/chalk/node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dev": true,
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/chalk/node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "dev": true
+    },
+    "node_modules/chalk/node_modules/has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/chalk/node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/check-error": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.0.0.tgz",
+      "integrity": "sha512-tjLAOBHKVxtPoHe/SA7kNOMvhCRdCJ3vETdeY0RuAc9popf+hyaSV6ZEg9hr4cpWF7jmo/JSWEnLDrnijS9Tog==",
+      "dev": true,
+      "engines": {
+        "node": ">= 16"
+      }
+    },
+    "node_modules/cheerio": {
+      "version": "0.22.0",
+      "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz",
+      "integrity": "sha512-8/MzidM6G/TgRelkzDG13y3Y9LxBjCb+8yOEZ9+wwq5gVF2w2pV0wmHvjfT0RvuxGyR7UEuK36r+yYMbT4uKgA==",
+      "dependencies": {
+        "css-select": "~1.2.0",
+        "dom-serializer": "~0.1.0",
+        "entities": "~1.1.1",
+        "htmlparser2": "^3.9.1",
+        "lodash.assignin": "^4.0.9",
+        "lodash.bind": "^4.1.4",
+        "lodash.defaults": "^4.0.1",
+        "lodash.filter": "^4.4.0",
+        "lodash.flatten": "^4.2.0",
+        "lodash.foreach": "^4.3.0",
+        "lodash.map": "^4.4.0",
+        "lodash.merge": "^4.4.0",
+        "lodash.pick": "^4.2.1",
+        "lodash.reduce": "^4.4.0",
+        "lodash.reject": "^4.4.0",
+        "lodash.some": "^4.4.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/chokidar": {
+      "version": "3.5.3",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+      "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://paulmillr.com/funding/"
+        }
+      ],
+      "dependencies": {
+        "anymatch": "~3.1.2",
+        "braces": "~3.0.2",
+        "glob-parent": "~5.1.2",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.6.0"
+      },
+      "engines": {
+        "node": ">= 8.10.0"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/chokidar/node_modules/glob-parent": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+      "dev": true,
+      "dependencies": {
+        "is-glob": "^4.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/chownr": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+      "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+    },
+    "node_modules/clean-stack": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+      "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+      "devOptional": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/cli-cursor": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+      "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==",
+      "dependencies": {
+        "restore-cursor": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/cli-spinners": {
+      "version": "2.9.2",
+      "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
+      "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/cliui": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+      "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+      "dependencies": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.1",
+        "wrap-ansi": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/clone": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+      "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dependencies": {
+        "color-name": "1.1.3"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+    },
+    "node_modules/color-support": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
+      "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
+      "license": "ISC",
+      "optional": true,
+      "bin": {
+        "color-support": "bin.js"
+      }
+    },
+    "node_modules/colors": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
+      "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==",
+      "engines": {
+        "node": ">=0.1.90"
+      }
+    },
+    "node_modules/combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "dependencies": {
+        "delayed-stream": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/commondir": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+      "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
+      "dev": true
+    },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+      "devOptional": true
+    },
+    "node_modules/console-control-strings": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+      "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/convert-source-map": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
+      "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
+      "dev": true
+    },
+    "node_modules/core-util-is": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+      "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="
+    },
+    "node_modules/cross-spawn": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+      "dev": true,
+      "dependencies": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/css-select": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+      "integrity": "sha512-dUQOBoqdR7QwV90WysXPLXG5LO7nhYBgiWVfxF80DKPF8zx1t/pUd2FYy73emg3zrjtM6dzmYgbHKfV2rxiHQA==",
+      "dependencies": {
+        "boolbase": "~1.0.0",
+        "css-what": "2.1",
+        "domutils": "1.5.1",
+        "nth-check": "~1.0.1"
+      }
+    },
+    "node_modules/css-what": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
+      "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/cycle": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz",
+      "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/dashdash": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+      "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
+      "dependencies": {
+        "assert-plus": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "devOptional": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/decamelize": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+      "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/decompress-response": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+      "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+      "dependencies": {
+        "mimic-response": "^3.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/deep-eql": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.1.tgz",
+      "integrity": "sha512-nwQCf6ne2gez3o1MxWifqkciwt0zhl0LO1/UwVu4uMBuPmflWM4oQ70XMqHqnBJA+nhzncaqL9HVL6KkHJ28lw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/deep-extend": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+      "engines": {
+        "node": ">=4.0.0"
+      }
+    },
+    "node_modules/deep-is": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+      "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+      "dev": true
+    },
+    "node_modules/default-require-extensions": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz",
+      "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==",
+      "dev": true,
+      "dependencies": {
+        "strip-bom": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/defaults": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+      "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+      "dependencies": {
+        "clone": "^1.0.2"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/delegates": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+      "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/detect-libc": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz",
+      "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/diff": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
+      "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.3.1"
+      }
+    },
+    "node_modules/dir-glob": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+      "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+      "dev": true,
+      "dependencies": {
+        "path-type": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/doctrine": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+      "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+      "dev": true,
+      "dependencies": {
+        "esutils": "^2.0.2"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/dom-serializer": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
+      "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
+      "dependencies": {
+        "domelementtype": "^1.3.0",
+        "entities": "^1.1.1"
+      }
+    },
+    "node_modules/domelementtype": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+      "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
+    },
+    "node_modules/domhandler": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+      "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+      "dependencies": {
+        "domelementtype": "1"
+      }
+    },
+    "node_modules/domutils": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
+      "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==",
+      "dependencies": {
+        "dom-serializer": "0",
+        "domelementtype": "1"
+      }
+    },
+    "node_modules/ecc-jsbn": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+      "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
+      "dependencies": {
+        "jsbn": "~0.1.0",
+        "safer-buffer": "^2.1.0"
+      }
+    },
+    "node_modules/electron-to-chromium": {
+      "version": "1.4.634",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.634.tgz",
+      "integrity": "sha512-gQNahJfF5AE4MZo+pMSwmnwkzVZ+F4ZGGj4Z/MMddOXVQM0y9OHy6ts3W9SDzAJaiZM3p6eixn5ABCQ+AfXzcQ==",
+      "dev": true
+    },
+    "node_modules/emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "license": "MIT"
+    },
+    "node_modules/encoding": {
+      "version": "0.1.13",
+      "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
+      "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "iconv-lite": "^0.6.2"
+      }
+    },
+    "node_modules/end-of-stream": {
+      "version": "1.4.4",
+      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+      "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+      "dependencies": {
+        "once": "^1.4.0"
+      }
+    },
+    "node_modules/entities": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+      "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
+    },
+    "node_modules/env-paths": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+      "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/err-code": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
+      "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/es6-error": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
+      "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
+      "dev": true
+    },
+    "node_modules/escalade": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+      "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/escape-string-regexp": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/eslint": {
+      "version": "8.56.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz",
+      "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==",
+      "dev": true,
+      "dependencies": {
+        "@eslint-community/eslint-utils": "^4.2.0",
+        "@eslint-community/regexpp": "^4.6.1",
+        "@eslint/eslintrc": "^2.1.4",
+        "@eslint/js": "8.56.0",
+        "@humanwhocodes/config-array": "^0.11.13",
+        "@humanwhocodes/module-importer": "^1.0.1",
+        "@nodelib/fs.walk": "^1.2.8",
+        "@ungap/structured-clone": "^1.2.0",
+        "ajv": "^6.12.4",
+        "chalk": "^4.0.0",
+        "cross-spawn": "^7.0.2",
+        "debug": "^4.3.2",
+        "doctrine": "^3.0.0",
+        "escape-string-regexp": "^4.0.0",
+        "eslint-scope": "^7.2.2",
+        "eslint-visitor-keys": "^3.4.3",
+        "espree": "^9.6.1",
+        "esquery": "^1.4.2",
+        "esutils": "^2.0.2",
+        "fast-deep-equal": "^3.1.3",
+        "file-entry-cache": "^6.0.1",
+        "find-up": "^5.0.0",
+        "glob-parent": "^6.0.2",
+        "globals": "^13.19.0",
+        "graphemer": "^1.4.0",
+        "ignore": "^5.2.0",
+        "imurmurhash": "^0.1.4",
+        "is-glob": "^4.0.0",
+        "is-path-inside": "^3.0.3",
+        "js-yaml": "^4.1.0",
+        "json-stable-stringify-without-jsonify": "^1.0.1",
+        "levn": "^0.4.1",
+        "lodash.merge": "^4.6.2",
+        "minimatch": "^3.1.2",
+        "natural-compare": "^1.4.0",
+        "optionator": "^0.9.3",
+        "strip-ansi": "^6.0.1",
+        "text-table": "^0.2.0"
+      },
+      "bin": {
+        "eslint": "bin/eslint.js"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/eslint-config-google": {
+      "version": "0.14.0",
+      "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz",
+      "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      },
+      "peerDependencies": {
+        "eslint": ">=5.16.0"
+      }
+    },
+    "node_modules/eslint-scope": {
+      "version": "7.2.2",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+      "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+      "dev": true,
+      "dependencies": {
+        "esrecurse": "^4.3.0",
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/eslint-visitor-keys": {
+      "version": "3.4.3",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+      "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+      "dev": true,
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/espree": {
+      "version": "9.6.1",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+      "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+      "dev": true,
+      "dependencies": {
+        "acorn": "^8.9.0",
+        "acorn-jsx": "^5.3.2",
+        "eslint-visitor-keys": "^3.4.1"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/esprima": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+      "dev": true,
+      "bin": {
+        "esparse": "bin/esparse.js",
+        "esvalidate": "bin/esvalidate.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/esquery": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+      "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+      "dev": true,
+      "dependencies": {
+        "estraverse": "^5.1.0"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/esrecurse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+      "dev": true,
+      "dependencies": {
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/estraverse": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/esutils": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/expand-template": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
+      "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/extend": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+    },
+    "node_modules/extsprintf": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+      "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
+      "engines": [
+        "node >=0.6.0"
+      ]
+    },
+    "node_modules/eyes": {
+      "version": "0.1.8",
+      "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
+      "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==",
+      "engines": {
+        "node": "> 0.1.90"
+      }
+    },
+    "node_modules/fast-deep-equal": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+    },
+    "node_modules/fast-glob": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+      "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+      "dev": true,
+      "dependencies": {
+        "@nodelib/fs.stat": "^2.0.2",
+        "@nodelib/fs.walk": "^1.2.3",
+        "glob-parent": "^5.1.2",
+        "merge2": "^1.3.0",
+        "micromatch": "^4.0.4"
+      },
+      "engines": {
+        "node": ">=8.6.0"
+      }
+    },
+    "node_modules/fast-glob/node_modules/glob-parent": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+      "dev": true,
+      "dependencies": {
+        "is-glob": "^4.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/fast-json-stable-stringify": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
+    },
+    "node_modules/fast-levenshtein": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+      "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+      "dev": true
+    },
+    "node_modules/fastq": {
+      "version": "1.16.0",
+      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz",
+      "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==",
+      "dev": true,
+      "dependencies": {
+        "reusify": "^1.0.4"
+      }
+    },
+    "node_modules/file-entry-cache": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+      "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+      "dev": true,
+      "dependencies": {
+        "flat-cache": "^3.0.4"
+      },
+      "engines": {
+        "node": "^10.12.0 || >=12.0.0"
+      }
+    },
+    "node_modules/file-uri-to-path": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+      "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+      "license": "MIT"
+    },
+    "node_modules/fill-range": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+      "dev": true,
+      "dependencies": {
+        "to-regex-range": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/find-cache-dir": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz",
+      "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==",
+      "dev": true,
+      "dependencies": {
+        "commondir": "^1.0.1",
+        "make-dir": "^3.0.2",
+        "pkg-dir": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/avajs/find-cache-dir?sponsor=1"
+      }
+    },
+    "node_modules/find-up": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+      "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+      "dev": true,
+      "dependencies": {
+        "locate-path": "^6.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/flat": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+      "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+      "dev": true,
+      "bin": {
+        "flat": "cli.js"
+      }
+    },
+    "node_modules/flat-cache": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+      "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+      "dev": true,
+      "dependencies": {
+        "flatted": "^3.2.9",
+        "keyv": "^4.5.3",
+        "rimraf": "^3.0.2"
+      },
+      "engines": {
+        "node": "^10.12.0 || >=12.0.0"
+      }
+    },
+    "node_modules/flatted": {
+      "version": "3.2.9",
+      "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
+      "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
+      "dev": true
+    },
+    "node_modules/foreground-child": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz",
+      "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==",
+      "dev": true,
+      "dependencies": {
+        "cross-spawn": "^7.0.0",
+        "signal-exit": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
+    "node_modules/forever-agent": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+      "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/form-data": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+      "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+      "dependencies": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.6",
+        "mime-types": "^2.1.12"
+      },
+      "engines": {
+        "node": ">= 0.12"
+      }
+    },
+    "node_modules/from2": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+      "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==",
+      "dev": true,
+      "dependencies": {
+        "inherits": "^2.0.1",
+        "readable-stream": "^2.0.0"
+      }
+    },
+    "node_modules/from2/node_modules/readable-stream": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+      "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+      "dev": true,
+      "dependencies": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
+      }
+    },
+    "node_modules/from2/node_modules/safe-buffer": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+      "dev": true
+    },
+    "node_modules/from2/node_modules/string_decoder": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "dev": true,
+      "dependencies": {
+        "safe-buffer": "~5.1.0"
+      }
+    },
+    "node_modules/fromentries": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz",
+      "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/fs-constants": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+      "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
+    },
+    "node_modules/fs-extra": {
+      "version": "9.1.0",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+      "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+      "dev": true,
+      "dependencies": {
+        "at-least-node": "^1.0.0",
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^6.0.1",
+        "universalify": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/fs-minipass": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+      "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+      "license": "ISC",
+      "dependencies": {
+        "minipass": "^3.0.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+      "devOptional": true
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/gauge": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz",
+      "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==",
+      "deprecated": "This package is no longer supported.",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "aproba": "^1.0.3 || ^2.0.0",
+        "color-support": "^1.1.3",
+        "console-control-strings": "^1.1.0",
+        "has-unicode": "^2.0.1",
+        "signal-exit": "^3.0.7",
+        "string-width": "^4.2.3",
+        "strip-ansi": "^6.0.1",
+        "wide-align": "^1.1.5"
+      },
+      "engines": {
+        "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+      }
+    },
+    "node_modules/gensync": {
+      "version": "1.0.0-beta.2",
+      "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+      "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/get-caller-file": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+      "engines": {
+        "node": "6.* || 8.* || >= 10.*"
+      }
+    },
+    "node_modules/get-func-name": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
+      "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
+      "dev": true,
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/get-package-type": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+      "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
+    "node_modules/getpass": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+      "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
+      "dependencies": {
+        "assert-plus": "^1.0.0"
+      }
+    },
+    "node_modules/github-from-package": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
+      "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="
+    },
+    "node_modules/glob": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+      "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+      "devOptional": true,
+      "dependencies": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.0.4",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      },
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/glob-parent": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+      "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+      "dev": true,
+      "dependencies": {
+        "is-glob": "^4.0.3"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/globals": {
+      "version": "13.24.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+      "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+      "dev": true,
+      "dependencies": {
+        "type-fest": "^0.20.2"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/globby": {
+      "version": "11.1.0",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+      "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+      "dev": true,
+      "dependencies": {
+        "array-union": "^2.1.0",
+        "dir-glob": "^3.0.1",
+        "fast-glob": "^3.2.9",
+        "ignore": "^5.2.0",
+        "merge2": "^1.4.1",
+        "slash": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/graceful-fs": {
+      "version": "4.2.11",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+      "devOptional": true
+    },
+    "node_modules/graphemer": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+      "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+      "dev": true
+    },
+    "node_modules/har-schema": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+      "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/har-validator": {
+      "version": "5.1.5",
+      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
+      "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
+      "deprecated": "this library is no longer supported",
+      "dependencies": {
+        "ajv": "^6.12.3",
+        "har-schema": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/has": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz",
+      "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/has-unicode": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+      "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/hasha": {
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz",
+      "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==",
+      "dev": true,
+      "dependencies": {
+        "is-stream": "^2.0.0",
+        "type-fest": "^0.8.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/hasha/node_modules/type-fest": {
+      "version": "0.8.1",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+      "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/hasown": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
+      "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
+      "dev": true,
+      "dependencies": {
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/he": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+      "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+      "bin": {
+        "he": "bin/he"
+      }
+    },
+    "node_modules/html-escaper": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+      "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+      "dev": true
+    },
+    "node_modules/htmlparser2": {
+      "version": "3.10.1",
+      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
+      "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
+      "dependencies": {
+        "domelementtype": "^1.3.1",
+        "domhandler": "^2.3.0",
+        "domutils": "^1.5.1",
+        "entities": "^1.1.1",
+        "inherits": "^2.0.1",
+        "readable-stream": "^3.1.1"
+      }
+    },
+    "node_modules/http-cache-semantics": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
+      "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
+      "license": "BSD-2-Clause",
+      "optional": true
+    },
+    "node_modules/http-proxy-agent": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
+      "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "@tootallnate/once": "1",
+        "agent-base": "6",
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/http-signature": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+      "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
+      "dependencies": {
+        "assert-plus": "^1.0.0",
+        "jsprim": "^1.2.2",
+        "sshpk": "^1.7.0"
+      },
+      "engines": {
+        "node": ">=0.8",
+        "npm": ">=1.3.7"
+      }
+    },
+    "node_modules/https-proxy-agent": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+      "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+      "devOptional": true,
+      "dependencies": {
+        "agent-base": "6",
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/humanize-ms": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+      "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "ms": "^2.0.0"
+      }
+    },
+    "node_modules/iconv-lite": {
+      "version": "0.6.3",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+      "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "safer-buffer": ">= 2.1.2 < 3.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/ieee754": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/ignore": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
+      "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 4"
+      }
+    },
+    "node_modules/import-fresh": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+      "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+      "dev": true,
+      "dependencies": {
+        "parent-module": "^1.0.0",
+        "resolve-from": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+      "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+      "devOptional": true,
+      "engines": {
+        "node": ">=0.8.19"
+      }
+    },
+    "node_modules/indent-string": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+      "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+      "devOptional": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/infer-owner": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
+      "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+      "devOptional": true,
+      "dependencies": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+    },
+    "node_modules/ini": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz",
+      "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==",
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/into-stream": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-6.0.0.tgz",
+      "integrity": "sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==",
+      "dev": true,
+      "dependencies": {
+        "from2": "^2.3.0",
+        "p-is-promise": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/ip-address": {
+      "version": "9.0.5",
+      "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
+      "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "jsbn": "1.1.0",
+        "sprintf-js": "^1.1.3"
+      },
+      "engines": {
+        "node": ">= 12"
+      }
+    },
+    "node_modules/ip-address/node_modules/jsbn": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
+      "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/ip-address/node_modules/sprintf-js": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
+      "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
+      "license": "BSD-3-Clause",
+      "optional": true
+    },
+    "node_modules/is-binary-path": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+      "dev": true,
+      "dependencies": {
+        "binary-extensions": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-core-module": {
+      "version": "2.9.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
+      "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==",
+      "dev": true,
+      "dependencies": {
+        "has": "^1.0.3"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "dev": true,
+      "dependencies": {
+        "is-extglob": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-lambda": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
+      "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.12.0"
+      }
+    },
+    "node_modules/is-path-inside": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+      "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-plain-obj": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+      "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-stream": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+      "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/is-typedarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+      "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
+    },
+    "node_modules/is-unicode-supported": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+      "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/is-windows": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+      "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+      "dev": true
+    },
+    "node_modules/isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+      "devOptional": true
+    },
+    "node_modules/isstream": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+      "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="
+    },
+    "node_modules/istanbul-lib-coverage": {
+      "version": "3.2.2",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+      "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/istanbul-lib-hook": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz",
+      "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==",
+      "dev": true,
+      "dependencies": {
+        "append-transform": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/istanbul-lib-instrument": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz",
+      "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/core": "^7.7.5",
+        "@istanbuljs/schema": "^0.1.2",
+        "istanbul-lib-coverage": "^3.0.0",
+        "semver": "^6.3.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/istanbul-lib-processinfo": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz",
+      "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==",
+      "dev": true,
+      "dependencies": {
+        "archy": "^1.0.0",
+        "cross-spawn": "^7.0.3",
+        "istanbul-lib-coverage": "^3.2.0",
+        "p-map": "^3.0.0",
+        "rimraf": "^3.0.0",
+        "uuid": "^8.3.2"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/istanbul-lib-report": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+      "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+      "dev": true,
+      "dependencies": {
+        "istanbul-lib-coverage": "^3.0.0",
+        "make-dir": "^4.0.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/istanbul-lib-report/node_modules/has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/istanbul-lib-report/node_modules/lru-cache": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/istanbul-lib-report/node_modules/make-dir": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+      "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+      "dev": true,
+      "dependencies": {
+        "semver": "^7.5.3"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/istanbul-lib-report/node_modules/semver": {
+      "version": "7.5.4",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+      "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+      "dev": true,
+      "dependencies": {
+        "lru-cache": "^6.0.0"
+      },
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/istanbul-lib-report/node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/istanbul-lib-report/node_modules/yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "dev": true
+    },
+    "node_modules/istanbul-lib-source-maps": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+      "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+      "dev": true,
+      "dependencies": {
+        "debug": "^4.1.1",
+        "istanbul-lib-coverage": "^3.0.0",
+        "source-map": "^0.6.1"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/istanbul-reports": {
+      "version": "3.1.6",
+      "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz",
+      "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==",
+      "dev": true,
+      "dependencies": {
+        "html-escaper": "^2.0.0",
+        "istanbul-lib-report": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "dev": true
+    },
+    "node_modules/js-yaml": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+      "dev": true,
+      "dependencies": {
+        "argparse": "^2.0.1"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
+    "node_modules/jsbn": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+      "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="
+    },
+    "node_modules/jsesc": {
+      "version": "2.5.2",
+      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+      "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+      "dev": true,
+      "bin": {
+        "jsesc": "bin/jsesc"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/json-buffer": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+      "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+      "dev": true
+    },
+    "node_modules/json-schema": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
+      "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
+    },
+    "node_modules/json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+    },
+    "node_modules/json-stable-stringify-without-jsonify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+      "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+      "dev": true
+    },
+    "node_modules/json-stringify-safe": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+      "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="
+    },
+    "node_modules/json5": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+      "dev": true,
+      "bin": {
+        "json5": "lib/cli.js"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/jsonfile": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+      "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+      "dev": true,
+      "dependencies": {
+        "universalify": "^2.0.0"
+      },
+      "optionalDependencies": {
+        "graceful-fs": "^4.1.6"
+      }
+    },
+    "node_modules/jsprim": {
+      "version": "1.4.2",
+      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
+      "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
+      "dependencies": {
+        "assert-plus": "1.0.0",
+        "extsprintf": "1.3.0",
+        "json-schema": "0.4.0",
+        "verror": "1.10.0"
+      },
+      "engines": {
+        "node": ">=0.6.0"
+      }
+    },
+    "node_modules/keytar": {
+      "version": "7.9.0",
+      "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz",
+      "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "dependencies": {
+        "node-addon-api": "^4.3.0",
+        "prebuild-install": "^7.0.1"
+      }
+    },
+    "node_modules/keyv": {
+      "version": "4.5.4",
+      "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+      "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+      "dev": true,
+      "dependencies": {
+        "json-buffer": "3.0.1"
+      }
+    },
+    "node_modules/levn": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+      "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+      "dev": true,
+      "dependencies": {
+        "prelude-ls": "^1.2.1",
+        "type-check": "~0.4.0"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/locate-path": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+      "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+      "dev": true,
+      "dependencies": {
+        "p-locate": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/lodash": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+    },
+    "node_modules/lodash.assignin": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz",
+      "integrity": "sha512-yX/rx6d/UTVh7sSVWVSIMjfnz95evAgDFdb1ZozC35I9mSFCkmzptOzevxjgbQUsc78NR44LVHWjsoMQXy9FDg=="
+    },
+    "node_modules/lodash.bind": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz",
+      "integrity": "sha512-lxdsn7xxlCymgLYo1gGvVrfHmkjDiyqVv62FAeF2i5ta72BipE1SLxw8hPEPLhD4/247Ijw07UQH7Hq/chT5LA=="
+    },
+    "node_modules/lodash.defaults": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
+      "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
+    },
+    "node_modules/lodash.filter": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz",
+      "integrity": "sha512-pXYUy7PR8BCLwX5mgJ/aNtyOvuJTdZAo9EQFUvMIYugqmJxnrYaANvTbgndOzHSCSR0wnlBBfRXJL5SbWxo3FQ=="
+    },
+    "node_modules/lodash.flatten": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+      "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g=="
+    },
+    "node_modules/lodash.flattendeep": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
+      "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==",
+      "dev": true
+    },
+    "node_modules/lodash.foreach": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
+      "integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ=="
+    },
+    "node_modules/lodash.map": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz",
+      "integrity": "sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q=="
+    },
+    "node_modules/lodash.merge": {
+      "version": "4.6.2",
+      "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+      "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
+    },
+    "node_modules/lodash.pick": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz",
+      "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q=="
+    },
+    "node_modules/lodash.reduce": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz",
+      "integrity": "sha512-6raRe2vxCYBhpBu+B+TtNGUzah+hQjVdu3E17wfusjyrXBka2nBS8OH/gjVZ5PvHOhWmIZTYri09Z6n/QfnNMw=="
+    },
+    "node_modules/lodash.reject": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz",
+      "integrity": "sha512-qkTuvgEzYdyhiJBx42YPzPo71R1aEr0z79kAv7Ixg8wPFEjgRgJdUsGMG3Hf3OYSF/kHI79XhNlt+5Ar6OzwxQ=="
+    },
+    "node_modules/lodash.some": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz",
+      "integrity": "sha512-j7MJE+TuT51q9ggt4fSgVqro163BEFjAt3u97IqU+JA2DkWl80nFTrowzLpZ/BnpN7rrl0JA/593NAdd8p/scQ=="
+    },
+    "node_modules/log-symbols": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+      "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+      "dev": true,
+      "dependencies": {
+        "chalk": "^4.1.0",
+        "is-unicode-supported": "^0.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/loupe": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.0.tgz",
+      "integrity": "sha512-qKl+FrLXUhFuHUoDJG7f8P8gEMHq9NFS0c6ghXG1J0rldmZFQZoNVv/vyirE9qwCIhWZDsvEFd1sbFu3GvRQFg==",
+      "dev": true,
+      "dependencies": {
+        "get-func-name": "^2.0.1"
+      }
+    },
+    "node_modules/lru-cache": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^3.0.2"
+      }
+    },
+    "node_modules/make-dir": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+      "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+      "dev": true,
+      "dependencies": {
+        "semver": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/make-fetch-happen": {
+      "version": "9.1.0",
+      "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
+      "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "agentkeepalive": "^4.1.3",
+        "cacache": "^15.2.0",
+        "http-cache-semantics": "^4.1.0",
+        "http-proxy-agent": "^4.0.1",
+        "https-proxy-agent": "^5.0.0",
+        "is-lambda": "^1.0.1",
+        "lru-cache": "^6.0.0",
+        "minipass": "^3.1.3",
+        "minipass-collect": "^1.0.2",
+        "minipass-fetch": "^1.3.2",
+        "minipass-flush": "^1.0.5",
+        "minipass-pipeline": "^1.2.4",
+        "negotiator": "^0.6.2",
+        "promise-retry": "^2.0.1",
+        "socks-proxy-agent": "^6.0.0",
+        "ssri": "^8.0.0"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/make-fetch-happen/node_modules/lru-cache": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/make-fetch-happen/node_modules/yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/merge2": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/micromatch": {
+      "version": "4.0.5",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+      "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+      "dev": true,
+      "dependencies": {
+        "braces": "^3.0.2",
+        "picomatch": "^2.3.1"
+      },
+      "engines": {
+        "node": ">=8.6"
+      }
+    },
+    "node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mimic-fn": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+      "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/mimic-response": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+      "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "devOptional": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/minimist": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/minipass": {
+      "version": "3.3.6",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+      "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+      "license": "ISC",
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/minipass-collect": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
+      "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "minipass": "^3.0.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/minipass-fetch": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz",
+      "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "minipass": "^3.1.0",
+        "minipass-sized": "^1.0.3",
+        "minizlib": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "optionalDependencies": {
+        "encoding": "^0.1.12"
+      }
+    },
+    "node_modules/minipass-flush": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
+      "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "minipass": "^3.0.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/minipass-pipeline": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
+      "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "minipass": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/minipass-sized": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
+      "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "minipass": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/minipass/node_modules/yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "license": "ISC"
+    },
+    "node_modules/minizlib": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+      "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+      "license": "MIT",
+      "dependencies": {
+        "minipass": "^3.0.0",
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/minizlib/node_modules/yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "license": "ISC"
+    },
+    "node_modules/mkdirp": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
+      "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
+      "bin": {
+        "mkdirp": "dist/cjs/src/bin.js"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/mkdirp-classic": {
+      "version": "0.5.3",
+      "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+      "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
+    },
+    "node_modules/mocha": {
+      "version": "10.2.0",
+      "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz",
+      "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==",
+      "dev": true,
+      "dependencies": {
+        "ansi-colors": "4.1.1",
+        "browser-stdout": "1.3.1",
+        "chokidar": "3.5.3",
+        "debug": "4.3.4",
+        "diff": "5.0.0",
+        "escape-string-regexp": "4.0.0",
+        "find-up": "5.0.0",
+        "glob": "7.2.0",
+        "he": "1.2.0",
+        "js-yaml": "4.1.0",
+        "log-symbols": "4.1.0",
+        "minimatch": "5.0.1",
+        "ms": "2.1.3",
+        "nanoid": "3.3.3",
+        "serialize-javascript": "6.0.0",
+        "strip-json-comments": "3.1.1",
+        "supports-color": "8.1.1",
+        "workerpool": "6.2.1",
+        "yargs": "16.2.0",
+        "yargs-parser": "20.2.4",
+        "yargs-unparser": "2.0.0"
+      },
+      "bin": {
+        "_mocha": "bin/_mocha",
+        "mocha": "bin/mocha.js"
+      },
+      "engines": {
+        "node": ">= 14.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/mochajs"
+      }
+    },
+    "node_modules/mocha/node_modules/brace-expansion": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0"
+      }
+    },
+    "node_modules/mocha/node_modules/cliui": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+      "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+      "dev": true,
+      "dependencies": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.0",
+        "wrap-ansi": "^7.0.0"
+      }
+    },
+    "node_modules/mocha/node_modules/has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/mocha/node_modules/minimatch": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+      "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/mocha/node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+      "dev": true
+    },
+    "node_modules/mocha/node_modules/supports-color": {
+      "version": "8.1.1",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+      "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/supports-color?sponsor=1"
+      }
+    },
+    "node_modules/mocha/node_modules/yargs": {
+      "version": "16.2.0",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+      "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+      "dev": true,
+      "dependencies": {
+        "cliui": "^7.0.2",
+        "escalade": "^3.1.1",
+        "get-caller-file": "^2.0.5",
+        "require-directory": "^2.1.1",
+        "string-width": "^4.2.0",
+        "y18n": "^5.0.5",
+        "yargs-parser": "^20.2.2"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/moment": {
+      "version": "2.30.1",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
+      "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "devOptional": true
+    },
+    "node_modules/multistream": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/multistream/-/multistream-4.1.0.tgz",
+      "integrity": "sha512-J1XDiAmmNpRCBfIWJv+n0ymC4ABcf/Pl+5YvC5B/D2f/2+8PtHvCNxMPKiQcZyi922Hq69J2YOpb1pTywfifyw==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "dependencies": {
+        "once": "^1.4.0",
+        "readable-stream": "^3.6.0"
+      }
+    },
+    "node_modules/mute-stream": {
+      "version": "0.0.8",
+      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+      "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
+      "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
+      "dev": true,
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/napi-build-utils": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
+      "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg=="
+    },
+    "node_modules/natural-compare": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+      "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+      "dev": true
+    },
+    "node_modules/nconf": {
+      "version": "0.12.1",
+      "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.12.1.tgz",
+      "integrity": "sha512-p2cfF+B3XXacQdswUYWZ0w6Vld0832A/tuqjLBu3H1sfUcby4N2oVbGhyuCkZv+t3iY3aiFEj7gZGqax9Q2c1w==",
+      "dependencies": {
+        "async": "^3.0.0",
+        "ini": "^2.0.0",
+        "secure-keys": "^1.0.0",
+        "yargs": "^16.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/nconf/node_modules/cliui": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+      "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+      "dependencies": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.0",
+        "wrap-ansi": "^7.0.0"
+      }
+    },
+    "node_modules/nconf/node_modules/yargs": {
+      "version": "16.2.0",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+      "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+      "dependencies": {
+        "cliui": "^7.0.2",
+        "escalade": "^3.1.1",
+        "get-caller-file": "^2.0.5",
+        "require-directory": "^2.1.1",
+        "string-width": "^4.2.0",
+        "y18n": "^5.0.5",
+        "yargs-parser": "^20.2.2"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/negotiator": {
+      "version": "0.6.3",
+      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+      "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/nock": {
+      "version": "13.5.0",
+      "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.0.tgz",
+      "integrity": "sha512-9hc1eCS2HtOz+sE9W7JQw/tXJktg0zoPSu48s/pYe73e25JW9ywiowbqnUSd7iZPeVawLcVpPZeZS312fwSY+g==",
+      "dev": true,
+      "dependencies": {
+        "debug": "^4.1.0",
+        "json-stringify-safe": "^5.0.1",
+        "propagate": "^2.0.0"
+      },
+      "engines": {
+        "node": ">= 10.13"
+      }
+    },
+    "node_modules/node-abi": {
+      "version": "3.54.0",
+      "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.54.0.tgz",
+      "integrity": "sha512-p7eGEiQil0YUV3ItH4/tBb781L5impVmmx2E9FRKF7d18XXzp4PGT2tdYMFY6wQqgxD0IwNZOiSJ0/K0fSi/OA==",
+      "dependencies": {
+        "semver": "^7.3.5"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/node-abi/node_modules/lru-cache": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/node-abi/node_modules/semver": {
+      "version": "7.5.4",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+      "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+      "dependencies": {
+        "lru-cache": "^6.0.0"
+      },
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/node-abi/node_modules/yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+    },
+    "node_modules/node-addon-api": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz",
+      "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==",
+      "license": "MIT"
+    },
+    "node_modules/node-fetch": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+      "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+      "dev": true,
+      "dependencies": {
+        "whatwg-url": "^5.0.0"
+      },
+      "engines": {
+        "node": "4.x || >=6.0.0"
+      },
+      "peerDependencies": {
+        "encoding": "^0.1.0"
+      },
+      "peerDependenciesMeta": {
+        "encoding": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/node-gyp": {
+      "version": "8.4.1",
+      "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz",
+      "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "env-paths": "^2.2.0",
+        "glob": "^7.1.4",
+        "graceful-fs": "^4.2.6",
+        "make-fetch-happen": "^9.1.0",
+        "nopt": "^5.0.0",
+        "npmlog": "^6.0.0",
+        "rimraf": "^3.0.2",
+        "semver": "^7.3.5",
+        "tar": "^6.1.2",
+        "which": "^2.0.2"
+      },
+      "bin": {
+        "node-gyp": "bin/node-gyp.js"
+      },
+      "engines": {
+        "node": ">= 10.12.0"
+      }
+    },
+    "node_modules/node-gyp/node_modules/semver": {
+      "version": "7.6.3",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+      "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+      "license": "ISC",
+      "optional": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/node-preload": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz",
+      "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==",
+      "dev": true,
+      "dependencies": {
+        "process-on-spawn": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/node-releases": {
+      "version": "2.0.14",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
+      "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
+      "dev": true
+    },
+    "node_modules/nopt": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
+      "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "abbrev": "1"
+      },
+      "bin": {
+        "nopt": "bin/nopt.js"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/npmlog": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz",
+      "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==",
+      "deprecated": "This package is no longer supported.",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "are-we-there-yet": "^3.0.0",
+        "console-control-strings": "^1.1.0",
+        "gauge": "^4.0.3",
+        "set-blocking": "^2.0.0"
+      },
+      "engines": {
+        "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+      }
+    },
+    "node_modules/nth-check": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+      "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+      "dependencies": {
+        "boolbase": "~1.0.0"
+      }
+    },
+    "node_modules/nyc": {
+      "version": "15.1.0",
+      "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz",
+      "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==",
+      "dev": true,
+      "dependencies": {
+        "@istanbuljs/load-nyc-config": "^1.0.0",
+        "@istanbuljs/schema": "^0.1.2",
+        "caching-transform": "^4.0.0",
+        "convert-source-map": "^1.7.0",
+        "decamelize": "^1.2.0",
+        "find-cache-dir": "^3.2.0",
+        "find-up": "^4.1.0",
+        "foreground-child": "^2.0.0",
+        "get-package-type": "^0.1.0",
+        "glob": "^7.1.6",
+        "istanbul-lib-coverage": "^3.0.0",
+        "istanbul-lib-hook": "^3.0.0",
+        "istanbul-lib-instrument": "^4.0.0",
+        "istanbul-lib-processinfo": "^2.0.2",
+        "istanbul-lib-report": "^3.0.0",
+        "istanbul-lib-source-maps": "^4.0.0",
+        "istanbul-reports": "^3.0.2",
+        "make-dir": "^3.0.0",
+        "node-preload": "^0.2.1",
+        "p-map": "^3.0.0",
+        "process-on-spawn": "^1.0.0",
+        "resolve-from": "^5.0.0",
+        "rimraf": "^3.0.0",
+        "signal-exit": "^3.0.2",
+        "spawn-wrap": "^2.0.0",
+        "test-exclude": "^6.0.0",
+        "yargs": "^15.0.2"
+      },
+      "bin": {
+        "nyc": "bin/nyc.js"
+      },
+      "engines": {
+        "node": ">=8.9"
+      }
+    },
+    "node_modules/nyc/node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "dev": true,
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/nyc/node_modules/cliui": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+      "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+      "dev": true,
+      "dependencies": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.0",
+        "wrap-ansi": "^6.2.0"
+      }
+    },
+    "node_modules/nyc/node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dev": true,
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/nyc/node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "dev": true
+    },
+    "node_modules/nyc/node_modules/find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "dev": true,
+      "dependencies": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/nyc/node_modules/locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "dev": true,
+      "dependencies": {
+        "p-locate": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/nyc/node_modules/p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "dev": true,
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/nyc/node_modules/p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "dev": true,
+      "dependencies": {
+        "p-limit": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/nyc/node_modules/resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/nyc/node_modules/wrap-ansi": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+      "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/nyc/node_modules/y18n": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+      "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+      "dev": true
+    },
+    "node_modules/nyc/node_modules/yargs": {
+      "version": "15.4.1",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+      "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+      "dev": true,
+      "dependencies": {
+        "cliui": "^6.0.0",
+        "decamelize": "^1.2.0",
+        "find-up": "^4.1.0",
+        "get-caller-file": "^2.0.1",
+        "require-directory": "^2.1.1",
+        "require-main-filename": "^2.0.0",
+        "set-blocking": "^2.0.0",
+        "string-width": "^4.2.0",
+        "which-module": "^2.0.0",
+        "y18n": "^4.0.0",
+        "yargs-parser": "^18.1.2"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/nyc/node_modules/yargs-parser": {
+      "version": "18.1.3",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+      "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+      "dev": true,
+      "dependencies": {
+        "camelcase": "^5.0.0",
+        "decamelize": "^1.2.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/oauth-sign": {
+      "version": "0.9.0",
+      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+      "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
+    "node_modules/onetime": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+      "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==",
+      "dependencies": {
+        "mimic-fn": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/optionator": {
+      "version": "0.9.3",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
+      "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
+      "dev": true,
+      "dependencies": {
+        "@aashutoshrathi/word-wrap": "^1.2.3",
+        "deep-is": "^0.1.3",
+        "fast-levenshtein": "^2.0.6",
+        "levn": "^0.4.1",
+        "prelude-ls": "^1.2.1",
+        "type-check": "^0.4.0"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/ora": {
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz",
+      "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==",
+      "dependencies": {
+        "chalk": "^2.4.2",
+        "cli-cursor": "^2.1.0",
+        "cli-spinners": "^2.0.0",
+        "log-symbols": "^2.2.0",
+        "strip-ansi": "^5.2.0",
+        "wcwidth": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/ora/node_modules/ansi-regex": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+      "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/ora/node_modules/chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "dependencies": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/ora/node_modules/escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/ora/node_modules/log-symbols": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
+      "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
+      "dependencies": {
+        "chalk": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/ora/node_modules/strip-ansi": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+      "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+      "dependencies": {
+        "ansi-regex": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/p-is-promise": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz",
+      "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/p-limit": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+      "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+      "dev": true,
+      "dependencies": {
+        "yocto-queue": "^0.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-locate": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+      "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+      "dev": true,
+      "dependencies": {
+        "p-limit": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-map": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz",
+      "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==",
+      "dev": true,
+      "dependencies": {
+        "aggregate-error": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/package-hash": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz",
+      "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==",
+      "dev": true,
+      "dependencies": {
+        "graceful-fs": "^4.1.15",
+        "hasha": "^5.0.0",
+        "lodash.flattendeep": "^4.4.0",
+        "release-zalgo": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/parent-module": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+      "dev": true,
+      "dependencies": {
+        "callsites": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+      "devOptional": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/path-key": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+      "dev": true
+    },
+    "node_modules/path-type": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/pathval": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz",
+      "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 14.16"
+      }
+    },
+    "node_modules/performance-now": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+      "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
+    },
+    "node_modules/picocolors": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+      "dev": true
+    },
+    "node_modules/picomatch": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/pkg": {
+      "version": "5.8.1",
+      "resolved": "https://registry.npmjs.org/pkg/-/pkg-5.8.1.tgz",
+      "integrity": "sha512-CjBWtFStCfIiT4Bde9QpJy0KeH19jCfwZRJqHFDFXfhUklCx8JoFmMj3wgnEYIwGmZVNkhsStPHEOnrtrQhEXA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/generator": "7.18.2",
+        "@babel/parser": "7.18.4",
+        "@babel/types": "7.19.0",
+        "chalk": "^4.1.2",
+        "fs-extra": "^9.1.0",
+        "globby": "^11.1.0",
+        "into-stream": "^6.0.0",
+        "is-core-module": "2.9.0",
+        "minimist": "^1.2.6",
+        "multistream": "^4.1.0",
+        "pkg-fetch": "3.4.2",
+        "prebuild-install": "7.1.1",
+        "resolve": "^1.22.0",
+        "stream-meter": "^1.0.4"
+      },
+      "bin": {
+        "pkg": "lib-es5/bin.js"
+      },
+      "peerDependencies": {
+        "node-notifier": ">=9.0.1"
+      },
+      "peerDependenciesMeta": {
+        "node-notifier": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/pkg-dir": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+      "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+      "dev": true,
+      "dependencies": {
+        "find-up": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/pkg-dir/node_modules/find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "dev": true,
+      "dependencies": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/pkg-dir/node_modules/locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "dev": true,
+      "dependencies": {
+        "p-locate": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/pkg-dir/node_modules/p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "dev": true,
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/pkg-dir/node_modules/p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "dev": true,
+      "dependencies": {
+        "p-limit": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/pkg-fetch": {
+      "version": "3.4.2",
+      "resolved": "https://registry.npmjs.org/pkg-fetch/-/pkg-fetch-3.4.2.tgz",
+      "integrity": "sha512-0+uijmzYcnhC0hStDjm/cl2VYdrmVVBpe7Q8k9YBojxmR5tG8mvR9/nooQq3QSXiQqORDVOTY3XqMEqJVIzkHA==",
+      "dev": true,
+      "dependencies": {
+        "chalk": "^4.1.2",
+        "fs-extra": "^9.1.0",
+        "https-proxy-agent": "^5.0.0",
+        "node-fetch": "^2.6.6",
+        "progress": "^2.0.3",
+        "semver": "^7.3.5",
+        "tar-fs": "^2.1.1",
+        "yargs": "^16.2.0"
+      },
+      "bin": {
+        "pkg-fetch": "lib-es5/bin.js"
+      }
+    },
+    "node_modules/pkg-fetch/node_modules/cliui": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+      "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+      "dev": true,
+      "dependencies": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.0",
+        "wrap-ansi": "^7.0.0"
+      }
+    },
+    "node_modules/pkg-fetch/node_modules/lru-cache": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/pkg-fetch/node_modules/semver": {
+      "version": "7.5.4",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+      "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+      "dev": true,
+      "dependencies": {
+        "lru-cache": "^6.0.0"
+      },
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/pkg-fetch/node_modules/yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "dev": true
+    },
+    "node_modules/pkg-fetch/node_modules/yargs": {
+      "version": "16.2.0",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+      "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+      "dev": true,
+      "dependencies": {
+        "cliui": "^7.0.2",
+        "escalade": "^3.1.1",
+        "get-caller-file": "^2.0.5",
+        "require-directory": "^2.1.1",
+        "string-width": "^4.2.0",
+        "y18n": "^5.0.5",
+        "yargs-parser": "^20.2.2"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/pkg/node_modules/@babel/generator": {
+      "version": "7.18.2",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz",
+      "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.18.2",
+        "@jridgewell/gen-mapping": "^0.3.0",
+        "jsesc": "^2.5.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/pkg/node_modules/@babel/parser": {
+      "version": "7.18.4",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.4.tgz",
+      "integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==",
+      "dev": true,
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/pkg/node_modules/@babel/types": {
+      "version": "7.19.0",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz",
+      "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.18.10",
+        "@babel/helper-validator-identifier": "^7.18.6",
+        "to-fast-properties": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/prebuild-install": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
+      "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==",
+      "dependencies": {
+        "detect-libc": "^2.0.0",
+        "expand-template": "^2.0.3",
+        "github-from-package": "0.0.0",
+        "minimist": "^1.2.3",
+        "mkdirp-classic": "^0.5.3",
+        "napi-build-utils": "^1.0.1",
+        "node-abi": "^3.3.0",
+        "pump": "^3.0.0",
+        "rc": "^1.2.7",
+        "simple-get": "^4.0.0",
+        "tar-fs": "^2.0.0",
+        "tunnel-agent": "^0.6.0"
+      },
+      "bin": {
+        "prebuild-install": "bin.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/prelude-ls": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+      "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/process-nextick-args": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+      "dev": true
+    },
+    "node_modules/process-on-spawn": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz",
+      "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==",
+      "dev": true,
+      "dependencies": {
+        "fromentries": "^1.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/progress": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+      "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/promise-inflight": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+      "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/promise-retry": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
+      "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "err-code": "^2.0.2",
+        "retry": "^0.12.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/prompt": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.3.0.tgz",
+      "integrity": "sha512-ZkaRWtaLBZl7KKAKndKYUL8WqNT+cQHKRZnT4RYYms48jQkFw3rrBL+/N5K/KtdEveHkxs982MX2BkDKub2ZMg==",
+      "dependencies": {
+        "@colors/colors": "1.5.0",
+        "async": "3.2.3",
+        "read": "1.0.x",
+        "revalidator": "0.1.x",
+        "winston": "2.x"
+      },
+      "engines": {
+        "node": ">= 6.0.0"
+      }
+    },
+    "node_modules/prompt/node_modules/async": {
+      "version": "3.2.3",
+      "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz",
+      "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g=="
+    },
+    "node_modules/propagate": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz",
+      "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==",
+      "dev": true,
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/psl": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
+      "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
+    },
+    "node_modules/pump": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+      "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+      "dependencies": {
+        "end-of-stream": "^1.1.0",
+        "once": "^1.3.1"
+      }
+    },
+    "node_modules/punycode": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+      "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ=="
+    },
+    "node_modules/qs": {
+      "version": "6.5.3",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
+      "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
+      "engines": {
+        "node": ">=0.6"
+      }
+    },
+    "node_modules/queue-microtask": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/randombytes": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+      "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+      "dev": true,
+      "dependencies": {
+        "safe-buffer": "^5.1.0"
+      }
+    },
+    "node_modules/rc": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+      "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+      "dependencies": {
+        "deep-extend": "^0.6.0",
+        "ini": "~1.3.0",
+        "minimist": "^1.2.0",
+        "strip-json-comments": "~2.0.1"
+      },
+      "bin": {
+        "rc": "cli.js"
+      }
+    },
+    "node_modules/rc/node_modules/ini": {
+      "version": "1.3.8",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+      "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
+    },
+    "node_modules/rc/node_modules/strip-json-comments": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+      "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/read": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
+      "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==",
+      "dependencies": {
+        "mute-stream": "~0.0.4"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/readable-stream": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/readdirp": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+      "dev": true,
+      "dependencies": {
+        "picomatch": "^2.2.1"
+      },
+      "engines": {
+        "node": ">=8.10.0"
+      }
+    },
+    "node_modules/release-zalgo": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz",
+      "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==",
+      "dev": true,
+      "dependencies": {
+        "es6-error": "^4.0.1"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/request": {
+      "version": "2.88.0",
+      "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
+      "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
+      "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
+      "dependencies": {
+        "aws-sign2": "~0.7.0",
+        "aws4": "^1.8.0",
+        "caseless": "~0.12.0",
+        "combined-stream": "~1.0.6",
+        "extend": "~3.0.2",
+        "forever-agent": "~0.6.1",
+        "form-data": "~2.3.2",
+        "har-validator": "~5.1.0",
+        "http-signature": "~1.2.0",
+        "is-typedarray": "~1.0.0",
+        "isstream": "~0.1.2",
+        "json-stringify-safe": "~5.0.1",
+        "mime-types": "~2.1.19",
+        "oauth-sign": "~0.9.0",
+        "performance-now": "^2.1.0",
+        "qs": "~6.5.2",
+        "safe-buffer": "^5.1.2",
+        "tough-cookie": "~2.4.3",
+        "tunnel-agent": "^0.6.0",
+        "uuid": "^3.3.2"
+      },
+      "engines": {
+        "node": ">= 4"
+      }
+    },
+    "node_modules/request/node_modules/uuid": {
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+      "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+      "deprecated": "Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.",
+      "bin": {
+        "uuid": "bin/uuid"
+      }
+    },
+    "node_modules/require-directory": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/require-main-filename": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+      "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+      "dev": true
+    },
+    "node_modules/resolve": {
+      "version": "1.22.8",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+      "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+      "dev": true,
+      "dependencies": {
+        "is-core-module": "^2.13.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      },
+      "bin": {
+        "resolve": "bin/resolve"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/resolve-from": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+      "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/resolve/node_modules/is-core-module": {
+      "version": "2.13.1",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
+      "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
+      "dev": true,
+      "dependencies": {
+        "hasown": "^2.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/restore-cursor": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+      "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==",
+      "dependencies": {
+        "onetime": "^2.0.0",
+        "signal-exit": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/retry": {
+      "version": "0.12.0",
+      "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+      "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">= 4"
+      }
+    },
+    "node_modules/reusify": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+      "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+      "dev": true,
+      "engines": {
+        "iojs": ">=1.0.0",
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/revalidator": {
+      "version": "0.1.8",
+      "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz",
+      "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==",
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/rewire": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/rewire/-/rewire-7.0.0.tgz",
+      "integrity": "sha512-DyyNyzwMtGYgu0Zl/ya0PR/oaunM+VuCuBxCuhYJHHaV0V+YvYa3bBGxb5OZ71vndgmp1pYY8F4YOwQo1siRGw==",
+      "dev": true,
+      "dependencies": {
+        "eslint": "^8.47.0"
+      }
+    },
+    "node_modules/rimraf": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+      "devOptional": true,
+      "dependencies": {
+        "glob": "^7.1.3"
+      },
+      "bin": {
+        "rimraf": "bin.js"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/run-parallel": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "dependencies": {
+        "queue-microtask": "^1.2.2"
+      }
+    },
+    "node_modules/safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+    },
+    "node_modules/secure-keys": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/secure-keys/-/secure-keys-1.0.0.tgz",
+      "integrity": "sha512-nZi59hW3Sl5P3+wOO89eHBAAGwmCPd2aE1+dLZV5MO+ItQctIvAqihzaAXIQhvtH4KJPxM080HsnqltR2y8cWg=="
+    },
+    "node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/serialize-javascript": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+      "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+      "dev": true,
+      "dependencies": {
+        "randombytes": "^2.1.0"
+      }
+    },
+    "node_modules/set-blocking": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+      "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
+      "devOptional": true
+    },
+    "node_modules/shebang-command": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+      "dev": true,
+      "dependencies": {
+        "shebang-regex": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shebang-regex": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/signal-exit": {
+      "version": "3.0.7",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+      "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+    },
+    "node_modules/simple-concat": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+      "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/simple-get": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+      "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "dependencies": {
+        "decompress-response": "^6.0.0",
+        "once": "^1.3.1",
+        "simple-concat": "^1.0.0"
+      }
+    },
+    "node_modules/slash": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/smart-buffer": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+      "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">= 6.0.0",
+        "npm": ">= 3.0.0"
+      }
+    },
+    "node_modules/socks": {
+      "version": "2.8.3",
+      "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
+      "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "ip-address": "^9.0.5",
+        "smart-buffer": "^4.2.0"
+      },
+      "engines": {
+        "node": ">= 10.0.0",
+        "npm": ">= 3.0.0"
+      }
+    },
+    "node_modules/socks-proxy-agent": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz",
+      "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "agent-base": "^6.0.2",
+        "debug": "^4.3.3",
+        "socks": "^2.6.2"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/spawn-wrap": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz",
+      "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==",
+      "dev": true,
+      "dependencies": {
+        "foreground-child": "^2.0.0",
+        "is-windows": "^1.0.2",
+        "make-dir": "^3.0.0",
+        "rimraf": "^3.0.0",
+        "signal-exit": "^3.0.2",
+        "which": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/sprintf-js": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+      "dev": true
+    },
+    "node_modules/sqlite3": {
+      "version": "5.1.7",
+      "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz",
+      "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==",
+      "hasInstallScript": true,
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "bindings": "^1.5.0",
+        "node-addon-api": "^7.0.0",
+        "prebuild-install": "^7.1.1",
+        "tar": "^6.1.11"
+      },
+      "optionalDependencies": {
+        "node-gyp": "8.x"
+      },
+      "peerDependencies": {
+        "node-gyp": "8.x"
+      },
+      "peerDependenciesMeta": {
+        "node-gyp": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/sqlite3/node_modules/node-addon-api": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
+      "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+      "license": "MIT"
+    },
+    "node_modules/sshpk": {
+      "version": "1.18.0",
+      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
+      "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==",
+      "dependencies": {
+        "asn1": "~0.2.3",
+        "assert-plus": "^1.0.0",
+        "bcrypt-pbkdf": "^1.0.0",
+        "dashdash": "^1.12.0",
+        "ecc-jsbn": "~0.1.1",
+        "getpass": "^0.1.1",
+        "jsbn": "~0.1.0",
+        "safer-buffer": "^2.0.2",
+        "tweetnacl": "~0.14.0"
+      },
+      "bin": {
+        "sshpk-conv": "bin/sshpk-conv",
+        "sshpk-sign": "bin/sshpk-sign",
+        "sshpk-verify": "bin/sshpk-verify"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/ssri": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
+      "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "minipass": "^3.1.1"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/stack-trace": {
+      "version": "0.0.10",
+      "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
+      "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/stream-meter": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/stream-meter/-/stream-meter-1.0.4.tgz",
+      "integrity": "sha512-4sOEtrbgFotXwnEuzzsQBYEV1elAeFSO8rSGeTwabuX1RRn/kEq9JVH7I0MRBhKVRR0sJkr0M0QCH7yOLf9fhQ==",
+      "dev": true,
+      "dependencies": {
+        "readable-stream": "^2.1.4"
+      }
+    },
+    "node_modules/stream-meter/node_modules/readable-stream": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+      "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+      "dev": true,
+      "dependencies": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
+      }
+    },
+    "node_modules/stream-meter/node_modules/safe-buffer": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+      "dev": true
+    },
+    "node_modules/stream-meter/node_modules/string_decoder": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "dev": true,
+      "dependencies": {
+        "safe-buffer": "~5.1.0"
+      }
+    },
+    "node_modules/string_decoder": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+      "dependencies": {
+        "safe-buffer": "~5.2.0"
+      }
+    },
+    "node_modules/string-width": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "license": "MIT",
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/strip-bom": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+      "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/strip-json-comments": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+      "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "dependencies": {
+        "has-flag": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/tar": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
+      "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
+      "license": "ISC",
+      "dependencies": {
+        "chownr": "^2.0.0",
+        "fs-minipass": "^2.0.0",
+        "minipass": "^5.0.0",
+        "minizlib": "^2.1.1",
+        "mkdirp": "^1.0.3",
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/tar-fs": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
+      "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
+      "dependencies": {
+        "chownr": "^1.1.1",
+        "mkdirp-classic": "^0.5.2",
+        "pump": "^3.0.0",
+        "tar-stream": "^2.1.4"
+      }
+    },
+    "node_modules/tar-stream": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+      "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+      "dependencies": {
+        "bl": "^4.0.3",
+        "end-of-stream": "^1.4.1",
+        "fs-constants": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^3.1.1"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/tar/node_modules/chownr": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+      "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+      "license": "ISC",
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/tar/node_modules/minipass": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
+      "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+      "license": "ISC",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tar/node_modules/mkdirp": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+      "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+      "license": "MIT",
+      "bin": {
+        "mkdirp": "bin/cmd.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/tar/node_modules/yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "license": "ISC"
+    },
+    "node_modules/test-exclude": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+      "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+      "dev": true,
+      "dependencies": {
+        "@istanbuljs/schema": "^0.1.2",
+        "glob": "^7.1.4",
+        "minimatch": "^3.0.4"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/text-table": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+      "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+      "dev": true
+    },
+    "node_modules/to-fast-properties": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+      "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "dev": true,
+      "dependencies": {
+        "is-number": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=8.0"
+      }
+    },
+    "node_modules/tough-cookie": {
+      "version": "2.4.3",
+      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
+      "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
+      "dependencies": {
+        "psl": "^1.1.24",
+        "punycode": "^1.4.1"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/tr46": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+      "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+      "dev": true
+    },
+    "node_modules/tunnel-agent": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+      "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+      "dependencies": {
+        "safe-buffer": "^5.0.1"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/tweetnacl": {
+      "version": "0.14.5",
+      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+      "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="
+    },
+    "node_modules/type-check": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+      "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+      "dev": true,
+      "dependencies": {
+        "prelude-ls": "^1.2.1"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/type-fest": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+      "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/typedarray-to-buffer": {
+      "version": "3.1.5",
+      "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+      "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+      "dev": true,
+      "dependencies": {
+        "is-typedarray": "^1.0.0"
+      }
+    },
+    "node_modules/underscore": {
+      "version": "1.13.6",
+      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz",
+      "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A=="
+    },
+    "node_modules/unique-filename": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
+      "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "unique-slug": "^2.0.0"
+      }
+    },
+    "node_modules/unique-slug": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
+      "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "imurmurhash": "^0.1.4"
+      }
+    },
+    "node_modules/universalify": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
+      "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+      "dev": true,
+      "engines": {
+        "node": ">= 10.0.0"
+      }
+    },
+    "node_modules/update-browserslist-db": {
+      "version": "1.0.13",
+      "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
+      "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "dependencies": {
+        "escalade": "^3.1.1",
+        "picocolors": "^1.0.0"
+      },
+      "bin": {
+        "update-browserslist-db": "cli.js"
+      },
+      "peerDependencies": {
+        "browserslist": ">= 4.21.0"
+      }
+    },
+    "node_modules/uri-js": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+      "dependencies": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "node_modules/uri-js/node_modules/punycode": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+      "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+    },
+    "node_modules/uuid": {
+      "version": "8.3.2",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+      "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+      "dev": true,
+      "bin": {
+        "uuid": "dist/bin/uuid"
+      }
+    },
+    "node_modules/verror": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+      "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
+      "engines": [
+        "node >=0.6.0"
+      ],
+      "dependencies": {
+        "assert-plus": "^1.0.0",
+        "core-util-is": "1.0.2",
+        "extsprintf": "^1.2.0"
+      }
+    },
+    "node_modules/wcwidth": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+      "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
+      "dependencies": {
+        "defaults": "^1.0.3"
+      }
+    },
+    "node_modules/webidl-conversions": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+      "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+      "dev": true
+    },
+    "node_modules/whatwg-url": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+      "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+      "dev": true,
+      "dependencies": {
+        "tr46": "~0.0.3",
+        "webidl-conversions": "^3.0.0"
+      }
+    },
+    "node_modules/which": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "devOptional": true,
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "node-which": "bin/node-which"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/which-module": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
+      "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
+      "dev": true
+    },
+    "node_modules/wide-align": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
+      "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "string-width": "^1.0.2 || 2 || 3 || 4"
+      }
+    },
+    "node_modules/winston": {
+      "version": "2.4.7",
+      "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz",
+      "integrity": "sha512-vLB4BqzCKDnnZH9PHGoS2ycawueX4HLqENXQitvFHczhgW2vFpSOn31LZtVr1KU8YTw7DS4tM+cqyovxo8taVg==",
+      "dependencies": {
+        "async": "^2.6.4",
+        "colors": "1.0.x",
+        "cycle": "1.0.x",
+        "eyes": "0.1.x",
+        "isstream": "0.1.x",
+        "stack-trace": "0.0.x"
+      },
+      "engines": {
+        "node": ">= 0.10.0"
+      }
+    },
+    "node_modules/winston/node_modules/async": {
+      "version": "2.6.4",
+      "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
+      "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
+      "dependencies": {
+        "lodash": "^4.17.14"
+      }
+    },
+    "node_modules/wordwrap": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+      "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="
+    },
+    "node_modules/workerpool": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
+      "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
+      "dev": true
+    },
+    "node_modules/wrap-ansi": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+      "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+      }
+    },
+    "node_modules/wrap-ansi/node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/wrap-ansi/node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/wrap-ansi/node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+    },
+    "node_modules/wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+    },
+    "node_modules/write-file-atomic": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+      "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+      "dev": true,
+      "dependencies": {
+        "imurmurhash": "^0.1.4",
+        "is-typedarray": "^1.0.0",
+        "signal-exit": "^3.0.2",
+        "typedarray-to-buffer": "^3.1.5"
+      }
+    },
+    "node_modules/y18n": {
+      "version": "5.0.8",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+      "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/yallist": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+      "dev": true
+    },
+    "node_modules/yargs": {
+      "version": "17.7.2",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+      "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+      "dependencies": {
+        "cliui": "^8.0.1",
+        "escalade": "^3.1.1",
+        "get-caller-file": "^2.0.5",
+        "require-directory": "^2.1.1",
+        "string-width": "^4.2.3",
+        "y18n": "^5.0.5",
+        "yargs-parser": "^21.1.1"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/yargs-parser": {
+      "version": "20.2.4",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
+      "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/yargs-unparser": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+      "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
+      "dev": true,
+      "dependencies": {
+        "camelcase": "^6.0.0",
+        "decamelize": "^4.0.0",
+        "flat": "^5.0.2",
+        "is-plain-obj": "^2.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/yargs-unparser/node_modules/camelcase": {
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+      "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/yargs-unparser/node_modules/decamelize": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+      "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/yargs/node_modules/yargs-parser": {
+      "version": "21.1.1",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+      "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/yocto-queue": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+      "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    }
+  }
+}
diff --git a/package.json b/package.json
index a9af9f7c..149604a2 100644
--- a/package.json
+++ b/package.json
@@ -1,19 +1,16 @@
 {
-  "name": "leetcode-cli",
-  "version": "2.6.2",
+  "name": "lc",
+  "version": "3.0.0",
   "description": "A cli tool to enjoy leetcode!",
-  "preferGlobal": "true",
   "engines": {
-    "node": ">=4"
+    "node": ">=20"
   },
   "bin": {
-    "leetcode": "./bin/leetcode"
+    "lc": "./bin/leetcode"
   },
   "scripts": {
     "lint": "eslint lib/ test/",
-    "test": "npm run lint && nyc mocha test test/plugins && nyc report --reporter=lcov",
-    "travis": "node bin/pkg",
-    "pkg": "pkg . --out-path=dist/ --targets"
+    "test": "pnpm run lint && nyc mocha test test/commands test/plugins && nyc report --reporter=lcov"
   },
   "pkg": {
     "scripts": [
@@ -25,14 +22,17 @@
       "templates"
     ],
     "targets": [
-      "node10-linux-x64",
-      "node10-macos-x64",
-      "node10-win-x64"
-    ]
+      "node20-linux-x64",
+      "node20-linux-arm64",
+      "node20-macos-x64",
+      "node20-macos-arm64",
+      "node20-win-x64"
+    ],
+    "outputPath": "dist"
   },
   "repository": {
     "type": "git",
-    "url": "http://github.com/skygragon/leetcode-cli.git"
+    "url": "http://github.com/dp9u0/leetcode-cli.git"
   },
   "keywords": [
     "leetcode",
@@ -41,37 +41,34 @@
     "tool"
   ],
   "author": {
-    "name": "Eric Wang",
-    "email": "skygragon@gmail.com"
+    "name": "guodengpeng",
+    "email": "guodp9u0@gmail.com"
   },
   "license": "MIT",
   "bugs": {
-    "url": "https://github.com/skygragon/leetcode-cli/issues"
+    "url": "https://github.com/dp9u0/leetcode-cli/issues"
   },
-  "homepage": "https://github.com/skygragon/leetcode-cli#readme",
+  "homepage": "https://github.com/dp9u0/leetcode-cli#readme",
   "dependencies": {
-    "ansi-styles": "3.2.1",
-    "cheerio": "0.20.0",
+    "ansi-styles": "^3.2.1",
+    "axios": "^1.7.0",
+    "cheerio": "1.2.0",
     "he": "1.2.0",
-    "mkdirp": "0.5.1",
-    "moment": "^2.20.1",
-    "nconf": "0.10.0",
-    "ora": "3.0.0",
-    "prompt": "1.0.0",
-    "request": "2.88.0",
-    "supports-color": "5.5.0",
-    "underscore": "1.9.1",
-    "wordwrap": "1.0.0",
-    "yargs": "12.0.4"
+    "moment": "^2.30.1",
+    "nconf": "0.13.0",
+    "ora": "^3.4.0",
+    "supports-color": "^5.5.0",
+    "underscore": "1.13.8",
+    "yargs": "17.7.2"
   },
   "devDependencies": {
-    "chai": "4.2.0",
-    "eslint": "5.9.0",
-    "eslint-config-google": "0.11.0",
-    "mocha": "5.2.0",
-    "nock": "10.0.2",
-    "nyc": "13.1.0",
-    "pkg": "^4.3.4",
-    "rewire": "4.0.1"
+    "@eslint/js": "^10.0.1",
+    "@yao-pkg/pkg": "^6.22.0",
+    "chai": "^6.2.2",
+    "eslint": "^10.9.1",
+    "mocha": "^11.8.0",
+    "nock": "^14.0.17",
+    "nyc": "^18.0.0",
+    "rewire": "^9.0.1"
   }
-}
+}
\ No newline at end of file
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 00000000..77b3bd3a
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,3828 @@
+lockfileVersion: '9.0'
+
+settings:
+  autoInstallPeers: true
+  excludeLinksFromLockfile: false
+
+importers:
+
+  .:
+    dependencies:
+      ansi-styles:
+        specifier: ^3.2.1
+        version: 3.2.1
+      axios:
+        specifier: ^1.7.0
+        version: 1.20.0(supports-color@5.5.0)
+      cheerio:
+        specifier: 1.2.0
+        version: 1.2.0
+      he:
+        specifier: 1.2.0
+        version: 1.2.0
+      moment:
+        specifier: ^2.30.1
+        version: 2.30.1
+      nconf:
+        specifier: 0.13.0
+        version: 0.13.0
+      ora:
+        specifier: ^3.4.0
+        version: 3.4.0
+      supports-color:
+        specifier: ^5.5.0
+        version: 5.5.0
+      underscore:
+        specifier: 1.13.8
+        version: 1.13.8
+      yargs:
+        specifier: 17.7.2
+        version: 17.7.2
+    devDependencies:
+      '@eslint/js':
+        specifier: ^10.0.1
+        version: 10.0.1(eslint@10.9.1(supports-color@5.5.0))
+      '@yao-pkg/pkg':
+        specifier: ^6.22.0
+        version: 6.22.0(supports-color@5.5.0)
+      chai:
+        specifier: ^6.2.2
+        version: 6.2.2
+      eslint:
+        specifier: ^10.9.1
+        version: 10.9.1(supports-color@5.5.0)
+      mocha:
+        specifier: ^11.8.0
+        version: 11.8.0
+      nock:
+        specifier: ^14.0.17
+        version: 14.0.17
+      nyc:
+        specifier: ^18.0.0
+        version: 18.0.0(supports-color@5.5.0)
+      rewire:
+        specifier: ^9.0.1
+        version: 9.0.1(supports-color@5.5.0)
+
+packages:
+
+  '@babel/code-frame@7.29.0':
+    resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/compat-data@7.29.0':
+    resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/core@7.29.0':
+    resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/generator@7.29.1':
+    resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-compilation-targets@7.28.6':
+    resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-globals@7.28.0':
+    resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-module-imports@7.28.6':
+    resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-module-transforms@7.28.6':
+    resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0
+
+  '@babel/helper-string-parser@7.27.1':
+    resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-validator-identifier@7.28.5':
+    resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-validator-option@7.27.1':
+    resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helpers@7.29.2':
+    resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/parser@7.29.2':
+    resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==}
+    engines: {node: '>=6.0.0'}
+    hasBin: true
+
+  '@babel/template@7.28.6':
+    resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/traverse@7.29.0':
+    resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/types@7.29.0':
+    resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
+    engines: {node: '>=6.9.0'}
+
+  '@esbuild/aix-ppc64@0.28.2':
+    resolution: {integrity: sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==}
+    engines: {node: '>=18'}
+    cpu: [ppc64]
+    os: [aix]
+
+  '@esbuild/android-arm64@0.28.2':
+    resolution: {integrity: sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [android]
+
+  '@esbuild/android-arm@0.28.2':
+    resolution: {integrity: sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==}
+    engines: {node: '>=18'}
+    cpu: [arm]
+    os: [android]
+
+  '@esbuild/android-x64@0.28.2':
+    resolution: {integrity: sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [android]
+
+  '@esbuild/darwin-arm64@0.28.2':
+    resolution: {integrity: sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [darwin]
+
+  '@esbuild/darwin-x64@0.28.2':
+    resolution: {integrity: sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [darwin]
+
+  '@esbuild/freebsd-arm64@0.28.2':
+    resolution: {integrity: sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [freebsd]
+
+  '@esbuild/freebsd-x64@0.28.2':
+    resolution: {integrity: sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [freebsd]
+
+  '@esbuild/linux-arm64@0.28.2':
+    resolution: {integrity: sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [linux]
+
+  '@esbuild/linux-arm@0.28.2':
+    resolution: {integrity: sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==}
+    engines: {node: '>=18'}
+    cpu: [arm]
+    os: [linux]
+
+  '@esbuild/linux-ia32@0.28.2':
+    resolution: {integrity: sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==}
+    engines: {node: '>=18'}
+    cpu: [ia32]
+    os: [linux]
+
+  '@esbuild/linux-loong64@0.28.2':
+    resolution: {integrity: sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==}
+    engines: {node: '>=18'}
+    cpu: [loong64]
+    os: [linux]
+
+  '@esbuild/linux-mips64el@0.28.2':
+    resolution: {integrity: sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==}
+    engines: {node: '>=18'}
+    cpu: [mips64el]
+    os: [linux]
+
+  '@esbuild/linux-ppc64@0.28.2':
+    resolution: {integrity: sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==}
+    engines: {node: '>=18'}
+    cpu: [ppc64]
+    os: [linux]
+
+  '@esbuild/linux-riscv64@0.28.2':
+    resolution: {integrity: sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==}
+    engines: {node: '>=18'}
+    cpu: [riscv64]
+    os: [linux]
+
+  '@esbuild/linux-s390x@0.28.2':
+    resolution: {integrity: sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==}
+    engines: {node: '>=18'}
+    cpu: [s390x]
+    os: [linux]
+
+  '@esbuild/linux-x64@0.28.2':
+    resolution: {integrity: sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [linux]
+
+  '@esbuild/netbsd-arm64@0.28.2':
+    resolution: {integrity: sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [netbsd]
+
+  '@esbuild/netbsd-x64@0.28.2':
+    resolution: {integrity: sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [netbsd]
+
+  '@esbuild/openbsd-arm64@0.28.2':
+    resolution: {integrity: sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [openbsd]
+
+  '@esbuild/openbsd-x64@0.28.2':
+    resolution: {integrity: sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [openbsd]
+
+  '@esbuild/openharmony-arm64@0.28.2':
+    resolution: {integrity: sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [openharmony]
+
+  '@esbuild/sunos-x64@0.28.2':
+    resolution: {integrity: sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [sunos]
+
+  '@esbuild/win32-arm64@0.28.2':
+    resolution: {integrity: sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [win32]
+
+  '@esbuild/win32-ia32@0.28.2':
+    resolution: {integrity: sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==}
+    engines: {node: '>=18'}
+    cpu: [ia32]
+    os: [win32]
+
+  '@esbuild/win32-x64@0.28.2':
+    resolution: {integrity: sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [win32]
+
+  '@eslint-community/eslint-utils@4.10.1':
+    resolution: {integrity: sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    peerDependencies:
+      eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+
+  '@eslint-community/regexpp@4.12.2':
+    resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==}
+    engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+
+  '@eslint/config-array@0.21.2':
+    resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@eslint/config-array@0.23.5':
+    resolution: {integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==}
+    engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+
+  '@eslint/config-helpers@0.4.2':
+    resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@eslint/config-helpers@0.7.0':
+    resolution: {integrity: sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==}
+    engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+
+  '@eslint/core@0.17.0':
+    resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@eslint/core@1.2.1':
+    resolution: {integrity: sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==}
+    engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+
+  '@eslint/eslintrc@3.3.6':
+    resolution: {integrity: sha512-l2Ul9PrHsPCKcEY/ac7VgFj9D80C7S68sOKc618SyHDPK36s1XcFebXY0iTzUVn4Yq+YbwvSnDmCz9yxjX+QrA==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@eslint/js@10.0.1':
+    resolution: {integrity: sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==}
+    engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+    peerDependencies:
+      eslint: ^10.0.0
+    peerDependenciesMeta:
+      eslint:
+        optional: true
+
+  '@eslint/js@9.39.5':
+    resolution: {integrity: sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@eslint/object-schema@2.1.7':
+    resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@eslint/object-schema@3.0.5':
+    resolution: {integrity: sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==}
+    engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+
+  '@eslint/plugin-kit@0.4.1':
+    resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@eslint/plugin-kit@0.7.2':
+    resolution: {integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==}
+    engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+
+  '@humanfs/core@0.19.2':
+    resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==}
+    engines: {node: '>=18.18.0'}
+
+  '@humanfs/node@0.16.8':
+    resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==}
+    engines: {node: '>=18.18.0'}
+
+  '@humanfs/types@0.15.0':
+    resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==}
+    engines: {node: '>=18.18.0'}
+
+  '@humanwhocodes/module-importer@1.0.1':
+    resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
+    engines: {node: '>=12.22'}
+
+  '@humanwhocodes/retry@0.4.3':
+    resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
+    engines: {node: '>=18.18'}
+
+  '@isaacs/cliui@8.0.2':
+    resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
+    engines: {node: '>=12'}
+
+  '@isaacs/fs-minipass@4.0.1':
+    resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
+    engines: {node: '>=18.0.0'}
+
+  '@istanbuljs/load-nyc-config@1.1.0':
+    resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==}
+    engines: {node: '>=8'}
+
+  '@istanbuljs/schema@0.1.3':
+    resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
+    engines: {node: '>=8'}
+
+  '@jridgewell/gen-mapping@0.3.13':
+    resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
+
+  '@jridgewell/remapping@2.3.5':
+    resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
+
+  '@jridgewell/resolve-uri@3.1.2':
+    resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+    engines: {node: '>=6.0.0'}
+
+  '@jridgewell/sourcemap-codec@1.5.5':
+    resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
+
+  '@jridgewell/trace-mapping@0.3.31':
+    resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+
+  '@mswjs/interceptors@0.41.9':
+    resolution: {integrity: sha512-VVPPgHyQ6ShqnrmDWuxjmUIsO9gWyOZFmuOfLd9LfBGQJwZfy0gvv9pbHSJuoFNIYC7ZDX9aoFwowjcdSC4E8w==}
+    engines: {node: '>=18'}
+
+  '@open-draft/deferred-promise@2.2.0':
+    resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==}
+
+  '@open-draft/logger@0.3.0':
+    resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==}
+
+  '@open-draft/until@2.1.0':
+    resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==}
+
+  '@pkgjs/parseargs@0.11.0':
+    resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
+    engines: {node: '>=14'}
+
+  '@roberts_lando/vfs@0.3.3':
+    resolution: {integrity: sha512-YjkxVSLw5WMZQoARaryRAjcxA+GbBzWMJdwYZX5oLUt9cC/gew9as4Dn7tcLzPp7BPoR221VpTZ+78TRPawnjg==}
+    engines: {node: '>= 22'}
+
+  '@types/esrecurse@4.3.1':
+    resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==}
+
+  '@types/estree@1.0.9':
+    resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
+
+  '@types/json-schema@7.0.15':
+    resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
+
+  '@yao-pkg/pkg-fetch@3.6.5':
+    resolution: {integrity: sha512-Sd1Hff7imsF2rcZ2GLQuIzVm2fc3Za+nE4KSWPTwIYegN/r90UFg3bq0MLSugbWQaVht72zzxV0MiKE0wvT1zA==}
+    hasBin: true
+
+  '@yao-pkg/pkg@6.22.0':
+    resolution: {integrity: sha512-u+ZgwLsvEFB+Q1rA+IGymgxnm+anl1qGJWsTH6hDHyy2cCiOvMteDNK7NgqFYxN/zdithtORIlCsYSyhAXAgQA==}
+    engines: {node: '>=22.0.0'}
+    hasBin: true
+
+  acorn-jsx@5.3.2:
+    resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+    peerDependencies:
+      acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+
+  acorn@8.18.0:
+    resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==}
+    engines: {node: '>=0.4.0'}
+    hasBin: true
+
+  agent-base@6.0.2:
+    resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
+    engines: {node: '>= 6.0.0'}
+
+  aggregate-error@3.1.0:
+    resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
+    engines: {node: '>=8'}
+
+  ajv@6.14.0:
+    resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==}
+
+  ansi-regex@4.1.1:
+    resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==}
+    engines: {node: '>=6'}
+
+  ansi-regex@5.0.1:
+    resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+    engines: {node: '>=8'}
+
+  ansi-regex@6.3.0:
+    resolution: {integrity: sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==}
+    engines: {node: '>=12'}
+
+  ansi-styles@3.2.1:
+    resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
+    engines: {node: '>=4'}
+
+  ansi-styles@4.3.0:
+    resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+    engines: {node: '>=8'}
+
+  ansi-styles@6.2.3:
+    resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
+    engines: {node: '>=12'}
+
+  append-transform@2.0.0:
+    resolution: {integrity: sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==}
+    engines: {node: '>=8'}
+
+  archy@1.0.0:
+    resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==}
+
+  argparse@1.0.10:
+    resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
+
+  argparse@2.0.1:
+    resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+
+  async@3.2.6:
+    resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==}
+
+  asynckit@0.4.0:
+    resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+
+  axios@1.20.0:
+    resolution: {integrity: sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg==}
+
+  b4a@1.8.1:
+    resolution: {integrity: sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==}
+    peerDependencies:
+      react-native-b4a: '*'
+    peerDependenciesMeta:
+      react-native-b4a:
+        optional: true
+
+  balanced-match@1.0.2:
+    resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+
+  balanced-match@4.0.4:
+    resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
+    engines: {node: 18 || 20 || >=22}
+
+  bare-events@2.9.2:
+    resolution: {integrity: sha512-AIPKioV7/Y/8KfZ3AAhjPJxLLbY49S64Ym5DakZlUg75qQiTgUq9hEJoEwa4eUezPUlXRy/i5NpsKvo9jgKmoA==}
+    peerDependencies:
+      bare-abort-controller: '*'
+    peerDependenciesMeta:
+      bare-abort-controller:
+        optional: true
+
+  bare-fs@4.8.1:
+    resolution: {integrity: sha512-N1nnXdHZAOSstz0XiHikGS4HGMH4CnSwhqWdGQQMqqdvp4Jybm9sE3R1WVnpWVd4SFkc8ryPDBLViNLwiEqECg==}
+    engines: {bare: '>=1.28.0'}
+    peerDependencies:
+      bare-buffer: '*'
+    peerDependenciesMeta:
+      bare-buffer:
+        optional: true
+
+  bare-path@3.1.1:
+    resolution: {integrity: sha512-JprUlveX3QjApC1cTpsUOiscADftCGVWkzitbHsRqv84hzYwYHw2mbluddsq5TvI8mH/8Ov1f4BiMAdcB0oYnQ==}
+
+  bare-stream@2.13.4:
+    resolution: {integrity: sha512-PcrQ8lVLbiJscNm1Kez+Yp4Gy4AHGcN1lzwjvf5NybWen7VvEgUfyfnXYJ2zNqWnzOfCb1Abq6lH8ti0syQszA==}
+    peerDependencies:
+      bare-abort-controller: '*'
+      bare-buffer: '*'
+      bare-events: '*'
+    peerDependenciesMeta:
+      bare-abort-controller:
+        optional: true
+      bare-buffer:
+        optional: true
+      bare-events:
+        optional: true
+
+  bare-url@2.5.2:
+    resolution: {integrity: sha512-L13PCJzKG8RGvx8V1/DdMi12ERhC3tprr7/8a94BxpmnRsFqxh5XZNdhtMxu5HPkRshYOOWRGY8lDP7ZhpG9Cg==}
+
+  base64-js@1.5.1:
+    resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+
+  baseline-browser-mapping@2.10.16:
+    resolution: {integrity: sha512-Lyf3aK28zpsD1yQMiiHD4RvVb6UdMoo8xzG2XzFIfR9luPzOpcBlAsT/qfB1XWS1bxWT+UtE4WmQgsp297FYOA==}
+    engines: {node: '>=6.0.0'}
+    hasBin: true
+
+  bl@4.1.0:
+    resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
+
+  bluebird@3.7.2:
+    resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
+
+  boolbase@1.0.0:
+    resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
+
+  brace-expansion@1.1.13:
+    resolution: {integrity: sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==}
+
+  brace-expansion@2.1.4:
+    resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==}
+
+  brace-expansion@5.0.9:
+    resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==}
+    engines: {node: 20 || >=22}
+
+  browser-stdout@1.3.1:
+    resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==}
+
+  browserslist@4.28.2:
+    resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==}
+    engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+    hasBin: true
+
+  buffer@5.7.1:
+    resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
+
+  caching-transform@4.0.0:
+    resolution: {integrity: sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==}
+    engines: {node: '>=8'}
+
+  call-bind-apply-helpers@1.0.2:
+    resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
+    engines: {node: '>= 0.4'}
+
+  callsites@3.1.0:
+    resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+    engines: {node: '>=6'}
+
+  camelcase@5.3.1:
+    resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
+    engines: {node: '>=6'}
+
+  camelcase@6.3.0:
+    resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
+    engines: {node: '>=10'}
+
+  caniuse-lite@1.0.30001787:
+    resolution: {integrity: sha512-mNcrMN9KeI68u7muanUpEejSLghOKlVhRqS/Za2IeyGllJ9I9otGpR9g3nsw7n4W378TE/LyIteA0+/FOZm4Kg==}
+
+  chai@6.2.2:
+    resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==}
+    engines: {node: '>=18'}
+
+  chalk@2.4.2:
+    resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
+    engines: {node: '>=4'}
+
+  chalk@4.1.2:
+    resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+    engines: {node: '>=10'}
+
+  cheerio-select@2.1.0:
+    resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==}
+
+  cheerio@1.2.0:
+    resolution: {integrity: sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==}
+    engines: {node: '>=20.18.1'}
+
+  chokidar@4.0.3:
+    resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
+    engines: {node: '>= 14.16.0'}
+
+  chownr@1.1.4:
+    resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
+
+  chownr@3.0.0:
+    resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
+    engines: {node: '>=18'}
+
+  clean-stack@2.2.0:
+    resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
+    engines: {node: '>=6'}
+
+  cli-cursor@2.1.0:
+    resolution: {integrity: sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==}
+    engines: {node: '>=4'}
+
+  cli-spinners@2.9.2:
+    resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
+    engines: {node: '>=6'}
+
+  cliui@6.0.0:
+    resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
+
+  cliui@7.0.4:
+    resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
+
+  cliui@8.0.1:
+    resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+    engines: {node: '>=12'}
+
+  clone@1.0.4:
+    resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
+    engines: {node: '>=0.8'}
+
+  color-convert@1.9.3:
+    resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
+
+  color-convert@2.0.1:
+    resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+    engines: {node: '>=7.0.0'}
+
+  color-name@1.1.3:
+    resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
+
+  color-name@1.1.4:
+    resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+  combined-stream@1.0.8:
+    resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+    engines: {node: '>= 0.8'}
+
+  commander@9.5.0:
+    resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
+    engines: {node: ^12.20.0 || >=14}
+
+  commondir@1.0.1:
+    resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
+
+  concat-map@0.0.1:
+    resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+
+  convert-source-map@1.9.0:
+    resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
+
+  convert-source-map@2.0.0:
+    resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+
+  core-util-is@1.0.3:
+    resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
+
+  cross-spawn@7.0.6:
+    resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
+    engines: {node: '>= 8'}
+
+  css-select@5.2.2:
+    resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==}
+
+  css-what@6.2.2:
+    resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==}
+    engines: {node: '>= 6'}
+
+  debug@4.4.3:
+    resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+    engines: {node: '>=6.0'}
+    peerDependencies:
+      supports-color: '*'
+    peerDependenciesMeta:
+      supports-color:
+        optional: true
+
+  decamelize@1.2.0:
+    resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
+    engines: {node: '>=0.10.0'}
+
+  decamelize@4.0.0:
+    resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==}
+    engines: {node: '>=10'}
+
+  decompress-response@6.0.0:
+    resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
+    engines: {node: '>=10'}
+
+  deep-extend@0.6.0:
+    resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
+    engines: {node: '>=4.0.0'}
+
+  deep-is@0.1.4:
+    resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+
+  default-require-extensions@3.0.1:
+    resolution: {integrity: sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==}
+    engines: {node: '>=8'}
+
+  defaults@1.0.4:
+    resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
+
+  delayed-stream@1.0.0:
+    resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+    engines: {node: '>=0.4.0'}
+
+  detect-libc@2.1.2:
+    resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
+    engines: {node: '>=8'}
+
+  diff@7.0.0:
+    resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==}
+    engines: {node: '>=0.3.1'}
+
+  dom-serializer@2.0.0:
+    resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
+
+  domelementtype@2.3.0:
+    resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
+
+  domhandler@5.0.3:
+    resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
+    engines: {node: '>= 4'}
+
+  domutils@3.2.2:
+    resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}
+
+  dunder-proto@1.0.1:
+    resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
+    engines: {node: '>= 0.4'}
+
+  duplexer2@0.1.4:
+    resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==}
+
+  eastasianwidth@0.2.0:
+    resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+
+  electron-to-chromium@1.5.334:
+    resolution: {integrity: sha512-mgjZAz7Jyx1SRCwEpy9wefDS7GvNPazLthHg8eQMJ76wBdGQQDW33TCrUTvQ4wzpmOrv2zrFoD3oNufMdyMpog==}
+
+  emoji-regex@8.0.0:
+    resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+
+  emoji-regex@9.2.2:
+    resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+
+  encoding-sniffer@0.2.1:
+    resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==}
+
+  end-of-stream@1.4.5:
+    resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
+
+  entities@4.5.0:
+    resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
+    engines: {node: '>=0.12'}
+
+  entities@6.0.1:
+    resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
+    engines: {node: '>=0.12'}
+
+  entities@7.0.1:
+    resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==}
+    engines: {node: '>=0.12'}
+
+  es-define-property@1.0.1:
+    resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
+    engines: {node: '>= 0.4'}
+
+  es-errors@1.3.0:
+    resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+    engines: {node: '>= 0.4'}
+
+  es-object-atoms@1.1.2:
+    resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==}
+    engines: {node: '>= 0.4'}
+
+  es-set-tostringtag@2.1.0:
+    resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
+    engines: {node: '>= 0.4'}
+
+  es6-error@4.1.1:
+    resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==}
+
+  esbuild@0.28.2:
+    resolution: {integrity: sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==}
+    engines: {node: '>=18'}
+    hasBin: true
+
+  escalade@3.2.0:
+    resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+    engines: {node: '>=6'}
+
+  escape-string-regexp@1.0.5:
+    resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
+    engines: {node: '>=0.8.0'}
+
+  escape-string-regexp@4.0.0:
+    resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+    engines: {node: '>=10'}
+
+  eslint-scope@8.4.0:
+    resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  eslint-scope@9.1.2:
+    resolution: {integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==}
+    engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+
+  eslint-visitor-keys@3.4.3:
+    resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
+  eslint-visitor-keys@4.2.1:
+    resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  eslint-visitor-keys@5.0.1:
+    resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==}
+    engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+
+  eslint@10.9.1:
+    resolution: {integrity: sha512-9VaAkDURekixUQJy0oJYl2DcN6oKMfxay7XzaGYAWQwsb6qfKf+x76R2k1L8kb1boc+FyCAaTA9GmiKaaiaF+A==}
+    engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+    hasBin: true
+    peerDependencies:
+      jiti: '*'
+    peerDependenciesMeta:
+      jiti:
+        optional: true
+
+  eslint@9.39.5:
+    resolution: {integrity: sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options.
+    hasBin: true
+    peerDependencies:
+      jiti: '*'
+    peerDependenciesMeta:
+      jiti:
+        optional: true
+
+  espree@10.4.0:
+    resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  espree@11.2.0:
+    resolution: {integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==}
+    engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+
+  esprima@4.0.1:
+    resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
+    engines: {node: '>=4'}
+    hasBin: true
+
+  esquery@1.7.0:
+    resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==}
+    engines: {node: '>=0.10'}
+
+  esrecurse@4.3.0:
+    resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
+    engines: {node: '>=4.0'}
+
+  estraverse@5.3.0:
+    resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+    engines: {node: '>=4.0'}
+
+  esutils@2.0.3:
+    resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+    engines: {node: '>=0.10.0'}
+
+  events-universal@1.0.1:
+    resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==}
+
+  expand-template@2.0.3:
+    resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==}
+    engines: {node: '>=6'}
+
+  fast-deep-equal@3.1.3:
+    resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+
+  fast-fifo@1.3.2:
+    resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==}
+
+  fast-json-stable-stringify@2.1.0:
+    resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+
+  fast-levenshtein@2.0.6:
+    resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+
+  fdir@6.5.0:
+    resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+    engines: {node: '>=12.0.0'}
+    peerDependencies:
+      picomatch: ^3 || ^4
+    peerDependenciesMeta:
+      picomatch:
+        optional: true
+
+  file-entry-cache@8.0.0:
+    resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
+    engines: {node: '>=16.0.0'}
+
+  find-cache-dir@3.3.2:
+    resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==}
+    engines: {node: '>=8'}
+
+  find-up@4.1.0:
+    resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
+    engines: {node: '>=8'}
+
+  find-up@5.0.0:
+    resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+    engines: {node: '>=10'}
+
+  flat-cache@4.0.1:
+    resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
+    engines: {node: '>=16'}
+
+  flat@5.0.2:
+    resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==}
+    hasBin: true
+
+  flatted@3.4.4:
+    resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==}
+
+  follow-redirects@1.16.0:
+    resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==}
+    engines: {node: '>=4.0'}
+    peerDependencies:
+      debug: '*'
+    peerDependenciesMeta:
+      debug:
+        optional: true
+
+  foreground-child@2.0.0:
+    resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==}
+    engines: {node: '>=8.0.0'}
+
+  foreground-child@3.3.1:
+    resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
+    engines: {node: '>=14'}
+
+  form-data@4.0.6:
+    resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==}
+    engines: {node: '>= 6'}
+
+  fromentries@1.3.2:
+    resolution: {integrity: sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==}
+
+  fs-constants@1.0.0:
+    resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
+
+  fs-extra@11.3.1:
+    resolution: {integrity: sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==}
+    engines: {node: '>=14.14'}
+
+  function-bind@1.1.2:
+    resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+  gensync@1.0.0-beta.2:
+    resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+    engines: {node: '>=6.9.0'}
+
+  get-caller-file@2.0.5:
+    resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+    engines: {node: 6.* || 8.* || >= 10.*}
+
+  get-intrinsic@1.3.0:
+    resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
+    engines: {node: '>= 0.4'}
+
+  get-package-type@0.1.0:
+    resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==}
+    engines: {node: '>=8.0.0'}
+
+  get-proto@1.0.1:
+    resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
+    engines: {node: '>= 0.4'}
+
+  github-from-package@0.0.0:
+    resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==}
+
+  glob-parent@6.0.2:
+    resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+    engines: {node: '>=10.13.0'}
+
+  glob@10.5.0:
+    resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==}
+    deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
+    hasBin: true
+
+  glob@13.0.6:
+    resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==}
+    engines: {node: 18 || 20 || >=22}
+
+  globals@14.0.0:
+    resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
+    engines: {node: '>=18'}
+
+  gopd@1.2.0:
+    resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
+    engines: {node: '>= 0.4'}
+
+  graceful-fs@4.2.11:
+    resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
+  has-flag@3.0.0:
+    resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
+    engines: {node: '>=4'}
+
+  has-flag@4.0.0:
+    resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+    engines: {node: '>=8'}
+
+  has-symbols@1.1.0:
+    resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
+    engines: {node: '>= 0.4'}
+
+  has-tostringtag@1.0.2:
+    resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
+    engines: {node: '>= 0.4'}
+
+  hasha@5.2.2:
+    resolution: {integrity: sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==}
+    engines: {node: '>=8'}
+
+  hasown@2.0.4:
+    resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==}
+    engines: {node: '>= 0.4'}
+
+  he@1.2.0:
+    resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
+    hasBin: true
+
+  html-escaper@2.0.2:
+    resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
+
+  htmlparser2@10.1.0:
+    resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==}
+
+  https-proxy-agent@5.0.1:
+    resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
+    engines: {node: '>= 6'}
+
+  iconv-lite@0.6.3:
+    resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
+    engines: {node: '>=0.10.0'}
+
+  ieee754@1.2.1:
+    resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
+
+  ignore@5.3.2:
+    resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
+    engines: {node: '>= 4'}
+
+  import-fresh@3.3.1:
+    resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
+    engines: {node: '>=6'}
+
+  imurmurhash@0.1.4:
+    resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+    engines: {node: '>=0.8.19'}
+
+  indent-string@4.0.0:
+    resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
+    engines: {node: '>=8'}
+
+  inherits@2.0.4:
+    resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
+  ini@1.3.8:
+    resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
+
+  ini@2.0.0:
+    resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==}
+    engines: {node: '>=10'}
+
+  into-stream@9.1.0:
+    resolution: {integrity: sha512-DRsRnQrbzdFjaQ1oe4C6/EIUymIOEix1qROEJTF9dbMq+M4Zrm6VaLp6SD/B9IsiEjPZuBSnWWFN+udajugdWA==}
+    engines: {node: '>=20'}
+
+  is-core-module@2.16.2:
+    resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==}
+    engines: {node: '>= 0.4'}
+
+  is-extglob@2.1.1:
+    resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+    engines: {node: '>=0.10.0'}
+
+  is-fullwidth-code-point@3.0.0:
+    resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+    engines: {node: '>=8'}
+
+  is-glob@4.0.3:
+    resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+    engines: {node: '>=0.10.0'}
+
+  is-node-process@1.2.0:
+    resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==}
+
+  is-path-inside@3.0.3:
+    resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
+    engines: {node: '>=8'}
+
+  is-plain-obj@2.1.0:
+    resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==}
+    engines: {node: '>=8'}
+
+  is-stream@2.0.1:
+    resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+    engines: {node: '>=8'}
+
+  is-typedarray@1.0.0:
+    resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==}
+
+  is-unicode-supported@0.1.0:
+    resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
+    engines: {node: '>=10'}
+
+  is-windows@1.0.2:
+    resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==}
+    engines: {node: '>=0.10.0'}
+
+  isarray@1.0.0:
+    resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
+
+  isexe@2.0.0:
+    resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+  istanbul-lib-coverage@3.2.2:
+    resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
+    engines: {node: '>=8'}
+
+  istanbul-lib-hook@3.0.0:
+    resolution: {integrity: sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==}
+    engines: {node: '>=8'}
+
+  istanbul-lib-instrument@6.0.3:
+    resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==}
+    engines: {node: '>=10'}
+
+  istanbul-lib-processinfo@3.0.1:
+    resolution: {integrity: sha512-s3mX05h5wGZeScG6XnOanygPh4SJu5ujMc9YbvpnLGXWy1cRiGbp0NdVcjHxgoZt3WfQppfBsa0y+gWdYJ2pGQ==}
+    engines: {node: 20 || >=22}
+
+  istanbul-lib-report@3.0.1:
+    resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==}
+    engines: {node: '>=10'}
+
+  istanbul-lib-source-maps@4.0.1:
+    resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==}
+    engines: {node: '>=10'}
+
+  istanbul-reports@3.2.0:
+    resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==}
+    engines: {node: '>=8'}
+
+  jackspeak@3.4.3:
+    resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
+
+  js-tokens@4.0.0:
+    resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+  js-yaml@3.14.2:
+    resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==}
+    hasBin: true
+
+  js-yaml@4.3.2:
+    resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==}
+    hasBin: true
+
+  jsesc@3.1.0:
+    resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
+    engines: {node: '>=6'}
+    hasBin: true
+
+  json-buffer@3.0.1:
+    resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+
+  json-schema-traverse@0.4.1:
+    resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+
+  json-stable-stringify-without-jsonify@1.0.1:
+    resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+
+  json-stringify-safe@5.0.1:
+    resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==}
+
+  json5@2.2.3:
+    resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+    engines: {node: '>=6'}
+    hasBin: true
+
+  jsonfile@6.2.1:
+    resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==}
+
+  keyv@4.5.4:
+    resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+
+  levn@0.4.1:
+    resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
+    engines: {node: '>= 0.8.0'}
+
+  locate-path@5.0.0:
+    resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
+    engines: {node: '>=8'}
+
+  locate-path@6.0.0:
+    resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+    engines: {node: '>=10'}
+
+  lodash.flattendeep@4.4.0:
+    resolution: {integrity: sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==}
+
+  lodash.merge@4.6.2:
+    resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+
+  log-symbols@2.2.0:
+    resolution: {integrity: sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==}
+    engines: {node: '>=4'}
+
+  log-symbols@4.1.0:
+    resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
+    engines: {node: '>=10'}
+
+  lru-cache@10.4.3:
+    resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
+
+  lru-cache@11.5.2:
+    resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==}
+    engines: {node: 20 || >=22}
+
+  lru-cache@5.1.1:
+    resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+
+  make-dir@3.1.0:
+    resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
+    engines: {node: '>=8'}
+
+  make-dir@4.0.0:
+    resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
+    engines: {node: '>=10'}
+
+  math-intrinsics@1.1.0:
+    resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
+    engines: {node: '>= 0.4'}
+
+  mime-db@1.52.0:
+    resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+    engines: {node: '>= 0.6'}
+
+  mime-types@2.1.35:
+    resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+    engines: {node: '>= 0.6'}
+
+  mimic-fn@1.2.0:
+    resolution: {integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==}
+    engines: {node: '>=4'}
+
+  mimic-response@3.1.0:
+    resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
+    engines: {node: '>=10'}
+
+  minimatch@10.2.6:
+    resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==}
+    engines: {node: 18 || 20 || >=22}
+
+  minimatch@3.1.5:
+    resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==}
+
+  minimatch@9.0.9:
+    resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==}
+    engines: {node: '>=16 || 14 >=14.17'}
+
+  minimist@1.2.8:
+    resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+
+  minipass@7.1.3:
+    resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==}
+    engines: {node: '>=16 || 14 >=14.17'}
+
+  minizlib@3.1.0:
+    resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==}
+    engines: {node: '>= 18'}
+
+  mkdirp-classic@0.5.3:
+    resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
+
+  mocha@11.8.0:
+    resolution: {integrity: sha512-VyCeUdGN3A9lmCTTgG4yuvY9ixxaDk+xt2R/7/+1AP6EqNG+G9OKkzBwhVtVYoNX8YsxNSgAl8mOv3IAeOpFbw==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    hasBin: true
+
+  moment@2.30.1:
+    resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
+
+  ms@2.1.3:
+    resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+  multistream@4.1.0:
+    resolution: {integrity: sha512-J1XDiAmmNpRCBfIWJv+n0ymC4ABcf/Pl+5YvC5B/D2f/2+8PtHvCNxMPKiQcZyi922Hq69J2YOpb1pTywfifyw==}
+
+  napi-build-utils@2.0.0:
+    resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==}
+
+  natural-compare@1.4.0:
+    resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+
+  nconf@0.13.0:
+    resolution: {integrity: sha512-hJ/u2xCpA663h6xyOiztx3y+lg9eU0rdkwJ+c4FtiHo2g/gB0sjXtW31yTdMLWLOIj1gL2FcJMwfOqouuUK/Wg==}
+    engines: {node: '>= 0.4.0'}
+
+  nock@14.0.17:
+    resolution: {integrity: sha512-EjRr1weMa4ALQX35AgZTEnP+weJJjlW1KGDiNM2IQC2069YDHas4f4B4UUYR+TTLyKWxJvOz2wObDKQs/LNreA==}
+    engines: {node: '>=18.20.0 <20 || >=20.12.1'}
+
+  node-abi@3.96.0:
+    resolution: {integrity: sha512-rebQ/lz7i0EkoLzUVSrKRzA69zMkwLp95kKMWoMDkkM00Suxz0D7zEQPwRml5fQum24mj7bPvmlgLAmu2JCiYg==}
+    engines: {node: '>=10'}
+
+  node-int64@0.4.0:
+    resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
+
+  node-preload@0.2.1:
+    resolution: {integrity: sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==}
+    engines: {node: '>=8'}
+
+  node-releases@2.0.37:
+    resolution: {integrity: sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==}
+
+  nth-check@2.1.1:
+    resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
+
+  nyc@18.0.0:
+    resolution: {integrity: sha512-G5UyHinFkB1BxqGTrmZdB6uIYH0+v7ZnVssuflUDi+J+RhKWyAhRT1RCehBSI6jLFLuUUgFDyLt49mUtdO1XeQ==}
+    engines: {node: 20 || >=22}
+    hasBin: true
+
+  once@1.4.0:
+    resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
+  onetime@2.0.1:
+    resolution: {integrity: sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==}
+    engines: {node: '>=4'}
+
+  optionator@0.9.4:
+    resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
+    engines: {node: '>= 0.8.0'}
+
+  ora@3.4.0:
+    resolution: {integrity: sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==}
+    engines: {node: '>=6'}
+
+  outvariant@1.4.3:
+    resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==}
+
+  p-limit@2.3.0:
+    resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
+    engines: {node: '>=6'}
+
+  p-limit@3.1.0:
+    resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+    engines: {node: '>=10'}
+
+  p-locate@4.1.0:
+    resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
+    engines: {node: '>=8'}
+
+  p-locate@5.0.0:
+    resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+    engines: {node: '>=10'}
+
+  p-map@3.0.0:
+    resolution: {integrity: sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==}
+    engines: {node: '>=8'}
+
+  p-try@2.2.0:
+    resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
+    engines: {node: '>=6'}
+
+  package-hash@4.0.0:
+    resolution: {integrity: sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==}
+    engines: {node: '>=8'}
+
+  package-json-from-dist@1.0.1:
+    resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
+
+  parent-module@1.0.1:
+    resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+    engines: {node: '>=6'}
+
+  parse5-htmlparser2-tree-adapter@7.1.0:
+    resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==}
+
+  parse5-parser-stream@7.1.2:
+    resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==}
+
+  parse5@7.3.0:
+    resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
+
+  path-exists@4.0.0:
+    resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+    engines: {node: '>=8'}
+
+  path-key@3.1.1:
+    resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+    engines: {node: '>=8'}
+
+  path-parse@1.0.7:
+    resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+
+  path-scurry@1.11.1:
+    resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
+    engines: {node: '>=16 || 14 >=14.18'}
+
+  path-scurry@2.0.2:
+    resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==}
+    engines: {node: 18 || 20 || >=22}
+
+  picocolors@1.1.1:
+    resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+  picomatch@4.0.7:
+    resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==}
+    engines: {node: '>=12'}
+
+  pirates@4.0.7:
+    resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
+    engines: {node: '>= 6'}
+
+  pkg-dir@4.2.0:
+    resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
+    engines: {node: '>=8'}
+
+  postject@1.0.0-alpha.6:
+    resolution: {integrity: sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==}
+    engines: {node: '>=14.0.0'}
+    hasBin: true
+
+  prebuild-install@7.1.3:
+    resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==}
+    engines: {node: '>=10'}
+    deprecated: No longer maintained. Please contact the author of the relevant native addon; alternatives are available.
+    hasBin: true
+
+  prelude-ls@1.2.1:
+    resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
+    engines: {node: '>= 0.8.0'}
+
+  process-nextick-args@2.0.1:
+    resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
+
+  process-on-spawn@1.1.0:
+    resolution: {integrity: sha512-JOnOPQ/8TZgjs1JIH/m9ni7FfimjNa/PRx7y/Wb5qdItsnhO0jE4AT7fC0HjC28DUQWDr50dwSYZLdRMlqDq3Q==}
+    engines: {node: '>=8'}
+
+  progress@2.0.3:
+    resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
+    engines: {node: '>=0.4.0'}
+
+  propagate@2.0.1:
+    resolution: {integrity: sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==}
+    engines: {node: '>= 8'}
+
+  proxy-from-env@2.1.0:
+    resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==}
+    engines: {node: '>=10'}
+
+  pump@3.0.4:
+    resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==}
+
+  punycode@2.3.1:
+    resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+    engines: {node: '>=6'}
+
+  randombytes@2.1.0:
+    resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
+
+  rc@1.2.8:
+    resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
+    hasBin: true
+
+  readable-stream@2.3.8:
+    resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
+
+  readable-stream@3.6.2:
+    resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
+    engines: {node: '>= 6'}
+
+  readdirp@4.1.2:
+    resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
+    engines: {node: '>= 14.18.0'}
+
+  release-zalgo@1.0.0:
+    resolution: {integrity: sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==}
+    engines: {node: '>=4'}
+
+  require-directory@2.1.1:
+    resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+    engines: {node: '>=0.10.0'}
+
+  require-main-filename@2.0.0:
+    resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
+
+  resolve-from@4.0.0:
+    resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+    engines: {node: '>=4'}
+
+  resolve-from@5.0.0:
+    resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
+    engines: {node: '>=8'}
+
+  resolve.exports@2.0.3:
+    resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==}
+    engines: {node: '>=10'}
+
+  resolve@1.22.12:
+    resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==}
+    engines: {node: '>= 0.4'}
+    hasBin: true
+
+  restore-cursor@2.0.0:
+    resolution: {integrity: sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==}
+    engines: {node: '>=4'}
+
+  rewire@9.0.1:
+    resolution: {integrity: sha512-dnbLeTwHpXvWJjswC6CshXUUnnpE5AVhlayVRvDJhJx5ejbO4nbj1IXqN2urErgB7TpHUAMpf6iPDhQIxeSQOQ==}
+
+  rimraf@6.1.3:
+    resolution: {integrity: sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==}
+    engines: {node: 20 || >=22}
+    hasBin: true
+
+  safe-buffer@5.1.2:
+    resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
+
+  safe-buffer@5.2.1:
+    resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
+  safer-buffer@2.1.2:
+    resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+
+  secure-keys@1.0.0:
+    resolution: {integrity: sha512-nZi59hW3Sl5P3+wOO89eHBAAGwmCPd2aE1+dLZV5MO+ItQctIvAqihzaAXIQhvtH4KJPxM080HsnqltR2y8cWg==}
+
+  semver@6.3.1:
+    resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+    hasBin: true
+
+  semver@7.7.4:
+    resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==}
+    engines: {node: '>=10'}
+    hasBin: true
+
+  serialize-javascript@6.0.2:
+    resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
+
+  set-blocking@2.0.0:
+    resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
+
+  shebang-command@2.0.0:
+    resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+    engines: {node: '>=8'}
+
+  shebang-regex@3.0.0:
+    resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+    engines: {node: '>=8'}
+
+  signal-exit@3.0.7:
+    resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+
+  signal-exit@4.1.0:
+    resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+    engines: {node: '>=14'}
+
+  simple-concat@1.0.1:
+    resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==}
+
+  simple-get@4.0.1:
+    resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==}
+
+  source-map@0.6.1:
+    resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+    engines: {node: '>=0.10.0'}
+
+  spawn-wrap@3.0.0:
+    resolution: {integrity: sha512-z+s5vv4KzFPJVddGab0xX2n7kQPGMdNUX5l9T8EJqsXdKTWpcxmAqWHpsgHEXoC1taGBCc7b79bi62M5kdbrxQ==}
+    engines: {node: '>=8'}
+
+  sprintf-js@1.0.3:
+    resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
+
+  stream-meter@1.0.4:
+    resolution: {integrity: sha512-4sOEtrbgFotXwnEuzzsQBYEV1elAeFSO8rSGeTwabuX1RRn/kEq9JVH7I0MRBhKVRR0sJkr0M0QCH7yOLf9fhQ==}
+
+  streamx@2.28.1:
+    resolution: {integrity: sha512-zEzXb0s5Cds7tqMH6rhZ05lcJydCWiQPEwiNngVqzsxCc962vLY4Uw+mW7od8kDH258k2Uz/JrOkdIAAhSh9VA==}
+
+  strict-event-emitter@0.5.1:
+    resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==}
+
+  string-width@4.2.3:
+    resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+    engines: {node: '>=8'}
+
+  string-width@5.1.2:
+    resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
+    engines: {node: '>=12'}
+
+  string_decoder@1.1.1:
+    resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
+
+  string_decoder@1.3.0:
+    resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+
+  strip-ansi@5.2.0:
+    resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==}
+    engines: {node: '>=6'}
+
+  strip-ansi@6.0.1:
+    resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+    engines: {node: '>=8'}
+
+  strip-ansi@7.2.0:
+    resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==}
+    engines: {node: '>=12'}
+
+  strip-bom@4.0.0:
+    resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==}
+    engines: {node: '>=8'}
+
+  strip-json-comments@2.0.1:
+    resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
+    engines: {node: '>=0.10.0'}
+
+  strip-json-comments@3.1.1:
+    resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
+    engines: {node: '>=8'}
+
+  supports-color@5.5.0:
+    resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
+    engines: {node: '>=4'}
+
+  supports-color@7.2.0:
+    resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+    engines: {node: '>=8'}
+
+  supports-color@8.1.1:
+    resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
+    engines: {node: '>=10'}
+
+  supports-preserve-symlinks-flag@1.0.0:
+    resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+    engines: {node: '>= 0.4'}
+
+  tar-fs@2.1.5:
+    resolution: {integrity: sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==}
+
+  tar-fs@3.1.3:
+    resolution: {integrity: sha512-/hU4AXnIdZu+Gvl1pk0oI5f5HxWsCJRtY2aFaJdk9VvyL48DWU6iU5WAIPG+wIi1YvWA6eTJvIviP/tMAZZNwQ==}
+
+  tar-stream@2.2.0:
+    resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
+    engines: {node: '>=6'}
+
+  tar-stream@3.2.1:
+    resolution: {integrity: sha512-nqsEO8zLZJvrOMdEwkA0QdCLFbetHMn95Zqu4fKwX+hkaTWJPZZOrxx/PwtxoK0MMGQmBQNRW3CPs8IFYQz4cQ==}
+
+  tar@7.5.22:
+    resolution: {integrity: sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==}
+    engines: {node: '>=18'}
+
+  teex@1.0.1:
+    resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==}
+
+  test-exclude@8.0.0:
+    resolution: {integrity: sha512-ZOffsNrXYggvU1mDGHk54I96r26P8SyMjO5slMKSc7+IWmtB/MQKnEC2fP51imB3/pT6YK5cT5E8f+Dd9KdyOQ==}
+    engines: {node: 20 || >=22}
+
+  text-decoder@1.2.7:
+    resolution: {integrity: sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==}
+
+  tinyglobby@0.2.17:
+    resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
+    engines: {node: '>=12.0.0'}
+
+  tunnel-agent@0.6.0:
+    resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
+
+  type-check@0.4.0:
+    resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
+    engines: {node: '>= 0.8.0'}
+
+  type-fest@0.8.1:
+    resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==}
+    engines: {node: '>=8'}
+
+  typedarray-to-buffer@3.1.5:
+    resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==}
+
+  underscore@1.13.8:
+    resolution: {integrity: sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==}
+
+  undici@7.29.0:
+    resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==}
+    engines: {node: '>=20.18.1'}
+
+  universalify@2.0.1:
+    resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
+    engines: {node: '>= 10.0.0'}
+
+  unzipper@0.12.5:
+    resolution: {integrity: sha512-tXYOi9R57Uj/2Z25SOs5RRSzq886MBQj2gY8dPL+xl/kv6s6SvByoKfAtvfVeEuhntWDgjd2o9p2lb4TVPAz0A==}
+
+  update-browserslist-db@1.2.3:
+    resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
+    hasBin: true
+    peerDependencies:
+      browserslist: '>= 4.21.0'
+
+  uri-js@4.4.1:
+    resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+
+  util-deprecate@1.0.2:
+    resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+
+  wcwidth@1.0.1:
+    resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
+
+  whatwg-encoding@3.1.1:
+    resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==}
+    engines: {node: '>=18'}
+    deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation
+
+  whatwg-mimetype@4.0.0:
+    resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==}
+    engines: {node: '>=18'}
+
+  which-module@2.0.1:
+    resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
+
+  which@2.0.2:
+    resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+    engines: {node: '>= 8'}
+    hasBin: true
+
+  word-wrap@1.2.5:
+    resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
+    engines: {node: '>=0.10.0'}
+
+  workerpool@9.3.4:
+    resolution: {integrity: sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==}
+
+  wrap-ansi@6.2.0:
+    resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
+    engines: {node: '>=8'}
+
+  wrap-ansi@7.0.0:
+    resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+    engines: {node: '>=10'}
+
+  wrap-ansi@8.1.0:
+    resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
+    engines: {node: '>=12'}
+
+  wrappy@1.0.2:
+    resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
+  write-file-atomic@3.0.3:
+    resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==}
+
+  y18n@4.0.3:
+    resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
+
+  y18n@5.0.8:
+    resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+    engines: {node: '>=10'}
+
+  yallist@3.1.1:
+    resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+
+  yallist@5.0.0:
+    resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
+    engines: {node: '>=18'}
+
+  yargs-parser@18.1.3:
+    resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
+    engines: {node: '>=6'}
+
+  yargs-parser@20.2.4:
+    resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==}
+    engines: {node: '>=10'}
+
+  yargs-parser@21.1.1:
+    resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+    engines: {node: '>=12'}
+
+  yargs-unparser@2.0.0:
+    resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==}
+    engines: {node: '>=10'}
+
+  yargs@15.4.1:
+    resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
+    engines: {node: '>=8'}
+
+  yargs@16.2.0:
+    resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
+    engines: {node: '>=10'}
+
+  yargs@17.7.2:
+    resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
+    engines: {node: '>=12'}
+
+  yocto-queue@0.1.0:
+    resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+    engines: {node: '>=10'}
+
+snapshots:
+
+  '@babel/code-frame@7.29.0':
+    dependencies:
+      '@babel/helper-validator-identifier': 7.28.5
+      js-tokens: 4.0.0
+      picocolors: 1.1.1
+
+  '@babel/compat-data@7.29.0': {}
+
+  '@babel/core@7.29.0(supports-color@5.5.0)':
+    dependencies:
+      '@babel/code-frame': 7.29.0
+      '@babel/generator': 7.29.1
+      '@babel/helper-compilation-targets': 7.28.6
+      '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0(supports-color@5.5.0))(supports-color@5.5.0)
+      '@babel/helpers': 7.29.2
+      '@babel/parser': 7.29.2
+      '@babel/template': 7.28.6
+      '@babel/traverse': 7.29.0(supports-color@5.5.0)
+      '@babel/types': 7.29.0
+      '@jridgewell/remapping': 2.3.5
+      convert-source-map: 2.0.0
+      debug: 4.4.3(supports-color@5.5.0)
+      gensync: 1.0.0-beta.2
+      json5: 2.2.3
+      semver: 6.3.1
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/generator@7.29.1':
+    dependencies:
+      '@babel/parser': 7.29.2
+      '@babel/types': 7.29.0
+      '@jridgewell/gen-mapping': 0.3.13
+      '@jridgewell/trace-mapping': 0.3.31
+      jsesc: 3.1.0
+
+  '@babel/helper-compilation-targets@7.28.6':
+    dependencies:
+      '@babel/compat-data': 7.29.0
+      '@babel/helper-validator-option': 7.27.1
+      browserslist: 4.28.2
+      lru-cache: 5.1.1
+      semver: 6.3.1
+
+  '@babel/helper-globals@7.28.0': {}
+
+  '@babel/helper-module-imports@7.28.6(supports-color@5.5.0)':
+    dependencies:
+      '@babel/traverse': 7.29.0(supports-color@5.5.0)
+      '@babel/types': 7.29.0
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0(supports-color@5.5.0))(supports-color@5.5.0)':
+    dependencies:
+      '@babel/core': 7.29.0(supports-color@5.5.0)
+      '@babel/helper-module-imports': 7.28.6(supports-color@5.5.0)
+      '@babel/helper-validator-identifier': 7.28.5
+      '@babel/traverse': 7.29.0(supports-color@5.5.0)
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/helper-string-parser@7.27.1': {}
+
+  '@babel/helper-validator-identifier@7.28.5': {}
+
+  '@babel/helper-validator-option@7.27.1': {}
+
+  '@babel/helpers@7.29.2':
+    dependencies:
+      '@babel/template': 7.28.6
+      '@babel/types': 7.29.0
+
+  '@babel/parser@7.29.2':
+    dependencies:
+      '@babel/types': 7.29.0
+
+  '@babel/template@7.28.6':
+    dependencies:
+      '@babel/code-frame': 7.29.0
+      '@babel/parser': 7.29.2
+      '@babel/types': 7.29.0
+
+  '@babel/traverse@7.29.0(supports-color@5.5.0)':
+    dependencies:
+      '@babel/code-frame': 7.29.0
+      '@babel/generator': 7.29.1
+      '@babel/helper-globals': 7.28.0
+      '@babel/parser': 7.29.2
+      '@babel/template': 7.28.6
+      '@babel/types': 7.29.0
+      debug: 4.4.3(supports-color@5.5.0)
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/types@7.29.0':
+    dependencies:
+      '@babel/helper-string-parser': 7.27.1
+      '@babel/helper-validator-identifier': 7.28.5
+
+  '@esbuild/aix-ppc64@0.28.2':
+    optional: true
+
+  '@esbuild/android-arm64@0.28.2':
+    optional: true
+
+  '@esbuild/android-arm@0.28.2':
+    optional: true
+
+  '@esbuild/android-x64@0.28.2':
+    optional: true
+
+  '@esbuild/darwin-arm64@0.28.2':
+    optional: true
+
+  '@esbuild/darwin-x64@0.28.2':
+    optional: true
+
+  '@esbuild/freebsd-arm64@0.28.2':
+    optional: true
+
+  '@esbuild/freebsd-x64@0.28.2':
+    optional: true
+
+  '@esbuild/linux-arm64@0.28.2':
+    optional: true
+
+  '@esbuild/linux-arm@0.28.2':
+    optional: true
+
+  '@esbuild/linux-ia32@0.28.2':
+    optional: true
+
+  '@esbuild/linux-loong64@0.28.2':
+    optional: true
+
+  '@esbuild/linux-mips64el@0.28.2':
+    optional: true
+
+  '@esbuild/linux-ppc64@0.28.2':
+    optional: true
+
+  '@esbuild/linux-riscv64@0.28.2':
+    optional: true
+
+  '@esbuild/linux-s390x@0.28.2':
+    optional: true
+
+  '@esbuild/linux-x64@0.28.2':
+    optional: true
+
+  '@esbuild/netbsd-arm64@0.28.2':
+    optional: true
+
+  '@esbuild/netbsd-x64@0.28.2':
+    optional: true
+
+  '@esbuild/openbsd-arm64@0.28.2':
+    optional: true
+
+  '@esbuild/openbsd-x64@0.28.2':
+    optional: true
+
+  '@esbuild/openharmony-arm64@0.28.2':
+    optional: true
+
+  '@esbuild/sunos-x64@0.28.2':
+    optional: true
+
+  '@esbuild/win32-arm64@0.28.2':
+    optional: true
+
+  '@esbuild/win32-ia32@0.28.2':
+    optional: true
+
+  '@esbuild/win32-x64@0.28.2':
+    optional: true
+
+  '@eslint-community/eslint-utils@4.10.1(eslint@10.9.1(supports-color@5.5.0))':
+    dependencies:
+      eslint: 10.9.1(supports-color@5.5.0)
+      eslint-visitor-keys: 3.4.3
+
+  '@eslint-community/eslint-utils@4.10.1(eslint@9.39.5(supports-color@5.5.0))':
+    dependencies:
+      eslint: 9.39.5(supports-color@5.5.0)
+      eslint-visitor-keys: 3.4.3
+
+  '@eslint-community/regexpp@4.12.2': {}
+
+  '@eslint/config-array@0.21.2(supports-color@5.5.0)':
+    dependencies:
+      '@eslint/object-schema': 2.1.7
+      debug: 4.4.3(supports-color@5.5.0)
+      minimatch: 3.1.5
+    transitivePeerDependencies:
+      - supports-color
+
+  '@eslint/config-array@0.23.5(supports-color@5.5.0)':
+    dependencies:
+      '@eslint/object-schema': 3.0.5
+      debug: 4.4.3(supports-color@5.5.0)
+      minimatch: 10.2.6
+    transitivePeerDependencies:
+      - supports-color
+
+  '@eslint/config-helpers@0.4.2':
+    dependencies:
+      '@eslint/core': 0.17.0
+
+  '@eslint/config-helpers@0.7.0':
+    dependencies:
+      '@eslint/core': 1.2.1
+
+  '@eslint/core@0.17.0':
+    dependencies:
+      '@types/json-schema': 7.0.15
+
+  '@eslint/core@1.2.1':
+    dependencies:
+      '@types/json-schema': 7.0.15
+
+  '@eslint/eslintrc@3.3.6(supports-color@5.5.0)':
+    dependencies:
+      ajv: 6.14.0
+      debug: 4.4.3(supports-color@5.5.0)
+      espree: 10.4.0
+      globals: 14.0.0
+      ignore: 5.3.2
+      import-fresh: 3.3.1
+      js-yaml: 4.3.2
+      minimatch: 3.1.5
+      strip-json-comments: 3.1.1
+    transitivePeerDependencies:
+      - supports-color
+
+  '@eslint/js@10.0.1(eslint@10.9.1(supports-color@5.5.0))':
+    optionalDependencies:
+      eslint: 10.9.1(supports-color@5.5.0)
+
+  '@eslint/js@9.39.5': {}
+
+  '@eslint/object-schema@2.1.7': {}
+
+  '@eslint/object-schema@3.0.5': {}
+
+  '@eslint/plugin-kit@0.4.1':
+    dependencies:
+      '@eslint/core': 0.17.0
+      levn: 0.4.1
+
+  '@eslint/plugin-kit@0.7.2':
+    dependencies:
+      '@eslint/core': 1.2.1
+      levn: 0.4.1
+
+  '@humanfs/core@0.19.2':
+    dependencies:
+      '@humanfs/types': 0.15.0
+
+  '@humanfs/node@0.16.8':
+    dependencies:
+      '@humanfs/core': 0.19.2
+      '@humanfs/types': 0.15.0
+      '@humanwhocodes/retry': 0.4.3
+
+  '@humanfs/types@0.15.0': {}
+
+  '@humanwhocodes/module-importer@1.0.1': {}
+
+  '@humanwhocodes/retry@0.4.3': {}
+
+  '@isaacs/cliui@8.0.2':
+    dependencies:
+      string-width: 5.1.2
+      string-width-cjs: string-width@4.2.3
+      strip-ansi: 7.2.0
+      strip-ansi-cjs: strip-ansi@6.0.1
+      wrap-ansi: 8.1.0
+      wrap-ansi-cjs: wrap-ansi@7.0.0
+
+  '@isaacs/fs-minipass@4.0.1':
+    dependencies:
+      minipass: 7.1.3
+
+  '@istanbuljs/load-nyc-config@1.1.0':
+    dependencies:
+      camelcase: 5.3.1
+      find-up: 4.1.0
+      get-package-type: 0.1.0
+      js-yaml: 3.14.2
+      resolve-from: 5.0.0
+
+  '@istanbuljs/schema@0.1.3': {}
+
+  '@jridgewell/gen-mapping@0.3.13':
+    dependencies:
+      '@jridgewell/sourcemap-codec': 1.5.5
+      '@jridgewell/trace-mapping': 0.3.31
+
+  '@jridgewell/remapping@2.3.5':
+    dependencies:
+      '@jridgewell/gen-mapping': 0.3.13
+      '@jridgewell/trace-mapping': 0.3.31
+
+  '@jridgewell/resolve-uri@3.1.2': {}
+
+  '@jridgewell/sourcemap-codec@1.5.5': {}
+
+  '@jridgewell/trace-mapping@0.3.31':
+    dependencies:
+      '@jridgewell/resolve-uri': 3.1.2
+      '@jridgewell/sourcemap-codec': 1.5.5
+
+  '@mswjs/interceptors@0.41.9':
+    dependencies:
+      '@open-draft/deferred-promise': 2.2.0
+      '@open-draft/logger': 0.3.0
+      '@open-draft/until': 2.1.0
+      is-node-process: 1.2.0
+      outvariant: 1.4.3
+      strict-event-emitter: 0.5.1
+
+  '@open-draft/deferred-promise@2.2.0': {}
+
+  '@open-draft/logger@0.3.0':
+    dependencies:
+      is-node-process: 1.2.0
+      outvariant: 1.4.3
+
+  '@open-draft/until@2.1.0': {}
+
+  '@pkgjs/parseargs@0.11.0':
+    optional: true
+
+  '@roberts_lando/vfs@0.3.3': {}
+
+  '@types/esrecurse@4.3.1': {}
+
+  '@types/estree@1.0.9': {}
+
+  '@types/json-schema@7.0.15': {}
+
+  '@yao-pkg/pkg-fetch@3.6.5':
+    dependencies:
+      picocolors: 1.1.1
+      progress: 2.0.3
+      semver: 7.7.4
+      tar-fs: 3.1.3
+      undici: 7.29.0
+      yargs: 16.2.0
+    transitivePeerDependencies:
+      - bare-abort-controller
+      - bare-buffer
+      - react-native-b4a
+
+  '@yao-pkg/pkg@6.22.0(supports-color@5.5.0)':
+    dependencies:
+      '@babel/generator': 7.29.1
+      '@babel/parser': 7.29.2
+      '@babel/traverse': 7.29.0(supports-color@5.5.0)
+      '@babel/types': 7.29.0
+      '@roberts_lando/vfs': 0.3.3
+      '@yao-pkg/pkg-fetch': 3.6.5
+      esbuild: 0.28.2
+      into-stream: 9.1.0
+      multistream: 4.1.0
+      picocolors: 1.1.1
+      picomatch: 4.0.7
+      postject: 1.0.0-alpha.6
+      prebuild-install: 7.1.3
+      resolve: 1.22.12
+      resolve.exports: 2.0.3
+      stream-meter: 1.0.4
+      tar: 7.5.22
+      tinyglobby: 0.2.17
+      unzipper: 0.12.5
+    transitivePeerDependencies:
+      - bare-abort-controller
+      - bare-buffer
+      - react-native-b4a
+      - supports-color
+
+  acorn-jsx@5.3.2(acorn@8.18.0):
+    dependencies:
+      acorn: 8.18.0
+
+  acorn@8.18.0: {}
+
+  agent-base@6.0.2(supports-color@5.5.0):
+    dependencies:
+      debug: 4.4.3(supports-color@5.5.0)
+    transitivePeerDependencies:
+      - supports-color
+
+  aggregate-error@3.1.0:
+    dependencies:
+      clean-stack: 2.2.0
+      indent-string: 4.0.0
+
+  ajv@6.14.0:
+    dependencies:
+      fast-deep-equal: 3.1.3
+      fast-json-stable-stringify: 2.1.0
+      json-schema-traverse: 0.4.1
+      uri-js: 4.4.1
+
+  ansi-regex@4.1.1: {}
+
+  ansi-regex@5.0.1: {}
+
+  ansi-regex@6.3.0: {}
+
+  ansi-styles@3.2.1:
+    dependencies:
+      color-convert: 1.9.3
+
+  ansi-styles@4.3.0:
+    dependencies:
+      color-convert: 2.0.1
+
+  ansi-styles@6.2.3: {}
+
+  append-transform@2.0.0:
+    dependencies:
+      default-require-extensions: 3.0.1
+
+  archy@1.0.0: {}
+
+  argparse@1.0.10:
+    dependencies:
+      sprintf-js: 1.0.3
+
+  argparse@2.0.1: {}
+
+  async@3.2.6: {}
+
+  asynckit@0.4.0: {}
+
+  axios@1.20.0(supports-color@5.5.0):
+    dependencies:
+      follow-redirects: 1.16.0
+      form-data: 4.0.6
+      https-proxy-agent: 5.0.1(supports-color@5.5.0)
+      proxy-from-env: 2.1.0
+    transitivePeerDependencies:
+      - debug
+      - supports-color
+
+  b4a@1.8.1: {}
+
+  balanced-match@1.0.2: {}
+
+  balanced-match@4.0.4: {}
+
+  bare-events@2.9.2: {}
+
+  bare-fs@4.8.1:
+    dependencies:
+      bare-events: 2.9.2
+      bare-path: 3.1.1
+      bare-stream: 2.13.4(bare-events@2.9.2)
+      bare-url: 2.5.2
+      fast-fifo: 1.3.2
+    transitivePeerDependencies:
+      - bare-abort-controller
+      - react-native-b4a
+
+  bare-path@3.1.1: {}
+
+  bare-stream@2.13.4(bare-events@2.9.2):
+    dependencies:
+      b4a: 1.8.1
+      streamx: 2.28.1
+      teex: 1.0.1
+    optionalDependencies:
+      bare-events: 2.9.2
+    transitivePeerDependencies:
+      - react-native-b4a
+
+  bare-url@2.5.2:
+    dependencies:
+      bare-path: 3.1.1
+
+  base64-js@1.5.1: {}
+
+  baseline-browser-mapping@2.10.16: {}
+
+  bl@4.1.0:
+    dependencies:
+      buffer: 5.7.1
+      inherits: 2.0.4
+      readable-stream: 3.6.2
+
+  bluebird@3.7.2: {}
+
+  boolbase@1.0.0: {}
+
+  brace-expansion@1.1.13:
+    dependencies:
+      balanced-match: 1.0.2
+      concat-map: 0.0.1
+
+  brace-expansion@2.1.4:
+    dependencies:
+      balanced-match: 1.0.2
+
+  brace-expansion@5.0.9:
+    dependencies:
+      balanced-match: 4.0.4
+
+  browser-stdout@1.3.1: {}
+
+  browserslist@4.28.2:
+    dependencies:
+      baseline-browser-mapping: 2.10.16
+      caniuse-lite: 1.0.30001787
+      electron-to-chromium: 1.5.334
+      node-releases: 2.0.37
+      update-browserslist-db: 1.2.3(browserslist@4.28.2)
+
+  buffer@5.7.1:
+    dependencies:
+      base64-js: 1.5.1
+      ieee754: 1.2.1
+
+  caching-transform@4.0.0:
+    dependencies:
+      hasha: 5.2.2
+      make-dir: 3.1.0
+      package-hash: 4.0.0
+      write-file-atomic: 3.0.3
+
+  call-bind-apply-helpers@1.0.2:
+    dependencies:
+      es-errors: 1.3.0
+      function-bind: 1.1.2
+
+  callsites@3.1.0: {}
+
+  camelcase@5.3.1: {}
+
+  camelcase@6.3.0: {}
+
+  caniuse-lite@1.0.30001787: {}
+
+  chai@6.2.2: {}
+
+  chalk@2.4.2:
+    dependencies:
+      ansi-styles: 3.2.1
+      escape-string-regexp: 1.0.5
+      supports-color: 5.5.0
+
+  chalk@4.1.2:
+    dependencies:
+      ansi-styles: 4.3.0
+      supports-color: 7.2.0
+
+  cheerio-select@2.1.0:
+    dependencies:
+      boolbase: 1.0.0
+      css-select: 5.2.2
+      css-what: 6.2.2
+      domelementtype: 2.3.0
+      domhandler: 5.0.3
+      domutils: 3.2.2
+
+  cheerio@1.2.0:
+    dependencies:
+      cheerio-select: 2.1.0
+      dom-serializer: 2.0.0
+      domhandler: 5.0.3
+      domutils: 3.2.2
+      encoding-sniffer: 0.2.1
+      htmlparser2: 10.1.0
+      parse5: 7.3.0
+      parse5-htmlparser2-tree-adapter: 7.1.0
+      parse5-parser-stream: 7.1.2
+      undici: 7.29.0
+      whatwg-mimetype: 4.0.0
+
+  chokidar@4.0.3:
+    dependencies:
+      readdirp: 4.1.2
+
+  chownr@1.1.4: {}
+
+  chownr@3.0.0: {}
+
+  clean-stack@2.2.0: {}
+
+  cli-cursor@2.1.0:
+    dependencies:
+      restore-cursor: 2.0.0
+
+  cli-spinners@2.9.2: {}
+
+  cliui@6.0.0:
+    dependencies:
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+      wrap-ansi: 6.2.0
+
+  cliui@7.0.4:
+    dependencies:
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+      wrap-ansi: 7.0.0
+
+  cliui@8.0.1:
+    dependencies:
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+      wrap-ansi: 7.0.0
+
+  clone@1.0.4: {}
+
+  color-convert@1.9.3:
+    dependencies:
+      color-name: 1.1.3
+
+  color-convert@2.0.1:
+    dependencies:
+      color-name: 1.1.4
+
+  color-name@1.1.3: {}
+
+  color-name@1.1.4: {}
+
+  combined-stream@1.0.8:
+    dependencies:
+      delayed-stream: 1.0.0
+
+  commander@9.5.0: {}
+
+  commondir@1.0.1: {}
+
+  concat-map@0.0.1: {}
+
+  convert-source-map@1.9.0: {}
+
+  convert-source-map@2.0.0: {}
+
+  core-util-is@1.0.3: {}
+
+  cross-spawn@7.0.6:
+    dependencies:
+      path-key: 3.1.1
+      shebang-command: 2.0.0
+      which: 2.0.2
+
+  css-select@5.2.2:
+    dependencies:
+      boolbase: 1.0.0
+      css-what: 6.2.2
+      domhandler: 5.0.3
+      domutils: 3.2.2
+      nth-check: 2.1.1
+
+  css-what@6.2.2: {}
+
+  debug@4.4.3(supports-color@5.5.0):
+    dependencies:
+      ms: 2.1.3
+    optionalDependencies:
+      supports-color: 5.5.0
+
+  debug@4.4.3(supports-color@8.1.1):
+    dependencies:
+      ms: 2.1.3
+    optionalDependencies:
+      supports-color: 8.1.1
+
+  decamelize@1.2.0: {}
+
+  decamelize@4.0.0: {}
+
+  decompress-response@6.0.0:
+    dependencies:
+      mimic-response: 3.1.0
+
+  deep-extend@0.6.0: {}
+
+  deep-is@0.1.4: {}
+
+  default-require-extensions@3.0.1:
+    dependencies:
+      strip-bom: 4.0.0
+
+  defaults@1.0.4:
+    dependencies:
+      clone: 1.0.4
+
+  delayed-stream@1.0.0: {}
+
+  detect-libc@2.1.2: {}
+
+  diff@7.0.0: {}
+
+  dom-serializer@2.0.0:
+    dependencies:
+      domelementtype: 2.3.0
+      domhandler: 5.0.3
+      entities: 4.5.0
+
+  domelementtype@2.3.0: {}
+
+  domhandler@5.0.3:
+    dependencies:
+      domelementtype: 2.3.0
+
+  domutils@3.2.2:
+    dependencies:
+      dom-serializer: 2.0.0
+      domelementtype: 2.3.0
+      domhandler: 5.0.3
+
+  dunder-proto@1.0.1:
+    dependencies:
+      call-bind-apply-helpers: 1.0.2
+      es-errors: 1.3.0
+      gopd: 1.2.0
+
+  duplexer2@0.1.4:
+    dependencies:
+      readable-stream: 2.3.8
+
+  eastasianwidth@0.2.0: {}
+
+  electron-to-chromium@1.5.334: {}
+
+  emoji-regex@8.0.0: {}
+
+  emoji-regex@9.2.2: {}
+
+  encoding-sniffer@0.2.1:
+    dependencies:
+      iconv-lite: 0.6.3
+      whatwg-encoding: 3.1.1
+
+  end-of-stream@1.4.5:
+    dependencies:
+      once: 1.4.0
+
+  entities@4.5.0: {}
+
+  entities@6.0.1: {}
+
+  entities@7.0.1: {}
+
+  es-define-property@1.0.1: {}
+
+  es-errors@1.3.0: {}
+
+  es-object-atoms@1.1.2:
+    dependencies:
+      es-errors: 1.3.0
+
+  es-set-tostringtag@2.1.0:
+    dependencies:
+      es-errors: 1.3.0
+      get-intrinsic: 1.3.0
+      has-tostringtag: 1.0.2
+      hasown: 2.0.4
+
+  es6-error@4.1.1: {}
+
+  esbuild@0.28.2:
+    optionalDependencies:
+      '@esbuild/aix-ppc64': 0.28.2
+      '@esbuild/android-arm': 0.28.2
+      '@esbuild/android-arm64': 0.28.2
+      '@esbuild/android-x64': 0.28.2
+      '@esbuild/darwin-arm64': 0.28.2
+      '@esbuild/darwin-x64': 0.28.2
+      '@esbuild/freebsd-arm64': 0.28.2
+      '@esbuild/freebsd-x64': 0.28.2
+      '@esbuild/linux-arm': 0.28.2
+      '@esbuild/linux-arm64': 0.28.2
+      '@esbuild/linux-ia32': 0.28.2
+      '@esbuild/linux-loong64': 0.28.2
+      '@esbuild/linux-mips64el': 0.28.2
+      '@esbuild/linux-ppc64': 0.28.2
+      '@esbuild/linux-riscv64': 0.28.2
+      '@esbuild/linux-s390x': 0.28.2
+      '@esbuild/linux-x64': 0.28.2
+      '@esbuild/netbsd-arm64': 0.28.2
+      '@esbuild/netbsd-x64': 0.28.2
+      '@esbuild/openbsd-arm64': 0.28.2
+      '@esbuild/openbsd-x64': 0.28.2
+      '@esbuild/openharmony-arm64': 0.28.2
+      '@esbuild/sunos-x64': 0.28.2
+      '@esbuild/win32-arm64': 0.28.2
+      '@esbuild/win32-ia32': 0.28.2
+      '@esbuild/win32-x64': 0.28.2
+
+  escalade@3.2.0: {}
+
+  escape-string-regexp@1.0.5: {}
+
+  escape-string-regexp@4.0.0: {}
+
+  eslint-scope@8.4.0:
+    dependencies:
+      esrecurse: 4.3.0
+      estraverse: 5.3.0
+
+  eslint-scope@9.1.2:
+    dependencies:
+      '@types/esrecurse': 4.3.1
+      '@types/estree': 1.0.9
+      esrecurse: 4.3.0
+      estraverse: 5.3.0
+
+  eslint-visitor-keys@3.4.3: {}
+
+  eslint-visitor-keys@4.2.1: {}
+
+  eslint-visitor-keys@5.0.1: {}
+
+  eslint@10.9.1(supports-color@5.5.0):
+    dependencies:
+      '@eslint-community/eslint-utils': 4.10.1(eslint@10.9.1(supports-color@5.5.0))
+      '@eslint-community/regexpp': 4.12.2
+      '@eslint/config-array': 0.23.5(supports-color@5.5.0)
+      '@eslint/config-helpers': 0.7.0
+      '@eslint/core': 1.2.1
+      '@eslint/plugin-kit': 0.7.2
+      '@humanfs/node': 0.16.8
+      '@humanwhocodes/module-importer': 1.0.1
+      '@humanwhocodes/retry': 0.4.3
+      '@types/estree': 1.0.9
+      ajv: 6.14.0
+      cross-spawn: 7.0.6
+      debug: 4.4.3(supports-color@5.5.0)
+      escape-string-regexp: 4.0.0
+      eslint-scope: 9.1.2
+      eslint-visitor-keys: 5.0.1
+      espree: 11.2.0
+      esquery: 1.7.0
+      esutils: 2.0.3
+      fast-deep-equal: 3.1.3
+      file-entry-cache: 8.0.0
+      find-up: 5.0.0
+      glob-parent: 6.0.2
+      ignore: 5.3.2
+      imurmurhash: 0.1.4
+      is-glob: 4.0.3
+      json-stable-stringify-without-jsonify: 1.0.1
+      minimatch: 10.2.6
+      natural-compare: 1.4.0
+      optionator: 0.9.4
+    transitivePeerDependencies:
+      - supports-color
+
+  eslint@9.39.5(supports-color@5.5.0):
+    dependencies:
+      '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(supports-color@5.5.0))
+      '@eslint-community/regexpp': 4.12.2
+      '@eslint/config-array': 0.21.2(supports-color@5.5.0)
+      '@eslint/config-helpers': 0.4.2
+      '@eslint/core': 0.17.0
+      '@eslint/eslintrc': 3.3.6(supports-color@5.5.0)
+      '@eslint/js': 9.39.5
+      '@eslint/plugin-kit': 0.4.1
+      '@humanfs/node': 0.16.8
+      '@humanwhocodes/module-importer': 1.0.1
+      '@humanwhocodes/retry': 0.4.3
+      '@types/estree': 1.0.9
+      ajv: 6.14.0
+      chalk: 4.1.2
+      cross-spawn: 7.0.6
+      debug: 4.4.3(supports-color@5.5.0)
+      escape-string-regexp: 4.0.0
+      eslint-scope: 8.4.0
+      eslint-visitor-keys: 4.2.1
+      espree: 10.4.0
+      esquery: 1.7.0
+      esutils: 2.0.3
+      fast-deep-equal: 3.1.3
+      file-entry-cache: 8.0.0
+      find-up: 5.0.0
+      glob-parent: 6.0.2
+      ignore: 5.3.2
+      imurmurhash: 0.1.4
+      is-glob: 4.0.3
+      json-stable-stringify-without-jsonify: 1.0.1
+      lodash.merge: 4.6.2
+      minimatch: 3.1.5
+      natural-compare: 1.4.0
+      optionator: 0.9.4
+    transitivePeerDependencies:
+      - supports-color
+
+  espree@10.4.0:
+    dependencies:
+      acorn: 8.18.0
+      acorn-jsx: 5.3.2(acorn@8.18.0)
+      eslint-visitor-keys: 4.2.1
+
+  espree@11.2.0:
+    dependencies:
+      acorn: 8.18.0
+      acorn-jsx: 5.3.2(acorn@8.18.0)
+      eslint-visitor-keys: 5.0.1
+
+  esprima@4.0.1: {}
+
+  esquery@1.7.0:
+    dependencies:
+      estraverse: 5.3.0
+
+  esrecurse@4.3.0:
+    dependencies:
+      estraverse: 5.3.0
+
+  estraverse@5.3.0: {}
+
+  esutils@2.0.3: {}
+
+  events-universal@1.0.1:
+    dependencies:
+      bare-events: 2.9.2
+    transitivePeerDependencies:
+      - bare-abort-controller
+
+  expand-template@2.0.3: {}
+
+  fast-deep-equal@3.1.3: {}
+
+  fast-fifo@1.3.2: {}
+
+  fast-json-stable-stringify@2.1.0: {}
+
+  fast-levenshtein@2.0.6: {}
+
+  fdir@6.5.0(picomatch@4.0.7):
+    optionalDependencies:
+      picomatch: 4.0.7
+
+  file-entry-cache@8.0.0:
+    dependencies:
+      flat-cache: 4.0.1
+
+  find-cache-dir@3.3.2:
+    dependencies:
+      commondir: 1.0.1
+      make-dir: 3.1.0
+      pkg-dir: 4.2.0
+
+  find-up@4.1.0:
+    dependencies:
+      locate-path: 5.0.0
+      path-exists: 4.0.0
+
+  find-up@5.0.0:
+    dependencies:
+      locate-path: 6.0.0
+      path-exists: 4.0.0
+
+  flat-cache@4.0.1:
+    dependencies:
+      flatted: 3.4.4
+      keyv: 4.5.4
+
+  flat@5.0.2: {}
+
+  flatted@3.4.4: {}
+
+  follow-redirects@1.16.0: {}
+
+  foreground-child@2.0.0:
+    dependencies:
+      cross-spawn: 7.0.6
+      signal-exit: 3.0.7
+
+  foreground-child@3.3.1:
+    dependencies:
+      cross-spawn: 7.0.6
+      signal-exit: 4.1.0
+
+  form-data@4.0.6:
+    dependencies:
+      asynckit: 0.4.0
+      combined-stream: 1.0.8
+      es-set-tostringtag: 2.1.0
+      hasown: 2.0.4
+      mime-types: 2.1.35
+
+  fromentries@1.3.2: {}
+
+  fs-constants@1.0.0: {}
+
+  fs-extra@11.3.1:
+    dependencies:
+      graceful-fs: 4.2.11
+      jsonfile: 6.2.1
+      universalify: 2.0.1
+
+  function-bind@1.1.2: {}
+
+  gensync@1.0.0-beta.2: {}
+
+  get-caller-file@2.0.5: {}
+
+  get-intrinsic@1.3.0:
+    dependencies:
+      call-bind-apply-helpers: 1.0.2
+      es-define-property: 1.0.1
+      es-errors: 1.3.0
+      es-object-atoms: 1.1.2
+      function-bind: 1.1.2
+      get-proto: 1.0.1
+      gopd: 1.2.0
+      has-symbols: 1.1.0
+      hasown: 2.0.4
+      math-intrinsics: 1.1.0
+
+  get-package-type@0.1.0: {}
+
+  get-proto@1.0.1:
+    dependencies:
+      dunder-proto: 1.0.1
+      es-object-atoms: 1.1.2
+
+  github-from-package@0.0.0: {}
+
+  glob-parent@6.0.2:
+    dependencies:
+      is-glob: 4.0.3
+
+  glob@10.5.0:
+    dependencies:
+      foreground-child: 3.3.1
+      jackspeak: 3.4.3
+      minimatch: 9.0.9
+      minipass: 7.1.3
+      package-json-from-dist: 1.0.1
+      path-scurry: 1.11.1
+
+  glob@13.0.6:
+    dependencies:
+      minimatch: 10.2.6
+      minipass: 7.1.3
+      path-scurry: 2.0.2
+
+  globals@14.0.0: {}
+
+  gopd@1.2.0: {}
+
+  graceful-fs@4.2.11: {}
+
+  has-flag@3.0.0: {}
+
+  has-flag@4.0.0: {}
+
+  has-symbols@1.1.0: {}
+
+  has-tostringtag@1.0.2:
+    dependencies:
+      has-symbols: 1.1.0
+
+  hasha@5.2.2:
+    dependencies:
+      is-stream: 2.0.1
+      type-fest: 0.8.1
+
+  hasown@2.0.4:
+    dependencies:
+      function-bind: 1.1.2
+
+  he@1.2.0: {}
+
+  html-escaper@2.0.2: {}
+
+  htmlparser2@10.1.0:
+    dependencies:
+      domelementtype: 2.3.0
+      domhandler: 5.0.3
+      domutils: 3.2.2
+      entities: 7.0.1
+
+  https-proxy-agent@5.0.1(supports-color@5.5.0):
+    dependencies:
+      agent-base: 6.0.2(supports-color@5.5.0)
+      debug: 4.4.3(supports-color@5.5.0)
+    transitivePeerDependencies:
+      - supports-color
+
+  iconv-lite@0.6.3:
+    dependencies:
+      safer-buffer: 2.1.2
+
+  ieee754@1.2.1: {}
+
+  ignore@5.3.2: {}
+
+  import-fresh@3.3.1:
+    dependencies:
+      parent-module: 1.0.1
+      resolve-from: 4.0.0
+
+  imurmurhash@0.1.4: {}
+
+  indent-string@4.0.0: {}
+
+  inherits@2.0.4: {}
+
+  ini@1.3.8: {}
+
+  ini@2.0.0: {}
+
+  into-stream@9.1.0: {}
+
+  is-core-module@2.16.2:
+    dependencies:
+      hasown: 2.0.4
+
+  is-extglob@2.1.1: {}
+
+  is-fullwidth-code-point@3.0.0: {}
+
+  is-glob@4.0.3:
+    dependencies:
+      is-extglob: 2.1.1
+
+  is-node-process@1.2.0: {}
+
+  is-path-inside@3.0.3: {}
+
+  is-plain-obj@2.1.0: {}
+
+  is-stream@2.0.1: {}
+
+  is-typedarray@1.0.0: {}
+
+  is-unicode-supported@0.1.0: {}
+
+  is-windows@1.0.2: {}
+
+  isarray@1.0.0: {}
+
+  isexe@2.0.0: {}
+
+  istanbul-lib-coverage@3.2.2: {}
+
+  istanbul-lib-hook@3.0.0:
+    dependencies:
+      append-transform: 2.0.0
+
+  istanbul-lib-instrument@6.0.3(supports-color@5.5.0):
+    dependencies:
+      '@babel/core': 7.29.0(supports-color@5.5.0)
+      '@babel/parser': 7.29.2
+      '@istanbuljs/schema': 0.1.3
+      istanbul-lib-coverage: 3.2.2
+      semver: 7.7.4
+    transitivePeerDependencies:
+      - supports-color
+
+  istanbul-lib-processinfo@3.0.1:
+    dependencies:
+      archy: 1.0.0
+      cross-spawn: 7.0.6
+      istanbul-lib-coverage: 3.2.2
+      p-map: 3.0.0
+      rimraf: 6.1.3
+
+  istanbul-lib-report@3.0.1:
+    dependencies:
+      istanbul-lib-coverage: 3.2.2
+      make-dir: 4.0.0
+      supports-color: 7.2.0
+
+  istanbul-lib-source-maps@4.0.1(supports-color@5.5.0):
+    dependencies:
+      debug: 4.4.3(supports-color@5.5.0)
+      istanbul-lib-coverage: 3.2.2
+      source-map: 0.6.1
+    transitivePeerDependencies:
+      - supports-color
+
+  istanbul-reports@3.2.0:
+    dependencies:
+      html-escaper: 2.0.2
+      istanbul-lib-report: 3.0.1
+
+  jackspeak@3.4.3:
+    dependencies:
+      '@isaacs/cliui': 8.0.2
+    optionalDependencies:
+      '@pkgjs/parseargs': 0.11.0
+
+  js-tokens@4.0.0: {}
+
+  js-yaml@3.14.2:
+    dependencies:
+      argparse: 1.0.10
+      esprima: 4.0.1
+
+  js-yaml@4.3.2:
+    dependencies:
+      argparse: 2.0.1
+
+  jsesc@3.1.0: {}
+
+  json-buffer@3.0.1: {}
+
+  json-schema-traverse@0.4.1: {}
+
+  json-stable-stringify-without-jsonify@1.0.1: {}
+
+  json-stringify-safe@5.0.1: {}
+
+  json5@2.2.3: {}
+
+  jsonfile@6.2.1:
+    dependencies:
+      universalify: 2.0.1
+    optionalDependencies:
+      graceful-fs: 4.2.11
+
+  keyv@4.5.4:
+    dependencies:
+      json-buffer: 3.0.1
+
+  levn@0.4.1:
+    dependencies:
+      prelude-ls: 1.2.1
+      type-check: 0.4.0
+
+  locate-path@5.0.0:
+    dependencies:
+      p-locate: 4.1.0
+
+  locate-path@6.0.0:
+    dependencies:
+      p-locate: 5.0.0
+
+  lodash.flattendeep@4.4.0: {}
+
+  lodash.merge@4.6.2: {}
+
+  log-symbols@2.2.0:
+    dependencies:
+      chalk: 2.4.2
+
+  log-symbols@4.1.0:
+    dependencies:
+      chalk: 4.1.2
+      is-unicode-supported: 0.1.0
+
+  lru-cache@10.4.3: {}
+
+  lru-cache@11.5.2: {}
+
+  lru-cache@5.1.1:
+    dependencies:
+      yallist: 3.1.1
+
+  make-dir@3.1.0:
+    dependencies:
+      semver: 6.3.1
+
+  make-dir@4.0.0:
+    dependencies:
+      semver: 7.7.4
+
+  math-intrinsics@1.1.0: {}
+
+  mime-db@1.52.0: {}
+
+  mime-types@2.1.35:
+    dependencies:
+      mime-db: 1.52.0
+
+  mimic-fn@1.2.0: {}
+
+  mimic-response@3.1.0: {}
+
+  minimatch@10.2.6:
+    dependencies:
+      brace-expansion: 5.0.9
+
+  minimatch@3.1.5:
+    dependencies:
+      brace-expansion: 1.1.13
+
+  minimatch@9.0.9:
+    dependencies:
+      brace-expansion: 2.1.4
+
+  minimist@1.2.8: {}
+
+  minipass@7.1.3: {}
+
+  minizlib@3.1.0:
+    dependencies:
+      minipass: 7.1.3
+
+  mkdirp-classic@0.5.3: {}
+
+  mocha@11.8.0:
+    dependencies:
+      browser-stdout: 1.3.1
+      chokidar: 4.0.3
+      debug: 4.4.3(supports-color@8.1.1)
+      diff: 7.0.0
+      escape-string-regexp: 4.0.0
+      find-up: 5.0.0
+      glob: 10.5.0
+      he: 1.2.0
+      is-path-inside: 3.0.3
+      js-yaml: 4.3.2
+      log-symbols: 4.1.0
+      minimatch: 9.0.9
+      ms: 2.1.3
+      picocolors: 1.1.1
+      serialize-javascript: 6.0.2
+      strip-json-comments: 3.1.1
+      supports-color: 8.1.1
+      workerpool: 9.3.4
+      yargs: 17.7.2
+      yargs-parser: 21.1.1
+      yargs-unparser: 2.0.0
+
+  moment@2.30.1: {}
+
+  ms@2.1.3: {}
+
+  multistream@4.1.0:
+    dependencies:
+      once: 1.4.0
+      readable-stream: 3.6.2
+
+  napi-build-utils@2.0.0: {}
+
+  natural-compare@1.4.0: {}
+
+  nconf@0.13.0:
+    dependencies:
+      async: 3.2.6
+      ini: 2.0.0
+      secure-keys: 1.0.0
+      yargs: 16.2.0
+
+  nock@14.0.17:
+    dependencies:
+      '@mswjs/interceptors': 0.41.9
+      json-stringify-safe: 5.0.1
+      propagate: 2.0.1
+
+  node-abi@3.96.0:
+    dependencies:
+      semver: 7.7.4
+
+  node-int64@0.4.0: {}
+
+  node-preload@0.2.1:
+    dependencies:
+      process-on-spawn: 1.1.0
+
+  node-releases@2.0.37: {}
+
+  nth-check@2.1.1:
+    dependencies:
+      boolbase: 1.0.0
+
+  nyc@18.0.0(supports-color@5.5.0):
+    dependencies:
+      '@istanbuljs/load-nyc-config': 1.1.0
+      '@istanbuljs/schema': 0.1.3
+      caching-transform: 4.0.0
+      convert-source-map: 1.9.0
+      decamelize: 1.2.0
+      find-cache-dir: 3.3.2
+      find-up: 4.1.0
+      foreground-child: 3.3.1
+      get-package-type: 0.1.0
+      glob: 13.0.6
+      istanbul-lib-coverage: 3.2.2
+      istanbul-lib-hook: 3.0.0
+      istanbul-lib-instrument: 6.0.3(supports-color@5.5.0)
+      istanbul-lib-processinfo: 3.0.1
+      istanbul-lib-report: 3.0.1
+      istanbul-lib-source-maps: 4.0.1(supports-color@5.5.0)
+      istanbul-reports: 3.2.0
+      make-dir: 3.1.0
+      node-preload: 0.2.1
+      p-map: 3.0.0
+      process-on-spawn: 1.1.0
+      resolve-from: 5.0.0
+      rimraf: 6.1.3
+      signal-exit: 3.0.7
+      spawn-wrap: 3.0.0
+      test-exclude: 8.0.0
+      yargs: 15.4.1
+    transitivePeerDependencies:
+      - supports-color
+
+  once@1.4.0:
+    dependencies:
+      wrappy: 1.0.2
+
+  onetime@2.0.1:
+    dependencies:
+      mimic-fn: 1.2.0
+
+  optionator@0.9.4:
+    dependencies:
+      deep-is: 0.1.4
+      fast-levenshtein: 2.0.6
+      levn: 0.4.1
+      prelude-ls: 1.2.1
+      type-check: 0.4.0
+      word-wrap: 1.2.5
+
+  ora@3.4.0:
+    dependencies:
+      chalk: 2.4.2
+      cli-cursor: 2.1.0
+      cli-spinners: 2.9.2
+      log-symbols: 2.2.0
+      strip-ansi: 5.2.0
+      wcwidth: 1.0.1
+
+  outvariant@1.4.3: {}
+
+  p-limit@2.3.0:
+    dependencies:
+      p-try: 2.2.0
+
+  p-limit@3.1.0:
+    dependencies:
+      yocto-queue: 0.1.0
+
+  p-locate@4.1.0:
+    dependencies:
+      p-limit: 2.3.0
+
+  p-locate@5.0.0:
+    dependencies:
+      p-limit: 3.1.0
+
+  p-map@3.0.0:
+    dependencies:
+      aggregate-error: 3.1.0
+
+  p-try@2.2.0: {}
+
+  package-hash@4.0.0:
+    dependencies:
+      graceful-fs: 4.2.11
+      hasha: 5.2.2
+      lodash.flattendeep: 4.4.0
+      release-zalgo: 1.0.0
+
+  package-json-from-dist@1.0.1: {}
+
+  parent-module@1.0.1:
+    dependencies:
+      callsites: 3.1.0
+
+  parse5-htmlparser2-tree-adapter@7.1.0:
+    dependencies:
+      domhandler: 5.0.3
+      parse5: 7.3.0
+
+  parse5-parser-stream@7.1.2:
+    dependencies:
+      parse5: 7.3.0
+
+  parse5@7.3.0:
+    dependencies:
+      entities: 6.0.1
+
+  path-exists@4.0.0: {}
+
+  path-key@3.1.1: {}
+
+  path-parse@1.0.7: {}
+
+  path-scurry@1.11.1:
+    dependencies:
+      lru-cache: 10.4.3
+      minipass: 7.1.3
+
+  path-scurry@2.0.2:
+    dependencies:
+      lru-cache: 11.5.2
+      minipass: 7.1.3
+
+  picocolors@1.1.1: {}
+
+  picomatch@4.0.7: {}
+
+  pirates@4.0.7: {}
+
+  pkg-dir@4.2.0:
+    dependencies:
+      find-up: 4.1.0
+
+  postject@1.0.0-alpha.6:
+    dependencies:
+      commander: 9.5.0
+
+  prebuild-install@7.1.3:
+    dependencies:
+      detect-libc: 2.1.2
+      expand-template: 2.0.3
+      github-from-package: 0.0.0
+      minimist: 1.2.8
+      mkdirp-classic: 0.5.3
+      napi-build-utils: 2.0.0
+      node-abi: 3.96.0
+      pump: 3.0.4
+      rc: 1.2.8
+      simple-get: 4.0.1
+      tar-fs: 2.1.5
+      tunnel-agent: 0.6.0
+
+  prelude-ls@1.2.1: {}
+
+  process-nextick-args@2.0.1: {}
+
+  process-on-spawn@1.1.0:
+    dependencies:
+      fromentries: 1.3.2
+
+  progress@2.0.3: {}
+
+  propagate@2.0.1: {}
+
+  proxy-from-env@2.1.0: {}
+
+  pump@3.0.4:
+    dependencies:
+      end-of-stream: 1.4.5
+      once: 1.4.0
+
+  punycode@2.3.1: {}
+
+  randombytes@2.1.0:
+    dependencies:
+      safe-buffer: 5.2.1
+
+  rc@1.2.8:
+    dependencies:
+      deep-extend: 0.6.0
+      ini: 1.3.8
+      minimist: 1.2.8
+      strip-json-comments: 2.0.1
+
+  readable-stream@2.3.8:
+    dependencies:
+      core-util-is: 1.0.3
+      inherits: 2.0.4
+      isarray: 1.0.0
+      process-nextick-args: 2.0.1
+      safe-buffer: 5.1.2
+      string_decoder: 1.1.1
+      util-deprecate: 1.0.2
+
+  readable-stream@3.6.2:
+    dependencies:
+      inherits: 2.0.4
+      string_decoder: 1.3.0
+      util-deprecate: 1.0.2
+
+  readdirp@4.1.2: {}
+
+  release-zalgo@1.0.0:
+    dependencies:
+      es6-error: 4.1.1
+
+  require-directory@2.1.1: {}
+
+  require-main-filename@2.0.0: {}
+
+  resolve-from@4.0.0: {}
+
+  resolve-from@5.0.0: {}
+
+  resolve.exports@2.0.3: {}
+
+  resolve@1.22.12:
+    dependencies:
+      es-errors: 1.3.0
+      is-core-module: 2.16.2
+      path-parse: 1.0.7
+      supports-preserve-symlinks-flag: 1.0.0
+
+  restore-cursor@2.0.0:
+    dependencies:
+      onetime: 2.0.1
+      signal-exit: 3.0.7
+
+  rewire@9.0.1(supports-color@5.5.0):
+    dependencies:
+      eslint: 9.39.5(supports-color@5.5.0)
+      pirates: 4.0.7
+    transitivePeerDependencies:
+      - jiti
+      - supports-color
+
+  rimraf@6.1.3:
+    dependencies:
+      glob: 13.0.6
+      package-json-from-dist: 1.0.1
+
+  safe-buffer@5.1.2: {}
+
+  safe-buffer@5.2.1: {}
+
+  safer-buffer@2.1.2: {}
+
+  secure-keys@1.0.0: {}
+
+  semver@6.3.1: {}
+
+  semver@7.7.4: {}
+
+  serialize-javascript@6.0.2:
+    dependencies:
+      randombytes: 2.1.0
+
+  set-blocking@2.0.0: {}
+
+  shebang-command@2.0.0:
+    dependencies:
+      shebang-regex: 3.0.0
+
+  shebang-regex@3.0.0: {}
+
+  signal-exit@3.0.7: {}
+
+  signal-exit@4.1.0: {}
+
+  simple-concat@1.0.1: {}
+
+  simple-get@4.0.1:
+    dependencies:
+      decompress-response: 6.0.0
+      once: 1.4.0
+      simple-concat: 1.0.1
+
+  source-map@0.6.1: {}
+
+  spawn-wrap@3.0.0:
+    dependencies:
+      cross-spawn: 7.0.6
+      foreground-child: 2.0.0
+      is-windows: 1.0.2
+      make-dir: 3.1.0
+      rimraf: 6.1.3
+      signal-exit: 3.0.7
+      which: 2.0.2
+
+  sprintf-js@1.0.3: {}
+
+  stream-meter@1.0.4:
+    dependencies:
+      readable-stream: 2.3.8
+
+  streamx@2.28.1:
+    dependencies:
+      events-universal: 1.0.1
+      fast-fifo: 1.3.2
+      text-decoder: 1.2.7
+    transitivePeerDependencies:
+      - bare-abort-controller
+      - react-native-b4a
+
+  strict-event-emitter@0.5.1: {}
+
+  string-width@4.2.3:
+    dependencies:
+      emoji-regex: 8.0.0
+      is-fullwidth-code-point: 3.0.0
+      strip-ansi: 6.0.1
+
+  string-width@5.1.2:
+    dependencies:
+      eastasianwidth: 0.2.0
+      emoji-regex: 9.2.2
+      strip-ansi: 7.2.0
+
+  string_decoder@1.1.1:
+    dependencies:
+      safe-buffer: 5.1.2
+
+  string_decoder@1.3.0:
+    dependencies:
+      safe-buffer: 5.2.1
+
+  strip-ansi@5.2.0:
+    dependencies:
+      ansi-regex: 4.1.1
+
+  strip-ansi@6.0.1:
+    dependencies:
+      ansi-regex: 5.0.1
+
+  strip-ansi@7.2.0:
+    dependencies:
+      ansi-regex: 6.3.0
+
+  strip-bom@4.0.0: {}
+
+  strip-json-comments@2.0.1: {}
+
+  strip-json-comments@3.1.1: {}
+
+  supports-color@5.5.0:
+    dependencies:
+      has-flag: 3.0.0
+
+  supports-color@7.2.0:
+    dependencies:
+      has-flag: 4.0.0
+
+  supports-color@8.1.1:
+    dependencies:
+      has-flag: 4.0.0
+
+  supports-preserve-symlinks-flag@1.0.0: {}
+
+  tar-fs@2.1.5:
+    dependencies:
+      chownr: 1.1.4
+      mkdirp-classic: 0.5.3
+      pump: 3.0.4
+      tar-stream: 2.2.0
+
+  tar-fs@3.1.3:
+    dependencies:
+      pump: 3.0.4
+      tar-stream: 3.2.1
+    optionalDependencies:
+      bare-fs: 4.8.1
+      bare-path: 3.1.1
+    transitivePeerDependencies:
+      - bare-abort-controller
+      - bare-buffer
+      - react-native-b4a
+
+  tar-stream@2.2.0:
+    dependencies:
+      bl: 4.1.0
+      end-of-stream: 1.4.5
+      fs-constants: 1.0.0
+      inherits: 2.0.4
+      readable-stream: 3.6.2
+
+  tar-stream@3.2.1:
+    dependencies:
+      b4a: 1.8.1
+      bare-fs: 4.8.1
+      fast-fifo: 1.3.2
+      streamx: 2.28.1
+    transitivePeerDependencies:
+      - bare-abort-controller
+      - bare-buffer
+      - react-native-b4a
+
+  tar@7.5.22:
+    dependencies:
+      '@isaacs/fs-minipass': 4.0.1
+      chownr: 3.0.0
+      minipass: 7.1.3
+      minizlib: 3.1.0
+      yallist: 5.0.0
+
+  teex@1.0.1:
+    dependencies:
+      streamx: 2.28.1
+    transitivePeerDependencies:
+      - bare-abort-controller
+      - react-native-b4a
+
+  test-exclude@8.0.0:
+    dependencies:
+      '@istanbuljs/schema': 0.1.3
+      glob: 13.0.6
+      minimatch: 10.2.6
+
+  text-decoder@1.2.7:
+    dependencies:
+      b4a: 1.8.1
+    transitivePeerDependencies:
+      - react-native-b4a
+
+  tinyglobby@0.2.17:
+    dependencies:
+      fdir: 6.5.0(picomatch@4.0.7)
+      picomatch: 4.0.7
+
+  tunnel-agent@0.6.0:
+    dependencies:
+      safe-buffer: 5.2.1
+
+  type-check@0.4.0:
+    dependencies:
+      prelude-ls: 1.2.1
+
+  type-fest@0.8.1: {}
+
+  typedarray-to-buffer@3.1.5:
+    dependencies:
+      is-typedarray: 1.0.0
+
+  underscore@1.13.8: {}
+
+  undici@7.29.0: {}
+
+  universalify@2.0.1: {}
+
+  unzipper@0.12.5:
+    dependencies:
+      bluebird: 3.7.2
+      duplexer2: 0.1.4
+      fs-extra: 11.3.1
+      graceful-fs: 4.2.11
+      node-int64: 0.4.0
+
+  update-browserslist-db@1.2.3(browserslist@4.28.2):
+    dependencies:
+      browserslist: 4.28.2
+      escalade: 3.2.0
+      picocolors: 1.1.1
+
+  uri-js@4.4.1:
+    dependencies:
+      punycode: 2.3.1
+
+  util-deprecate@1.0.2: {}
+
+  wcwidth@1.0.1:
+    dependencies:
+      defaults: 1.0.4
+
+  whatwg-encoding@3.1.1:
+    dependencies:
+      iconv-lite: 0.6.3
+
+  whatwg-mimetype@4.0.0: {}
+
+  which-module@2.0.1: {}
+
+  which@2.0.2:
+    dependencies:
+      isexe: 2.0.0
+
+  word-wrap@1.2.5: {}
+
+  workerpool@9.3.4: {}
+
+  wrap-ansi@6.2.0:
+    dependencies:
+      ansi-styles: 4.3.0
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+
+  wrap-ansi@7.0.0:
+    dependencies:
+      ansi-styles: 4.3.0
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+
+  wrap-ansi@8.1.0:
+    dependencies:
+      ansi-styles: 6.2.3
+      string-width: 5.1.2
+      strip-ansi: 7.2.0
+
+  wrappy@1.0.2: {}
+
+  write-file-atomic@3.0.3:
+    dependencies:
+      imurmurhash: 0.1.4
+      is-typedarray: 1.0.0
+      signal-exit: 3.0.7
+      typedarray-to-buffer: 3.1.5
+
+  y18n@4.0.3: {}
+
+  y18n@5.0.8: {}
+
+  yallist@3.1.1: {}
+
+  yallist@5.0.0: {}
+
+  yargs-parser@18.1.3:
+    dependencies:
+      camelcase: 5.3.1
+      decamelize: 1.2.0
+
+  yargs-parser@20.2.4: {}
+
+  yargs-parser@21.1.1: {}
+
+  yargs-unparser@2.0.0:
+    dependencies:
+      camelcase: 6.3.0
+      decamelize: 4.0.0
+      flat: 5.0.2
+      is-plain-obj: 2.1.0
+
+  yargs@15.4.1:
+    dependencies:
+      cliui: 6.0.0
+      decamelize: 1.2.0
+      find-up: 4.1.0
+      get-caller-file: 2.0.5
+      require-directory: 2.1.1
+      require-main-filename: 2.0.0
+      set-blocking: 2.0.0
+      string-width: 4.2.3
+      which-module: 2.0.1
+      y18n: 4.0.3
+      yargs-parser: 18.1.3
+
+  yargs@16.2.0:
+    dependencies:
+      cliui: 7.0.4
+      escalade: 3.2.0
+      get-caller-file: 2.0.5
+      require-directory: 2.1.1
+      string-width: 4.2.3
+      y18n: 5.0.8
+      yargs-parser: 20.2.4
+
+  yargs@17.7.2:
+    dependencies:
+      cliui: 8.0.1
+      escalade: 3.2.0
+      get-caller-file: 2.0.5
+      require-directory: 2.1.1
+      string-width: 4.2.3
+      y18n: 5.0.8
+      yargs-parser: 21.1.1
+
+  yocto-queue@0.1.0: {}
diff --git a/templates/codeonly.tpl b/templates/codeonly.tpl
index d8baa802..ae5b54a7 100644
--- a/templates/codeonly.tpl
+++ b/templates/codeonly.tpl
@@ -1 +1,9 @@
+${comment.start}
+${comment.line} @lc app=${app} id=${fid} lang=${lang}
+${comment.line}
+${comment.line} [${fid}] ${name}
+${comment.end}
+
+${comment.singleLine} @lc code=start
 ${code}
+${comment.singleLine} @lc code=end
diff --git a/templates/detailed.tpl b/templates/detailed.tpl
index cf501c0d..f310584f 100644
--- a/templates/detailed.tpl
+++ b/templates/detailed.tpl
@@ -7,10 +7,18 @@ ${comment.line} ${link}
 ${comment.line}
 ${comment.line} ${category}
 ${comment.line} ${level} (${percent}%)
+${comment.line} Likes:    ${likes}
+${comment.line} Dislikes: ${dislikes}
 ${comment.line} Total Accepted:    ${totalAC}
 ${comment.line} Total Submissions: ${totalSubmit}
 ${comment.line} Testcase Example:  ${testcase}
 ${comment.line}
 {{ desc.forEach(function(x) { }}${comment.line} ${x}
+{{ }) }}{{ hints.forEach(function(hint, index) { }}${comment.line}
+${comment.line} Hint ${index + 1}:
+${comment.line} ${hint}
 {{ }) }}${comment.end}
+
+${comment.singleLine} @lc code=start
 ${code}
+${comment.singleLine} @lc code=end
diff --git a/test/commands/test_cache.js b/test/commands/test_cache.js
new file mode 100644
index 00000000..5005ff9d
--- /dev/null
+++ b/test/commands/test_cache.js
@@ -0,0 +1,73 @@
+'use strict';
+const fs = require('fs');
+const assert = require('chai').assert;
+const rewire = require('rewire');
+
+const chalk = require('../../lib/chalk');
+const log = require('../../lib/log');
+const th = require('../helper');
+
+const stripAnsi = s => s.replace(/\u001b\[[0-9;]*m/g, '');
+
+describe('command:cache', function() {
+  let cmd;
+  let out;
+  let cache;
+  let file;
+
+  before(function() {
+    log.init();
+    chalk.init();
+  });
+
+  beforeEach(function() {
+    th.clean();
+    out = [];
+    log.output = x => out.push(x);
+
+    file = rewire('../../lib/file');
+    file.cacheDir = () => th.DIR;
+
+    cache = rewire('../../lib/cache');
+    cache.__set__('file', file);
+    cache.init();
+
+    cmd = rewire('../../lib/commands/cache');
+    cmd.__set__('cache', cache);
+  });
+
+  it('should list caches with a solved marker', function() {
+    cache.set('problems', [
+      {fid: 1, slug: 'two-sum', state: 'ac', category: 'algorithms'},
+      {fid: 2, slug: 'add-two', state: 'None', category: 'algorithms'}
+    ]);
+    cache.set('problemsMeta', {fetchedAt: Date.now(), v: 2});
+    cache.set('1.two-sum.algorithms', {desc: '
'});
+    cache.set('2.add-two.algorithms', {desc: '
'});
+    cache.set('user', {name: 'x'});
+
+    cmd.handler({keyword: '', delete: false});
+
+    const text = stripAnsi(out.join('\n'));
+    assert.include(text, '1.two-sum.algorithms');
+    assert.include(text, '2.add-two.algorithms');
+    // solved problems get a check mark, unsolved ones a blank slot
+    const row1 = out.find(x => x.includes('1.two-sum'));
+    const row2 = out.find(x => x.includes('2.add-two'));
+    assert.notEqual(row1.indexOf('✔'), -1);
+    assert.equal(row2.indexOf('✔'), -1);
+    // non-problem caches have no marker column alignment issues
+    const rowUser = out.find(x => x.includes('user'));
+    assert.exists(rowUser);
+  });
+
+  it('should delete caches by id', function() {
+    cache.set('1.two-sum.algorithms', {x: 1});
+    cache.set('2.add-two.algorithms', {x: 1});
+
+    cmd.handler({keyword: '1', delete: true});
+
+    assert.equal(cache.get('1.two-sum.algorithms'), null);
+    assert.notEqual(cache.get('2.add-two.algorithms'), null);
+  });
+});
diff --git a/test/commands/test_list.js b/test/commands/test_list.js
new file mode 100644
index 00000000..4c76cabc
--- /dev/null
+++ b/test/commands/test_list.js
@@ -0,0 +1,73 @@
+'use strict';
+const assert = require('chai').assert;
+const rewire = require('rewire');
+
+const config = require('../../lib/config');
+const chalk = require('../../lib/chalk');
+const icon = require('../../lib/icon');
+const log = require('../../lib/log');
+
+const PROBLEMS = [
+  {fid:      1, name:     'Two Sum', slug:     'two-sum', starred:  true, locked:   false,
+      state:    'ac', level:    'Easy', category: 'algorithms', percent:  50},
+  {fid:      2, name:     'Two Sum II', slug:     'two-sum-ii', starred:  false, locked:   false,
+      state:    'None', level:    'Medium', category: 'algorithms', percent:  40},
+  {fid:      3, name:     'Third', slug:     'third', starred:  false, locked:   true,
+      state:    'None', level:    'Hard', category: 'algorithms', percent:  30}
+];
+
+const stripAnsi = s => s.replace(/\u001b\[[0-9;]*m/g, '');
+
+describe('command:list', function() {
+  let cmd;
+  let out;
+  let filterProblems;
+
+  before(function() {
+    log.init();
+    config.init();
+    chalk.init();
+    icon.init();
+  });
+
+  beforeEach(function() {
+    out = [];
+    log.output = x => out.push(x);
+    process.exitCode = 0;
+
+    cmd = rewire('../../lib/commands/list');
+    filterProblems = (argv, cb) => cb(null, PROBLEMS.slice());
+    cmd.__set__('core', {filterProblems: filterProblems});
+  });
+
+  it('should list all problems w/ stats', function() {
+    cmd.handler({keyword: '', query: '', stat: true, extra: false});
+
+    const text = stripAnsi(out.join('\n'));
+    assert.include(text, 'Two Sum');
+    assert.include(text, 'Two Sum II');
+    assert.include(text, 'Third');
+    assert.include(text, 'Listed: 3');
+    assert.include(text, 'Locked:  1');
+    assert.include(text, 'Accept: 1');
+    assert.include(text, 'Remain:  2');
+    assert.include(text, 'Easy:   1');
+    assert.include(text, 'Medium:  1');
+    assert.include(text, 'Hard:    1');
+  });
+
+  it('should filter by keyword', function() {
+    cmd.handler({keyword: 'two sum', query: '', stat: false, extra: false});
+
+    const text = stripAnsi(out.join('\n'));
+    assert.include(text, 'Two Sum');
+    assert.notInclude(text, 'Third');
+  });
+
+  it('should warn on repeated keyboard characters', function() {
+    cmd.handler({keyword: 'aaaaaa', query: '', stat: false, extra: false});
+
+    const text = stripAnsi(out.join('\n'));
+    assert.include(text, 'new keyboard');
+  });
+});
diff --git a/test/commands/test_show.js b/test/commands/test_show.js
new file mode 100644
index 00000000..d277dac8
--- /dev/null
+++ b/test/commands/test_show.js
@@ -0,0 +1,81 @@
+'use strict';
+const fs = require('fs');
+const assert = require('chai').assert;
+const rewire = require('rewire');
+
+const config = require('../../lib/config');
+const chalk = require('../../lib/chalk');
+const icon = require('../../lib/icon');
+const log = require('../../lib/log');
+const file = require('../../lib/file');
+const th = require('../helper');
+
+const PROBLEM = {
+  fid:       1,
+  name:      'Two Sum',
+  slug:      'two-sum',
+  link:      'https://leetcode.com/problems/two-sum/',
+  category:  'algorithms',
+  level:     'Easy',
+  percent:   50,
+  starred:   false,
+  locked:    false,
+  likes:     10,
+  dislikes:  2,
+  templates: [{value: 'cpp', defaultCode: 'class Solution {};'}],
+  testcase:  '[2,7,11,15]',
+  testable:  true,
+  desc:      '

Given an array of integers nums.

', + hints: ['A brute force way would be O(n^2).'] +}; + +const stripAnsi = s => s.replace(/\u001b\[[0-9;]*m/g, ''); + +describe('command:show', function() { + let cmd; + let out; + + before(function() { + log.init(); + config.init(); + file.init(); + chalk.init(); + icon.init(); + }); + + beforeEach(function() { + th.clean(); + out = []; + log.output = x => out.push(x); + + cmd = rewire('../../lib/commands/show'); + cmd.__set__('core', { + getProblem: (kw, t, cb) => cb(null, Object.assign({}, PROBLEM)), + exportProblem: (problem, opts) => problem.templates[0].defaultCode + }); + }); + + it('should show the problem with plain text desc and hints', function() { + cmd.handler({keyword: 'two-sum', daily: false, gen: false, codeonly: false, extra: false}); + + const text = stripAnsi(out.join('\n')); + assert.include(text, '[1] Two Sum'); + assert.include(text, PROBLEM.link); + // html decoded to plain text + assert.include(text, 'Given an array of integers nums.'); + assert.notInclude(text, ''); + assert.include(text, 'Hint 1: A brute force way would be O(n^2).'); + assert.notInclude(text, '
'); + }); + + it('should generate source code from template', function() { + cmd.handler({keyword: 'two-sum', daily: false, gen: true, codeonly: false, + extra: true, outdir: th.DIR, lang: 'cpp'}); + + const text = stripAnsi(out.join('\n')); + assert.include(text, 'Source Code:'); + const files = fs.readdirSync(th.DIR); + assert.equal(files.length, 1); + assert.include(fs.readFileSync(th.DIR + files[0], 'utf8'), 'class Solution {};'); + }); +}); diff --git a/test/commands/test_stat.js b/test/commands/test_stat.js new file mode 100644 index 00000000..aab3e5b9 --- /dev/null +++ b/test/commands/test_stat.js @@ -0,0 +1,60 @@ +'use strict'; +const assert = require('chai').assert; +const rewire = require('rewire'); + +const config = require('../../lib/config'); +const chalk = require('../../lib/chalk'); +const icon = require('../../lib/icon'); +const log = require('../../lib/log'); +const h = require('../../lib/helper'); + +const PROBLEMS = []; +for (let i = 0; i < 10; ++i) PROBLEMS.push({fid: i + 1, state: 'ac', level: 'Easy'}); +for (let i = 0; i < 20; ++i) PROBLEMS.push({fid: i + 11, state: 'None', level: 'Medium'}); +for (let i = 0; i < 5; ++i) PROBLEMS.push({fid: i + 31, state: 'notac', level: 'Hard'}); + +const stripAnsi = s => s.replace(/\u001b\[[0-9;]*m/g, ''); + +describe('command:stat', function() { + let cmd; + let out; + + before(function() { + log.init(); + config.init(); + chalk.init(); + icon.init(); + h.width = 120; + }); + + beforeEach(function() { + out = []; + log.output = x => out.push(x); + + cmd = rewire('../../lib/commands/stat'); + cmd.__set__('core', {filterProblems: (argv, cb) => cb(null, PROBLEMS.slice())}); + }); + + it('should show progress bars', function() { + cmd.handler({lock: true}); + + const text = stripAnsi(out.join('\n')); + assert.include(text, 'Easy'); + assert.include(text, '10/10'); + assert.include(text, 'Medium'); + assert.include(text, ' 0/20'); + assert.include(text, 'Hard'); + assert.include(text, ' 0/5'); + assert.match(text, /█+/, 'green bar rendered'); + assert.match(text, /░+/, 'red bar rendered'); + }); + + it('should show the graph legend', function() { + cmd.handler({lock: true, graph: true}); + + const text = stripAnsi(out.join('\n')); + assert.include(text, 'Accepted'); + assert.include(text, 'Not Accepted'); + assert.include(text, 'Remaining'); + }); +}); diff --git a/test/commands/test_submission.js b/test/commands/test_submission.js new file mode 100644 index 00000000..e009f641 --- /dev/null +++ b/test/commands/test_submission.js @@ -0,0 +1,75 @@ +'use strict'; +const fs = require('fs'); +const assert = require('chai').assert; +const rewire = require('rewire'); + +const config = require('../../lib/config'); +const chalk = require('../../lib/chalk'); +const icon = require('../../lib/icon'); +const log = require('../../lib/log'); +const file = require('../../lib/file'); +const th = require('../helper'); + +const PROBLEM = {fid: 1, name: 'Two Sum', slug: 'two-sum', category: 'algorithms'}; +const SUBMISSION = { + id: 's1', + lang: 'cpp', + status_display: 'Accepted', + code: 'int main() {}' +}; + +const stripAnsi = s => s.replace(/\u001b\[[0-9;]*m/g, ''); + +describe('command:submission', function() { + let cmd; + let out; + + before(function() { + log.init(); + config.init(); + file.init(); + chalk.init(); + icon.init(); + }); + + beforeEach(function() { + th.clean(); + out = []; + log.output = x => out.push(x); + process.exitCode = 0; + + cmd = rewire('../../lib/commands/submission'); + cmd.__set__('core', { + getProblem: (kw, t, cb) => cb(null, Object.assign({lang: 'cpp'}, PROBLEM)), + getSubmissions: (problem, cb) => cb(null, [SUBMISSION]), + getSubmission: (submission, cb) => cb(null, Object.assign({}, SUBMISSION)), + exportProblem: (problem, opts) => opts.code + }); + }); + + it('should download the accepted submission', function(done) { + this.timeout(2000); + cmd.handler({keyword: '1', outdir: th.DIR, lang: 'all', extra: false, dontTranslate: true}); + + // the write happens from the async queue, poll for it + (function wait() { + const files = fs.existsSync(th.DIR) ? fs.readdirSync(th.DIR) : []; + if (files.length === 0) return setTimeout(wait, 20); + + assert.equal(files.length, 1); + assert.include(files[0], '1.'); + assert.include(fs.readFileSync(th.DIR + files[0], 'utf8'), 'int main() {}'); + assert.notEqual(process.exitCode, 1); + done(); + })(); + }); + + it('should flag errors and keep going', function() { + cmd.__set__('core', { + getProblem: (kw, t, cb) => cb('problem not found!') + }); + + cmd.handler({keyword: '404', outdir: th.DIR, lang: 'all', extra: false, dontTranslate: true}); + assert.equal(process.exitCode, 1); + }); +}); diff --git a/test/commands/test_user.js b/test/commands/test_user.js new file mode 100644 index 00000000..ce374b86 --- /dev/null +++ b/test/commands/test_user.js @@ -0,0 +1,62 @@ +'use strict'; +const assert = require('chai').assert; +const rewire = require('rewire'); + +const config = require('../../lib/config'); +const chalk = require('../../lib/chalk'); +const log = require('../../lib/log'); + +const USER = {name: 'ywnwa417', paid: false}; + +const stripAnsi = s => s.replace(/\u001b\[[0-9;]*m/g, ''); + +describe('command:user', function() { + let cmd; + let out; + let session; + + before(function() { + log.init(); + config.init(); + chalk.init(); + }); + + beforeEach(function() { + out = []; + log.output = x => out.push(x); + process.exitCode = 0; + + cmd = rewire('../../lib/commands/user'); + session = { + argv: null, + getUser: () => USER, + deleteUser: () => {} + }; + cmd.__set__('session', session); + cmd.__set__('core', {logout: (user, purge) => USER}); + }); + + it('should show the current user', function() { + cmd.handler({}); + + const text = stripAnsi(out.join('\n')); + assert.include(text, 'Premium'); + assert.include(text, 'ywnwa417'); + assert.include(text, 'leetcode.com'); + }); + + it('should show not-login for missing user', function() { + session.getUser = () => null; + + cmd.handler({}); + const text = stripAnsi(out.join('\n')); + assert.include(text, 'not login yet'); + assert.equal(process.exitCode, 1); + }); + + it('should logout ok', function() { + cmd.handler({logout: true}); + const text = stripAnsi(out.join('\n')); + assert.include(text, 'Successfully logout as'); + }); +}); diff --git a/test/mock/add-two-numbers.20161015.json b/test/mock/add-two-numbers.20161015.json index c8a4d61f..aaee38bd 100644 --- a/test/mock/add-two-numbers.20161015.json +++ b/test/mock/add-two-numbers.20161015.json @@ -1 +1 @@ -{"state":"ac","id":2,"category":"algorithms","name":"Add Two Numbers","key":"add-two-numbers","link":"https://leetcode.com/problems/add-two-numbers","locked":false,"percent":25.368142876074806,"level":"Medium","starred":true,"totalAC":"195263","totalSubmit":"769711","desc":"You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.\r\n\r\nInput: (2 -> 4 -> 3) + (5 -> 6 -> 4)\r\nOutput: 7 -> 0 -> 8","templates":[{"value":"cpp","text":"C++","defaultCode":"/**\r\n * Definition for singly-linked list.\r\n * struct ListNode {\r\n * int val;\r\n * ListNode *next;\r\n * ListNode(int x) : val(x), next(NULL) {}\r\n * };\r\n */\r\nclass Solution {\r\npublic:\r\n ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {\r\n \r\n }\r\n};"},{"value":"java","text":"Java","defaultCode":"/**\r\n * Definition for singly-linked list.\r\n * public class ListNode {\r\n * int val;\r\n * ListNode next;\r\n * ListNode(int x) { val = x; }\r\n * }\r\n */\r\npublic class Solution {\r\n public ListNode addTwoNumbers(ListNode l1, ListNode l2) {\r\n \r\n }\r\n}"},{"value":"python","text":"Python","defaultCode":"# Definition for singly-linked list.\r\n# class ListNode(object):\r\n# def __init__(self, x):\r\n# self.val = x\r\n# self.next = None\r\n\r\nclass Solution(object):\r\n def addTwoNumbers(self, l1, l2):\r\n \"\"\"\r\n :type l1: ListNode\r\n :type l2: ListNode\r\n :rtype: ListNode\r\n \"\"\"\r\n "},{"value":"c","text":"C","defaultCode":"/**\r\n * Definition for singly-linked list.\r\n * struct ListNode {\r\n * int val;\r\n * struct ListNode *next;\r\n * };\r\n */\r\nstruct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {\r\n \r\n}"},{"value":"csharp","text":"C#","defaultCode":"/**\r\n * Definition for singly-linked list.\r\n * public class ListNode {\r\n * public int val;\r\n * public ListNode next;\r\n * public ListNode(int x) { val = x; }\r\n * }\r\n */\r\npublic class Solution {\r\n public ListNode AddTwoNumbers(ListNode l1, ListNode l2) {\r\n \r\n }\r\n}"},{"value":"javascript","text":"JavaScript","defaultCode":"/**\r\n * Definition for singly-linked list.\r\n * function ListNode(val) {\r\n * this.val = val;\r\n * this.next = null;\r\n * }\r\n */\r\n/**\r\n * @param {ListNode} l1\r\n * @param {ListNode} l2\r\n * @return {ListNode}\r\n */\r\nvar addTwoNumbers = function(l1, l2) {\r\n \r\n};"},{"value":"ruby","text":"Ruby","defaultCode":"# Definition for singly-linked list.\r\n# class ListNode\r\n# attr_accessor :val, :next\r\n# def initialize(val)\r\n# @val = val\r\n# @next = nil\r\n# end\r\n# end\r\n\r\n# @param {ListNode} l1\r\n# @param {ListNode} l2\r\n# @return {ListNode}\r\ndef add_two_numbers(l1, l2)\r\n \r\nend"},{"value":"swift","text":"Swift","defaultCode":"/**\r\n * Definition for singly-linked list.\r\n * public class ListNode {\r\n * public var val: Int\r\n * public var next: ListNode?\r\n * public init(_ val: Int) {\r\n * self.val = val\r\n * self.next = nil\r\n * }\r\n * }\r\n */\r\nclass Solution {\r\n func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {\r\n \r\n }\r\n}"},{"value":"golang","text":"Go","defaultCode":"/**\r\n * Definition for singly-linked list.\r\n * type ListNode struct {\r\n * Val int\r\n * Next *ListNode\r\n * }\r\n */\r\nfunc addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {\r\n \r\n}"}],"testcase":"[2,4,3]\n[5,6,4]","testable":true} +{"state":"ac","id":2,"category":"algorithms","name":"Add Two Numbers","key":"add-two-numbers","link":"https://leetcode.com/problems/add-two-numbers","locked":false,"percent":25.368142876074806,"level":"Medium","starred":true,"totalAC":"195263","totalSubmit":"769711","likes": "1","dislikes": "1","desc":"You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.\r\n\r\nInput: (2 -> 4 -> 3) + (5 -> 6 -> 4)\r\nOutput: 7 -> 0 -> 8","templates":[{"value":"cpp","text":"C++","defaultCode":"/**\r\n * Definition for singly-linked list.\r\n * struct ListNode {\r\n * int val;\r\n * ListNode *next;\r\n * ListNode(int x) : val(x), next(NULL) {}\r\n * };\r\n */\r\nclass Solution {\r\npublic:\r\n ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {\r\n \r\n }\r\n};"},{"value":"java","text":"Java","defaultCode":"/**\r\n * Definition for singly-linked list.\r\n * public class ListNode {\r\n * int val;\r\n * ListNode next;\r\n * ListNode(int x) { val = x; }\r\n * }\r\n */\r\npublic class Solution {\r\n public ListNode addTwoNumbers(ListNode l1, ListNode l2) {\r\n \r\n }\r\n}"},{"value":"python","text":"Python","defaultCode":"# Definition for singly-linked list.\r\n# class ListNode(object):\r\n# def __init__(self, x):\r\n# self.val = x\r\n# self.next = None\r\n\r\nclass Solution(object):\r\n def addTwoNumbers(self, l1, l2):\r\n \"\"\"\r\n :type l1: ListNode\r\n :type l2: ListNode\r\n :rtype: ListNode\r\n \"\"\"\r\n "},{"value":"c","text":"C","defaultCode":"/**\r\n * Definition for singly-linked list.\r\n * struct ListNode {\r\n * int val;\r\n * struct ListNode *next;\r\n * };\r\n */\r\nstruct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {\r\n \r\n}"},{"value":"csharp","text":"C#","defaultCode":"/**\r\n * Definition for singly-linked list.\r\n * public class ListNode {\r\n * public int val;\r\n * public ListNode next;\r\n * public ListNode(int x) { val = x; }\r\n * }\r\n */\r\npublic class Solution {\r\n public ListNode AddTwoNumbers(ListNode l1, ListNode l2) {\r\n \r\n }\r\n}"},{"value":"javascript","text":"JavaScript","defaultCode":"/**\r\n * Definition for singly-linked list.\r\n * function ListNode(val) {\r\n * this.val = val;\r\n * this.next = null;\r\n * }\r\n */\r\n/**\r\n * @param {ListNode} l1\r\n * @param {ListNode} l2\r\n * @return {ListNode}\r\n */\r\nvar addTwoNumbers = function(l1, l2) {\r\n \r\n};"},{"value":"ruby","text":"Ruby","defaultCode":"# Definition for singly-linked list.\r\n# class ListNode\r\n# attr_accessor :val, :next\r\n# def initialize(val)\r\n# @val = val\r\n# @next = nil\r\n# end\r\n# end\r\n\r\n# @param {ListNode} l1\r\n# @param {ListNode} l2\r\n# @return {ListNode}\r\ndef add_two_numbers(l1, l2)\r\n \r\nend"},{"value":"swift","text":"Swift","defaultCode":"/**\r\n * Definition for singly-linked list.\r\n * public class ListNode {\r\n * public var val: Int\r\n * public var next: ListNode?\r\n * public init(_ val: Int) {\r\n * self.val = val\r\n * self.next = nil\r\n * }\r\n * }\r\n */\r\nclass Solution {\r\n func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {\r\n \r\n }\r\n}"},{"value":"golang","text":"Go","defaultCode":"/**\r\n * Definition for singly-linked list.\r\n * type ListNode struct {\r\n * Val int\r\n * Next *ListNode\r\n * }\r\n */\r\nfunc addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {\r\n \r\n}"}],"testcase":"[2,4,3]\n[5,6,4]","testable":true} diff --git a/test/mock/find-the-difference-star.json.20200821 b/test/mock/find-the-difference-star.json.20200821 new file mode 100644 index 00000000..d07567d3 --- /dev/null +++ b/test/mock/find-the-difference-star.json.20200821 @@ -0,0 +1 @@ +{"data":{"addQuestionToFavorite":{"ok":true,"error":null,"favoriteIdHash":"","questionId":"389","__typename":"AddQuestionToFavorite"}}} \ No newline at end of file diff --git a/test/mock/find-the-difference-unstar.json.20200821 b/test/mock/find-the-difference-unstar.json.20200821 new file mode 100644 index 00000000..9d2c26a8 --- /dev/null +++ b/test/mock/find-the-difference-unstar.json.20200821 @@ -0,0 +1 @@ +{"data":{"removeQuestionFromFavorite":{"ok":true,"error":null,"favoriteIdHash":"","questionId":"389","__typename":"RemoveQuestionFromFavorite"}}} \ No newline at end of file diff --git a/test/mock/find-the-difference.json.20171216 b/test/mock/find-the-difference.json.20171216 index bd1f7dc6..c2cd192d 100644 --- a/test/mock/find-the-difference.json.20171216 +++ b/test/mock/find-the-difference.json.20171216 @@ -1 +1 @@ -{"data":{"question":{"content":"

\r\nGiven two strings s and t which consist of only lowercase letters.

\r\n\r\n

String t is generated by random shuffling string s and then add one more letter at a random position.

\r\n\r\n

Find the letter that was added in t.

\r\n\r\n

Example:\r\n

\r\nInput:\r\ns = \"abcd\"\r\nt = \"abcde\"\r\n\r\nOutput:\r\ne\r\n\r\nExplanation:\r\n'e' is the letter that was added.\r\n
","stats":"{\"totalAccepted\": \"89.7K\", \"totalSubmission\": \"175.7K\"}","codeDefinition":"[{\"text\": \"C++\", \"value\": \"cpp\", \"defaultCode\": \"class Solution {\\r\\npublic:\\r\\n char findTheDifference(string s, string t) {\\r\\n \\r\\n }\\r\\n};\"}, {\"text\": \"Java\", \"value\": \"java\", \"defaultCode\": \"class Solution {\\r\\n public char findTheDifference(String s, String t) {\\r\\n \\r\\n }\\r\\n}\"}, {\"text\": \"Python\", \"value\": \"python\", \"defaultCode\": \"class Solution(object):\\r\\n def findTheDifference(self, s, t):\\r\\n \\\"\\\"\\\"\\r\\n :type s: str\\r\\n :type t: str\\r\\n :rtype: str\\r\\n \\\"\\\"\\\"\\r\\n \"}, {\"text\": \"Python3\", \"value\": \"python3\", \"defaultCode\": \"class Solution:\\r\\n def findTheDifference(self, s, t):\\r\\n \\\"\\\"\\\"\\r\\n :type s: str\\r\\n :type t: str\\r\\n :rtype: str\\r\\n \\\"\\\"\\\"\\r\\n \"}, {\"text\": \"C\", \"value\": \"c\", \"defaultCode\": \"char findTheDifference(char* s, char* t) {\\r\\n \\r\\n}\"}, {\"text\": \"C#\", \"value\": \"csharp\", \"defaultCode\": \"public class Solution {\\r\\n public char FindTheDifference(string s, string t) {\\r\\n \\r\\n }\\r\\n}\"}, {\"text\": \"JavaScript\", \"value\": \"javascript\", \"defaultCode\": \"/**\\r\\n * @param {string} s\\r\\n * @param {string} t\\r\\n * @return {character}\\r\\n */\\r\\nvar findTheDifference = function(s, t) {\\r\\n \\r\\n};\"}, {\"text\": \"Ruby\", \"value\": \"ruby\", \"defaultCode\": \"# @param {String} s\\r\\n# @param {String} t\\r\\n# @return {Character}\\r\\ndef find_the_difference(s, t)\\r\\n \\r\\nend\"}, {\"text\": \"Swift\", \"value\": \"swift\", \"defaultCode\": \"class Solution {\\r\\n func findTheDifference(_ s: String, _ t: String) -> Character {\\r\\n \\r\\n }\\r\\n}\"}, {\"text\": \"Go\", \"value\": \"golang\", \"defaultCode\": \"func findTheDifference(s string, t string) byte {\\r\\n \\r\\n}\"}, {\"text\": \"Scala\", \"value\": \"scala\", \"defaultCode\": \"object Solution {\\n def findTheDifference(s: String, t: String): Char = {\\n \\n }\\n}\"}, {\"text\": \"Kotlin\", \"value\": \"kotlin\", \"defaultCode\": \"class Solution {\\n fun findTheDifference(s: String, t: String): Char {\\n \\n }\\n}\"}]","sampleTestCase":"\"abcd\"\n\"abcde\"","enableRunCode":true,"metaData":"{\r\n \"name\": \"findTheDifference\",\r\n \"params\": [\r\n {\r\n \"name\": \"s\",\r\n \"type\": \"string\"\r\n },\r\n {\r\n \"name\": \"t\",\r\n \"type\": \"string\"\r\n }\r\n ],\r\n \"return\": {\r\n \"type\": \"character\"\r\n }\r\n}","discussCategoryId":"511"}}} \ No newline at end of file +{"data": {"question": {"content": "

\r\nGiven two strings s and t which consist of only lowercase letters.

\r\n\r\n

String t is generated by random shuffling string s and then add one more letter at a random position.

\r\n\r\n

Find the letter that was added in t.

\r\n\r\n

Example:\r\n

\r\nInput:\r\ns = \"abcd\"\r\nt = \"abcde\"\r\n\r\nOutput:\r\ne\r\n\r\nExplanation:\r\n'e' is the letter that was added.\r\n
", "stats": "{\"totalAccepted\": \"89.7K\", \"totalSubmission\": \"175.7K\"}", "codeDefinition": "[{\"text\": \"C++\", \"value\": \"cpp\", \"defaultCode\": \"class Solution {\\r\\npublic:\\r\\n char findTheDifference(string s, string t) {\\r\\n \\r\\n }\\r\\n};\"}, {\"text\": \"Java\", \"value\": \"java\", \"defaultCode\": \"class Solution {\\r\\n public char findTheDifference(String s, String t) {\\r\\n \\r\\n }\\r\\n}\"}, {\"text\": \"Python\", \"value\": \"python\", \"defaultCode\": \"class Solution(object):\\r\\n def findTheDifference(self, s, t):\\r\\n \\\"\\\"\\\"\\r\\n :type s: str\\r\\n :type t: str\\r\\n :rtype: str\\r\\n \\\"\\\"\\\"\\r\\n \"}, {\"text\": \"Python3\", \"value\": \"python3\", \"defaultCode\": \"class Solution:\\r\\n def findTheDifference(self, s, t):\\r\\n \\\"\\\"\\\"\\r\\n :type s: str\\r\\n :type t: str\\r\\n :rtype: str\\r\\n \\\"\\\"\\\"\\r\\n \"}, {\"text\": \"C\", \"value\": \"c\", \"defaultCode\": \"char findTheDifference(char* s, char* t) {\\r\\n \\r\\n}\"}, {\"text\": \"C#\", \"value\": \"csharp\", \"defaultCode\": \"public class Solution {\\r\\n public char FindTheDifference(string s, string t) {\\r\\n \\r\\n }\\r\\n}\"}, {\"text\": \"JavaScript\", \"value\": \"javascript\", \"defaultCode\": \"/**\\r\\n * @param {string} s\\r\\n * @param {string} t\\r\\n * @return {character}\\r\\n */\\r\\nvar findTheDifference = function(s, t) {\\r\\n \\r\\n};\"}, {\"text\": \"Ruby\", \"value\": \"ruby\", \"defaultCode\": \"# @param {String} s\\r\\n# @param {String} t\\r\\n# @return {Character}\\r\\ndef find_the_difference(s, t)\\r\\n \\r\\nend\"}, {\"text\": \"Swift\", \"value\": \"swift\", \"defaultCode\": \"class Solution {\\r\\n func findTheDifference(_ s: String, _ t: String) -> Character {\\r\\n \\r\\n }\\r\\n}\"}, {\"text\": \"Go\", \"value\": \"golang\", \"defaultCode\": \"func findTheDifference(s string, t string) byte {\\r\\n \\r\\n}\"}, {\"text\": \"Scala\", \"value\": \"scala\", \"defaultCode\": \"object Solution {\\n def findTheDifference(s: String, t: String): Char = {\\n \\n }\\n}\"}, {\"text\": \"Kotlin\", \"value\": \"kotlin\", \"defaultCode\": \"class Solution {\\n fun findTheDifference(s: String, t: String): Char {\\n \\n }\\n}\"}]", "sampleTestCase": "\"abcd\"\n\"abcde\"", "enableRunCode": true, "metaData": "{\r\n \"name\": \"findTheDifference\",\r\n \"params\": [\r\n {\r\n \"name\": \"s\",\r\n \"type\": \"string\"\r\n },\r\n {\r\n \"name\": \"t\",\r\n \"type\": \"string\"\r\n }\r\n ],\r\n \"return\": {\r\n \"type\": \"character\"\r\n }\r\n}", "discussCategoryId": "511", "hints": ["Can we sort the strings?", "XOR trick works here."]}}} \ No newline at end of file diff --git a/test/plugins/test_cache.js b/test/plugins/test_cache.js index 6b3114ca..ddd87506 100644 --- a/test/plugins/test_cache.js +++ b/test/plugins/test_cache.js @@ -16,10 +16,21 @@ describe('plugin:cache', function() { let session; const PROBLEMS = [ - {id: 0, fid: 0, name: 'name0', slug: 'slug0', starred: false, category: 'algorithms'}, - {id: 1, fid: 1, name: 'name1', slug: 'slug1', starred: true, category: 'algorithms'} + { + id: 0, fid: 0, name: 'name0', slug: 'slug0', starred: false, + desc: '
', likes:    '1', dislikes: '1', hints:    [],
+      category: 'algorithms'
+    },
+    {
+      id:       1, fid:      1, name:     'name1', slug:     'slug1', starred:  true,
+      desc:     '
', likes:    '1', dislikes: '1', hints:    [],
+      category: 'algorithms'
+    }
   ];
+  const TRANSLATION_CONFIGS = { useEndpointTranslation: false };
   const PROBLEM = {id: 0, fid: 0, slug: 'slug0', category: 'algorithms'};
+  const FRESH_META = () => ({fetchedAt: Date.now(), v: 2});
+  const EXPIRED_META = () => ({fetchedAt: Date.now() - 25 * 60 * 60 * 1000, v: 2});
 
   before(function() {
     log.init();
@@ -49,10 +60,73 @@ describe('plugin:cache', function() {
   });
 
   describe('#getProblems', function() {
-    it('should getProblems w/ cache ok', function(done) {
+    it('should getProblems w/ fresh cache ok', function(done) {
       cache.set('problems', PROBLEMS);
+      cache.set(h.KEYS.problemsMeta, FRESH_META());
+      cache.set(h.KEYS.translation, TRANSLATION_CONFIGS);
+      next.getProblems = () => assert.fail('should not reach next plugin');
 
-      plugin.getProblems(function(e, problems) {
+      plugin.getProblems(false, function(e, problems) {
+        assert.equal(e, null);
+        assert.deepEqual(problems, PROBLEMS);
+        done();
+      });
+    });
+
+    it('should refresh problems w/ expired cache', function(done) {
+      cache.set('problems', PROBLEMS);
+      cache.set(h.KEYS.problemsMeta, EXPIRED_META());
+      cache.set(h.KEYS.translation, TRANSLATION_CONFIGS);
+      const NEW_PROBLEMS = [{id: 2, fid: 2, name: 'name2', slug: 'slug2', category: 'algorithms'}];
+      next.getProblems = (needT, cb) => cb(null, NEW_PROBLEMS);
+
+      plugin.getProblems(false, function(e, problems) {
+        assert.equal(e, null);
+        assert.deepEqual(problems, NEW_PROBLEMS);
+        assert.isAtLeast(cache.get(h.KEYS.problemsMeta).fetchedAt, Date.now() - 1000);
+        done();
+      });
+    });
+
+    it('should refresh legacy problems cache w/o meta', function(done) {
+      cache.set('problems', PROBLEMS);
+      cache.del(h.KEYS.problemsMeta);
+      cache.set(h.KEYS.translation, TRANSLATION_CONFIGS);
+      let reachedNext = false;
+      next.getProblems = (needT, cb) => { reachedNext = true; return cb(null, PROBLEMS); };
+
+      plugin.getProblems(false, function(e, problems) {
+        assert.equal(e, null);
+        assert.deepEqual(problems, PROBLEMS);
+        assert.equal(reachedNext, true);
+        assert.isNumber(cache.get(h.KEYS.problemsMeta).fetchedAt);
+        done();
+      });
+    });
+
+    it('should refresh problems w/ old meta version', function(done) {
+      cache.set('problems', PROBLEMS);
+      cache.set(h.KEYS.problemsMeta, {fetchedAt: Date.now(), v: 1});
+      cache.set(h.KEYS.translation, TRANSLATION_CONFIGS);
+      next.getProblems = (needT, cb) => cb(null, PROBLEMS);
+
+      plugin.getProblems(false, function(e, problems) {
+        assert.equal(e, null);
+        assert.equal(cache.get(h.KEYS.problemsMeta).v, 2);
+        done();
+      });
+    });
+
+    it('should serve stale problems if refresh fails', function(done) {
+      cache.set('problems', PROBLEMS);
+      cache.set(h.KEYS.problemsMeta, EXPIRED_META());
+      cache.set(h.KEYS.translation, TRANSLATION_CONFIGS);
+      next.getProblems = (needT, cb) => cb('client getProblems error');
+
+      const originWarn = log.warn;
+      log.warn = () => {};
+      plugin.getProblems(false, function(e, problems) {
+        log.warn = originWarn;
         assert.equal(e, null);
         assert.deepEqual(problems, PROBLEMS);
         done();
@@ -61,9 +135,9 @@ describe('plugin:cache', function() {
 
     it('should getProblems w/o cache ok', function(done) {
       cache.del('problems');
-      next.getProblems = cb => cb(null, PROBLEMS);
+      next.getProblems = (needT, cb) => cb(null, PROBLEMS);
 
-      plugin.getProblems(function(e, problems) {
+      plugin.getProblems(false, function(e, problems) {
         assert.equal(e, null);
         assert.deepEqual(problems, PROBLEMS);
         done();
@@ -72,9 +146,9 @@ describe('plugin:cache', function() {
 
     it('should getProblems w/o cache fail if client error', function(done) {
       cache.del('problems');
-      next.getProblems = cb => cb('client getProblems error');
+      next.getProblems = (needT, cb) => cb('client getProblems error');
 
-      plugin.getProblems(function(e, problems) {
+      plugin.getProblems(false, function(e, problems) {
         assert.equal(e, 'client getProblems error');
         done();
       });
@@ -84,9 +158,10 @@ describe('plugin:cache', function() {
   describe('#getProblem', function() {
     it('should getProblem w/ cache ok', function(done) {
       cache.set('problems', PROBLEMS);
+      cache.set(h.KEYS.translation, TRANSLATION_CONFIGS);
       cache.set('0.slug0.algorithms', PROBLEMS[0]);
 
-      plugin.getProblem(_.clone(PROBLEM), function(e, problem) {
+      plugin.getProblem(_.clone(PROBLEM), false, function(e, problem) {
         assert.equal(e, null);
         assert.deepEqual(problem, PROBLEMS[0]);
         done();
@@ -96,9 +171,9 @@ describe('plugin:cache', function() {
     it('should getProblem w/o cache ok', function(done) {
       cache.set('problems', PROBLEMS);
       cache.del('0.slug0.algorithms');
-      next.getProblem = (problem, cb) => cb(null, PROBLEMS[0]);
+      next.getProblem = (problem, needT, cb) => cb(null, PROBLEMS[0]);
 
-      plugin.getProblem(_.clone(PROBLEM), function(e, problem) {
+      plugin.getProblem(_.clone(PROBLEM), false, function(e, problem) {
         assert.equal(e, null);
         assert.deepEqual(problem, PROBLEMS[0]);
         done();
@@ -108,9 +183,9 @@ describe('plugin:cache', function() {
     it('should getProblem fail if client error', function(done) {
       cache.set('problems', PROBLEMS);
       cache.del('0.slug0.algorithms');
-      next.getProblem = (problem, cb) => cb('client getProblem error');
+      next.getProblem = (problem, needT, cb) => cb('client getProblem error');
 
-      plugin.getProblem(_.clone(PROBLEM), function(e, problem) {
+      plugin.getProblem(_.clone(PROBLEM), false, function(e, problem) {
         assert.equal(e, 'client getProblem error');
         done();
       });
@@ -128,23 +203,37 @@ describe('plugin:cache', function() {
       const ret = plugin.saveProblem(problem);
       assert.equal(ret, true);
       assert.deepEqual(cache.get('0.slug0.algorithms'),
-          {id: 0, fid: 0, slug: 'slug0', name: 'name0', category: 'algorithms'});
+          {
+            id:       0, fid:      0, slug:     'slug0', name:     'name0',
+            desc:     '
', likes:    '1', dislikes: '1', hints:    [],
+            category: 'algorithms'
+          });
     });
   }); // #saveProblem
 
   describe('#updateProblem', function() {
     it('should updateProblem ok', function(done) {
       cache.set('problems', PROBLEMS);
+      cache.set(h.KEYS.problemsMeta, FRESH_META());
+      cache.set(h.KEYS.translation, TRANSLATION_CONFIGS);
 
       const kv = {value: 'value00'};
       const ret = plugin.updateProblem(PROBLEMS[0], kv);
       assert.equal(ret, true);
 
-      plugin.getProblems(function(e, problems) {
+      plugin.getProblems(false, function(e, problems) {
         assert.equal(e, null);
         assert.deepEqual(problems, [
-            {id: 0, fid: 0, name: 'name0', slug: 'slug0', value: 'value00', starred: false, category: 'algorithms'},
-            {id: 1, fid: 1, name: 'name1', slug: 'slug1', starred: true, category: 'algorithms'}
+            {
+              id:       0, fid:      0, name:     'name0', slug:     'slug0', value:    'value00',
+              starred:  false, desc:     '
', likes:    '1', dislikes: '1',
+              hints:    [], category: 'algorithms'
+            },
+            {
+              id:       1, fid:      1, name:     'name1', slug:     'slug1', starred:  true,
+              desc:     '
', likes:    '1', dislikes: '1', hints:    [],
+              category: 'algorithms'
+            }
         ]);
         done();
       });
@@ -211,6 +300,38 @@ describe('plugin:cache', function() {
       });
     });
 
+    it('should cookieLogin purge problems cache ok', function(done) {
+      config.autologin.enable = false;
+      cache.set(h.KEYS.user, USER);
+      cache.set('problems', PROBLEMS);
+      cache.set(h.KEYS.problemsMeta, FRESH_META());
+      next.cookieLogin = (user, cb) => cb(null, USER);
+
+      // call detached on purpose, commands/user.js invokes it this way
+      const cookieLogin = plugin.cookieLogin;
+      cookieLogin(USER, function(e, user) {
+        assert.equal(e, null);
+        assert.deepEqual(user, USER);
+        assert.deepEqual(session.getUser(), USER_SAFE);
+        assert.equal(cache.get(h.KEYS.problems), null);
+        assert.equal(cache.get(h.KEYS.problemsMeta), null);
+        done();
+      });
+    });
+
+    it('should cookieLogin fail if client error', function(done) {
+      cache.set('problems', PROBLEMS);
+      cache.set(h.KEYS.problemsMeta, FRESH_META());
+      next.cookieLogin = (user, cb) => cb('client cookieLogin error');
+
+      const cookieLogin = plugin.cookieLogin;
+      cookieLogin(USER, function(e, user) {
+        assert.equal(e, 'client cookieLogin error');
+        assert.equal(cache.get(h.KEYS.problems), null);
+        done();
+      });
+    });
+
     it('should logout ok', function(done) {
       // before logout
       cache.set(h.KEYS.user, USER);
diff --git a/test/plugins/test_leetcode.js b/test/plugins/test_leetcode.js
index ef099b9b..bf233a42 100644
--- a/test/plugins/test_leetcode.js
+++ b/test/plugins/test_leetcode.js
@@ -40,6 +40,84 @@ describe('plugin:leetcode', function() {
     plugin.__set__('session', session);
   });
 
+  describe('#cookieLogin', function() {
+    const getUserNocks = () => {
+      nock('https://leetcode.com').get('/list/api/questions')
+        .reply(200, JSON.stringify({
+          favorites: {private_favorites: [{name: 'Favorite', id_hash: 'HASH'}]},
+          user_name: 'NAME'
+        }));
+      nock('https://leetcode.com').post('/graphql')
+        .reply(200, {data: {userStatus: {username: 'NAME', isPremium: false}}});
+    };
+
+    it('should ok', function(done) {
+      getUserNocks();
+      const user = {
+        login:  'user',
+        cookie: 'other=1; LEETCODE_SESSION=SESSION_ID; csrftoken=CSRF_TOKEN;'
+      };
+
+      plugin.cookieLogin(user, function(e, user) {
+        assert.equal(e, null);
+        assert.equal(user.sessionId, 'SESSION_ID');
+        assert.equal(user.sessionCSRF, 'CSRF_TOKEN');
+        assert.equal(user.name, 'NAME');
+        assert.equal(user.paid, false);
+        done();
+      });
+    });
+
+    it('should fail if cookie misses LEETCODE_SESSION', function(done) {
+      plugin.cookieLogin({login: 'user', cookie: 'csrftoken=CSRF;'}, function(e, user) {
+        assert.equal(e, 'invalid cookie?');
+        done();
+      });
+    });
+
+    it('should fail if cookie misses csrftoken', function(done) {
+      plugin.cookieLogin({login: 'user', cookie: 'LEETCODE_SESSION=SESSION;'}, function(e, user) {
+        assert.equal(e, 'invalid cookie?');
+        done();
+      });
+    });
+
+    it('should fail if no cookie', function(done) {
+      plugin.cookieLogin({login: 'user'}, function(e, user) {
+        assert.equal(e, 'invalid cookie?');
+        done();
+      });
+    });
+  }); // #cookieLogin
+
+  describe('#checkError', function() {
+    it('should pass on expected status', function() {
+      assert.equal(plugin.checkError(null, {statusCode: 200}, 200), null);
+    });
+
+    it('should map 401 to session expired', function() {
+      assert.equal(plugin.checkError(null, {statusCode: 401}, 200), session.errors.EXPIRED);
+    });
+
+    it('should map 403 to blocked', function() {
+      assert.equal(plugin.checkError(null, {statusCode: 403}, 200), session.errors.BLOCKED);
+    });
+
+    it('should map 429 to blocked', function() {
+      assert.equal(plugin.checkError(null, {statusCode: 429}, 200), session.errors.BLOCKED);
+    });
+
+    it('should keep other http errors', function() {
+      assert.deepEqual(plugin.checkError(null, {statusCode: 500}, 200),
+          {msg: 'http error', statusCode: 500});
+    });
+
+    it('should pass through network error', function() {
+      const e = new Error('boom');
+      assert.equal(plugin.checkError(e, null, 200), e);
+    });
+  }); // #checkError
+
   describe('#login', function() {
     it('should ok', function(done) {
       nock('https://leetcode.com')
@@ -65,6 +143,10 @@ describe('plugin:leetcode', function() {
           }
         }));
 
+      nock('https://leetcode.com')
+        .post('/graphql')
+        .reply(200, {data: {userStatus: {username: 'Eric', isPremium: true}}});
+
       plugin.login({}, function(e, user) {
         assert.equal(e, null);
 
@@ -73,6 +155,43 @@ describe('plugin:leetcode', function() {
         assert.equal(user.sessionId, 'SESSION_ID');
         assert.equal(user.name, 'Eric');
         assert.equal(user.hash, 'abcdef');
+        assert.equal(user.paid, true);
+        done();
+      });
+    });
+
+    it('should login ok even if user info unavailable', function(done) {
+      nock('https://leetcode.com')
+        .get('/accounts/login/')
+        .reply(200, '', { 'Set-Cookie': [
+            'csrftoken=LOGIN_CSRF_TOKEN; Max-Age=31449600; Path=/; secure'
+          ]});
+
+      nock('https://leetcode.com')
+        .post('/accounts/login/')
+        .reply(302, '', {
+          'Set-Cookie': [
+            'csrftoken=SESSION_CSRF_TOKEN; Max-Age=31449600; Path=/; secure',
+            'LEETCODE_SESSION=SESSION_ID; Max-Age=31449600; Path=/; secure'
+          ]});
+
+      nock('https://leetcode.com')
+        .get('/list/api/questions')
+        .reply(200, JSON.stringify({
+          user_name: 'Eric',
+          favorites: {
+            private_favorites: [{id_hash: 'abcdef', name: 'Favorite'}]
+          }
+        }));
+
+      nock('https://leetcode.com')
+        .post('/graphql')
+        .reply(500);
+
+      plugin.login({}, function(e, user) {
+        assert.equal(e, null);
+        assert.equal(user.name, 'Eric'); // falls back to favorites user_name
+        assert.equal(user.paid, undefined);
         done();
       });
     });
@@ -121,9 +240,55 @@ describe('plugin:leetcode', function() {
         .get('/api/problems/shell/')
         .replyWithFile(200, './test/mock/problems.json.20160911');
 
-      plugin.getProblems(function(e, problems) {
+      nock('https://leetcode.com')
+        .get('/api/problems/concurrency/')
+        .replyWithFile(200, './test/mock/problems.json.20160911');
+
+      nock('https://leetcode.com')
+        .post('/graphql')
+        .reply(200, {data: {problemsetQuestionListV2: {
+          hasMore:   false,
+          questions: [
+            {questionFrontendId: '1', topicTags: [{slug: 'hash-table'}, {slug: 'two-pointers'}]},
+            {questionFrontendId: '2', topicTags: []}
+          ]
+        }}});
+
+      plugin.getProblems(false, function(e, problems) {
         assert.equal(e, null);
-        assert.equal(problems.length, 377 * 3);
+        assert.equal(problems.length, 377 * 4);
+        // the 2016 mock carries no frontend ids, so every problem falls
+        // back to the empty tag list
+        assert.deepEqual(problems[0].tags, []);
+        done();
+      });
+    });
+
+    it('should ok sans tags if tag fetch fails', function(done) {
+      nock('https://leetcode.com')
+        .get('/api/problems/algorithms/')
+        .replyWithFile(200, './test/mock/problems.json.20160911');
+
+      nock('https://leetcode.com')
+        .get('/api/problems/database/')
+        .replyWithFile(200, './test/mock/problems.json.20160911');
+
+      nock('https://leetcode.com')
+        .get('/api/problems/shell/')
+        .replyWithFile(200, './test/mock/problems.json.20160911');
+
+      nock('https://leetcode.com')
+        .get('/api/problems/concurrency/')
+        .replyWithFile(200, './test/mock/problems.json.20160911');
+
+      nock('https://leetcode.com')
+        .post('/graphql')
+        .reply(500);
+
+      plugin.getProblems(false, function(e, problems) {
+        assert.equal(e, null);
+        assert.equal(problems.length, 377 * 4);
+        assert.equal(problems[0].tags, undefined);
         done();
       });
     });
@@ -141,7 +306,11 @@ describe('plugin:leetcode', function() {
         .get('/api/problems/shell/')
         .replyWithFile(200, './test/mock/problems.json.20160911');
 
-      plugin.getProblems(function(e, problems) {
+      nock('https://leetcode.com')
+        .get('/api/problems/concurrency/')
+        .replyWithFile(200, './test/mock/problems.json.20160911');
+
+      plugin.getProblems(false, function(e, problems) {
         assert.equal(e.message, 'unknown error');
         done();
       });
@@ -174,6 +343,77 @@ describe('plugin:leetcode', function() {
     });
   }); // #getCategoryProblems
 
+  describe('#getProblemOfToday', function() {
+    it('should ok', function(done) {
+      nock('https://leetcode.com')
+        .post('/graphql')
+        .reply(200, {data: {activeDailyCodingChallengeQuestion:
+            {question: {titleSlug: 'find-the-difference'}}}});
+
+      plugin.getProblemOfToday(false, function(e, slug) {
+        assert.equal(e, null);
+        assert.equal(slug, 'find-the-difference');
+        done();
+      });
+    });
+
+    it('should fail if http error', function(done) {
+      nock('https://leetcode.com')
+        .post('/graphql')
+        .reply(500);
+
+      plugin.getProblemOfToday(false, function(e, slug) {
+        assert.deepEqual(e, {msg: 'http error', statusCode: 500});
+        done();
+      });
+    });
+
+    it('should fail if no daily challenge', function(done) {
+      nock('https://leetcode.com')
+        .post('/graphql')
+        .reply(200, {data: {activeDailyCodingChallengeQuestion: null}});
+
+      plugin.getProblemOfToday(false, function(e, slug) {
+        assert.equal(e, 'failed to load problem of today!');
+        done();
+      });
+    });
+  }); // #getProblemOfToday
+
+  describe('#getTags', function() {
+    it('should page through the whole tag map', function(done) {
+      nock('https://leetcode.com')
+        .post('/graphql')
+        .reply(200, {data: {problemsetQuestionListV2: {
+          hasMore:   true,
+          questions: [{questionFrontendId: '1', topicTags: [{slug: 'hash-table'}, {slug: 'two-pointers'}]}]
+        }}});
+      nock('https://leetcode.com')
+        .post('/graphql')
+        .reply(200, {data: {problemsetQuestionListV2: {
+          hasMore:   false,
+          questions: [{questionFrontendId: '2', topicTags: []}]
+        }}});
+
+      plugin.getTags(function(e, map) {
+        assert.equal(e, null);
+        assert.deepEqual(map, {1: ['hash-table', 'two-pointers'], 2: []});
+        done();
+      });
+    });
+
+    it('should fail if http error', function(done) {
+      nock('https://leetcode.com')
+        .post('/graphql')
+        .reply(500);
+
+      plugin.getTags(function(e, map) {
+        assert.deepEqual(e, {msg: 'http error', statusCode: 500});
+        done();
+      });
+    });
+  }); // #getTags
+
   describe('#getProblem', function() {
     beforeEach(function() {
       PROBLEM.locked = false;
@@ -184,21 +424,23 @@ describe('plugin:leetcode', function() {
         .post('/graphql')
         .replyWithFile(200, './test/mock/find-the-difference.json.20171216');
 
-      plugin.getProblem(PROBLEM, function(e, problem) {
+      plugin.getProblem(PROBLEM, false, function(e, problem) {
         assert.equal(e, null);
         assert.equal(problem.totalAC, '89.7K');
         assert.equal(problem.totalSubmit, '175.7K');
+        assert.deepEqual(problem.hints,
+            ['Can we sort the strings?', 'XOR trick works here.']);
         assert.equal(problem.desc,
           [
+            '

', + 'Given two strings s and t which consist of only lowercase letters.

', '', - 'Given two strings s and t which consist of only lowercase letters.', - '', - 'String t is generated by random shuffling string s and then add one more letter at a random position.', - '', - 'Find the letter that was added in t.', + '

String t is generated by random shuffling string s and then add one more letter at a random position.

', '', - 'Example:', + '

Find the letter that was added in t.

', '', + '

Example:', + '

',
             'Input:',
             's = "abcd"',
             't = "abcde"',
@@ -208,7 +450,7 @@ describe('plugin:leetcode', function() {
             '',
             'Explanation:',
             "'e' is the letter that was added.",
-            ''
+            '
' ].join('\r\n')); assert.equal(problem.templates.length, 12); @@ -359,25 +601,34 @@ describe('plugin:leetcode', function() { it('should fail if no permission for locked', function(done) { PROBLEM.locked = true; - plugin.getProblem(PROBLEM, function(e, problem) { + plugin.getProblem(PROBLEM, false, function(e, problem) { assert.equal(e, 'failed to load locked problem!'); done(); }); }); it('should fail if session expired', function(done) { - nock('https://leetcode.com').post('/graphql').reply(403); + nock('https://leetcode.com').post('/graphql').reply(401); - plugin.getProblem(PROBLEM, function(e, problem) { + plugin.getProblem(PROBLEM, false, function(e, problem) { assert.equal(e, session.errors.EXPIRED); done(); }); }); + it('should fail if blocked by cloudflare/rate-limit', function(done) { + nock('https://leetcode.com').post('/graphql').reply(403); + + plugin.getProblem(PROBLEM, false, function(e, problem) { + assert.equal(e, session.errors.BLOCKED); + done(); + }); + }); + it('should fail if http error', function(done) { nock('https://leetcode.com').post('/graphql').reply(500); - plugin.getProblem(PROBLEM, function(e, problem) { + plugin.getProblem(PROBLEM, false, function(e, problem) { assert.deepEqual(e, {msg: 'http error', statusCode: 500}); done(); }); @@ -386,7 +637,7 @@ describe('plugin:leetcode', function() { it('should fail if unknown error', function(done) { nock('https://leetcode.com').post('/graphql').replyWithError('unknown error!'); - plugin.getProblem(PROBLEM, function(e, problem) { + plugin.getProblem(PROBLEM, false, function(e, problem) { assert.equal(e.message, 'unknown error!'); done(); }); @@ -401,11 +652,11 @@ describe('plugin:leetcode', function() { nock('https://leetcode.com') .get('/submissions/detail/id1/check/') - .reply(200, '{"state": "SUCCESS", "run_success": true, "status_code": 10}'); + .reply(200, '{"state": "SUCCESS", "run_success": true, "status_msg": "Accepted", "submission_id": "interpret_expected_id1"}'); nock('https://leetcode.com') .get('/submissions/detail/id2/check/') - .reply(200, '{"state": "SUCCESS", "run_success": false, "status_code": 15}'); + .reply(200, '{"state": "SUCCESS", "run_success": false, "status_msg": "Runtime Error", "submission_id": "interpret_id2"}'); plugin.testProblem(PROBLEM, function(e, results) { assert.equal(e, null); @@ -437,7 +688,7 @@ describe('plugin:leetcode', function() { nock('https://leetcode.com') .get('/submissions/detail/id1/check/') - .reply(200, '{"state": "SUCCESS", "run_success": true, "status_code": 10}'); + .reply(200, '{"state": "SUCCESS", "run_success": true, "status_msg": "Accepted", "submission_id": "id1"}'); plugin.submitProblem(PROBLEM, function(e, results) { assert.equal(e, null); @@ -460,7 +711,7 @@ describe('plugin:leetcode', function() { .reply(200, '{"state": "STARTED"}'); nock('https://leetcode.com') .get('/submissions/detail/id1/check/') - .reply(200, '{"state": "SUCCESS", "run_success": true, "status_code": 10}'); + .reply(200, '{"state": "SUCCESS", "run_success": true, "status_msg": "Accepted", "submission_id": "id1"}'); plugin.submitProblem(PROBLEM, function(e, results) { assert.equal(e, null); @@ -500,8 +751,8 @@ describe('plugin:leetcode', function() { describe('#starProblem', function() { it('should star ok', function(done) { nock('https://leetcode.com') - .post('/list/api/questions') - .reply(204, ''); + .post('/graphql') + .replyWithFile(200, './test/mock/find-the-difference-star.json.20200821'); plugin.starProblem(PROBLEM, true, function(e, starred) { assert.equal(e, null); @@ -512,8 +763,8 @@ describe('plugin:leetcode', function() { it('should unstar ok', function(done) { nock('https://leetcode.com') - .delete('/list/api/questions/abcdef/389') - .reply(204, ''); + .post('/graphql') + .replyWithFile(200, './test/mock/find-the-difference-unstar.json.20200821'); plugin.starProblem(PROBLEM, false, function(e, starred) { assert.equal(e, null); @@ -524,7 +775,7 @@ describe('plugin:leetcode', function() { it('should star fail if http error', function(done) { nock('https://leetcode.com') - .post('/list/api/questions') + .post('/graphql') .replyWithError('unknown error!'); plugin.starProblem(PROBLEM, true, function(e, starred) { diff --git a/test/plugins/test_retry.js b/test/plugins/test_retry.js index dbdb060c..5205f716 100644 --- a/test/plugins/test_retry.js +++ b/test/plugins/test_retry.js @@ -3,6 +3,7 @@ const assert = require('chai').assert; const rewire = require('rewire'); const log = require('../../lib/log'); +const chalk = require('../../lib/chalk'); const config = rewire('../../lib/config'); const session = rewire('../../lib/session'); @@ -15,6 +16,7 @@ describe('plugin:retry', function() { before(function() { log.init(); + chalk.init(); config.init(); plugin.init(); @@ -95,4 +97,24 @@ describe('plugin:retry', function() { done(); }); }); + + it('should skip relogin if no password saved', function(done) { + config.autologin.enable = true; + config.autologin.retry = 2; + session.getUser = () => USER; // USER has no pass + + let logins = 0; + let n = 0; + NEXT.getProblems = function(cb) { + return ++n <= 2 ? cb(session.errors.EXPIRED) : cb(null, PROBLEMS); + }; + NEXT.login = (user, cb) => { ++logins; return cb(null, user); }; + + plugin.getProblems(function(e, problems) { + assert.notExists(e); + assert.equal(problems, PROBLEMS); + assert.equal(logins, 0); // signin never attempted + done(); + }); + }); }); diff --git a/test/test_core.js b/test/test_core.js index 0a436bb4..34d058ce 100644 --- a/test/test_core.js +++ b/test/test_core.js @@ -40,8 +40,8 @@ describe('core', function() { beforeEach(function() { next = {}; - next.getProblems = cb => cb(null, PROBLEMS); - next.getProblem = (p, cb) => cb(null, p); + next.getProblems = (needTrans, cb) => cb(null, PROBLEMS); + next.getProblem = (p, needTrans, cb) => cb(null, p); core = rewire('../lib/core'); core.setNext(next); @@ -68,7 +68,7 @@ describe('core', function() { let n = cases.length; for (let x of cases) { - core.filterProblems({query: x[0]}, function(e, problems) { + core.filterProblems({query: x[0], dontTranslate: false}, function(e, problems) { assert.notExists(e); assert.equal(problems.length, x[1].length); @@ -90,7 +90,7 @@ describe('core', function() { let n = cases.length; for (let x of cases) { - core.filterProblems({tag: x[0]}, function(e, problems) { + core.filterProblems({ tag: x[0], dontTranslate: false}, function(e, problems) { assert.notExists(e); assert.equal(problems.length, x[1].length); @@ -102,7 +102,7 @@ describe('core', function() { }); it('should fail if getProblems error', function(done) { - next.getProblems = cb => cb('getProblems error'); + next.getProblems = (needT, cb) => cb('getProblems error'); core.filterProblems({}, function(e) { assert.equal(e, 'getProblems error'); done(); @@ -154,6 +154,13 @@ describe('core', function() { file.isWindows = () => false; const expected = [ + '/*', + ' * @lc app=leetcode id=2 lang=cpp', + ' *', + ' * [2] Add Two Numbers', + ' */', + '', + '// @lc code=start', '/**', ' * Definition for singly-linked list.', ' * struct ListNode {', @@ -168,6 +175,7 @@ describe('core', function() { ' ', ' }', '};', + '// @lc code=end', '' ].join('\n'); @@ -184,6 +192,13 @@ describe('core', function() { file.isWindows = () => true; const expected = [ + '/*', + ' * @lc app=leetcode id=2 lang=cpp', + ' *', + ' * [2] Add Two Numbers', + ' */', + '', + '// @lc code=start', '/**', ' * Definition for singly-linked list.', ' * struct ListNode {', @@ -198,6 +213,7 @@ describe('core', function() { ' ', ' }', '};', + '// @lc code=end', '' ].join('\r\n'); @@ -223,6 +239,8 @@ describe('core', function() { ' *', ' * algorithms', ' * Medium (25.37%)', + ' * Likes: 1', + ' * Dislikes: 1', ' * Total Accepted: 195263', ' * Total Submissions: 769711', ' * Testcase Example: \'[2,4,3]\\n[5,6,4]\'', @@ -234,6 +252,8 @@ describe('core', function() { ' * Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)', ' * Output: 7 -> 0 -> 8', ' */', + '', + '// @lc code=start', '/**', ' * Definition for singly-linked list.', ' * struct ListNode {', @@ -248,6 +268,7 @@ describe('core', function() { ' ', ' }', '};', + '// @lc code=end', '' ].join('\n'); @@ -273,6 +294,8 @@ describe('core', function() { '#', '# algorithms', '# Medium (25.37%)', + '# Likes: 1', + '# Dislikes: 1', '# Total Accepted: 195263', '# Total Submissions: 769711', '# Testcase Example: \'\'', @@ -284,6 +307,8 @@ describe('core', function() { '# Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)', '# Output: 7 -> 0 -> 8', '#', + '', + '# @lc code=start', '# Definition for singly-linked list.', '# class ListNode', '# attr_accessor :val, :next', @@ -299,6 +324,7 @@ describe('core', function() { 'def add_two_numbers(l1, l2)', ' ', 'end', + '# @lc code=end', '' ].join('\n'); @@ -314,8 +340,9 @@ describe('core', function() { }); // #exportProblem describe('#getProblem', function() { - it('should get by id ok', function(done) { - core.getProblem(0, function(e, problem) { + it('should get by id ok', function (done) { + // set needTranslate to false here because it's not used anyways + core.getProblem(0, false, function(e, problem) { assert.notExists(e); assert.deepEqual(problem, PROBLEMS[0]); done(); @@ -323,7 +350,15 @@ describe('core', function() { }); it('should get by key ok', function(done) { - core.getProblem('slug0', function(e, problem) { + core.getProblem('slug0', false, function(e, problem) { + assert.notExists(e); + assert.deepEqual(problem, PROBLEMS[0]); + done(); + }); + }); + + it('should get by url ok', function(done) { + core.getProblem('https://leetcode.com/problems/slug0/description/', false, function(e, problem) { assert.notExists(e); assert.deepEqual(problem, PROBLEMS[0]); done(); @@ -331,23 +366,23 @@ describe('core', function() { }); it('should fail if not found', function(done) { - core.getProblem(3, function(e, problem) { + core.getProblem(3, false, function(e, problem) { assert.equal(e, 'Problem not found!'); done(); }); }); it('should fail if client error', function(done) { - next.getProblem = (problem, cb) => cb('client getProblem error'); + next.getProblem = (problem, needT, cb) => cb('client getProblem error'); - core.getProblem(0, function(e, problem) { + core.getProblem(0, false, function(e, problem) { assert.equal(e, 'client getProblem error'); done(); }); }); it('should ok if problem is already there', function(done) { - core.getProblem(PROBLEMS[1], function(e, problem) { + core.getProblem(PROBLEMS[1], false, function(e, problem) { assert.notExists(e); assert.deepEqual(problem, PROBLEMS[1]); done(); @@ -355,12 +390,40 @@ describe('core', function() { }); it('should fail if getProblems error', function(done) { - next.getProblems = cb => cb('getProblems error'); + next.getProblems = (needT, cb) => cb('getProblems error'); - core.getProblem(0, function(e, problem) { + core.getProblem(0, false, function(e, problem) { assert.equal(e, 'getProblems error'); done(); }); }); + + it('should get problem of today ok', function(done) { + next.getProblemOfToday = (needT, cb) => cb(null, 'slug1'); + + core.getProblemOfToday(false, function(e, problem) { + assert.notExists(e); + assert.equal(problem.slug, 'slug1'); + done(); + }); + }); + + it('should fail if problem of today not found', function(done) { + next.getProblemOfToday = (needT, cb) => cb(null, 'slug999'); + + core.getProblemOfToday(false, function(e, problem) { + assert.equal(e, 'Problem not found!'); + done(); + }); + }); + + it('should fail if problem of today client error', function(done) { + next.getProblemOfToday = (needT, cb) => cb('client getProblemOfToday error'); + + core.getProblemOfToday(false, function(e, problem) { + assert.equal(e, 'client getProblemOfToday error'); + done(); + }); + }); }); // #getProblem }); diff --git a/test/test_file.js b/test/test_file.js index d458e83f..352d5b12 100644 --- a/test/test_file.js +++ b/test/test_file.js @@ -9,11 +9,19 @@ const th = require('./helper'); describe('file', function() { let file; + const savedHome = process.env.HOME; + const savedUserProfile = process.env.USERPROFILE; beforeEach(function() { file = rewire('../lib/file'); }); + afterEach(function() { + // env tweaks here leak into every suite loaded afterwards otherwise + process.env.HOME = savedHome; + process.env.USERPROFILE = savedUserProfile; + }); + describe('#dirAndFiles', function() { const HOME = path.join(__dirname, '..'); @@ -50,10 +58,13 @@ describe('file', function() { it('should listCodeDir ok', function() { const files = file.listCodeDir('lib/plugins'); - assert.equal(files.length, 3); + assert.equal(files.length, 6); assert.equal(files[0].name, 'cache'); - assert.equal(files[1].name, 'leetcode'); - assert.equal(files[2].name, 'retry'); + assert.equal(files[1].name, 'company'); + assert.equal(files[2].name, 'leetcode.cn'); + assert.equal(files[3].name, 'leetcode'); + assert.equal(files[4].name, 'retry'); + assert.equal(files[5].name, 'solution.discuss'); }); it('should pluginFile ok', function() { diff --git a/test/test_helper.js b/test/test_helper.js index 143bda9e..df07be45 100644 --- a/test/test_helper.js +++ b/test/test_helper.js @@ -135,6 +135,7 @@ describe('helper', function() { assert.equal(h.langToExt('rust'), '.rs'); assert.equal(h.langToExt('scala'), '.scala'); assert.equal(h.langToExt('swift'), '.swift'); + assert.equal(h.langToExt('typescript'), '.ts'); }); }); // #langToExt @@ -146,6 +147,8 @@ describe('helper', function() { assert.equal(h.extToLang('./file.cs'), 'csharp'); assert.equal(h.extToLang('../file.go'), 'golang'); assert.equal(h.extToLang('file.java'), 'java'); + assert.equal(h.extToLang('~/leetcode/../file.sql'), 'mysql'); + assert.equal(h.extToLang('~/leetcode/hello.php'), 'php'); assert.equal(h.extToLang('c:/file.js'), 'javascript'); assert.equal(h.extToLang('~/leetcode/../file.sql'), 'mysql'); assert.equal(h.extToLang('~/leetcode/hello.php'), 'php'); @@ -155,30 +158,32 @@ describe('helper', function() { assert.equal(h.extToLang('/tmp/file.scala'), 'scala'); assert.equal(h.extToLang('~/leetcode/file.swift'), 'swift'); assert.equal(h.extToLang('/home/skygragon/file.dat'), 'unknown'); + assert.equal(h.extToLang('~/leetcode/file.ts'), 'typescript'); }); }); // #extToLang describe('#langToCommentStyle', function() { it('should ok', function() { - const C_STYLE = {start: '/*', line: ' *', end: ' */'}; - const RUBY_STYLE = {start: '#', line: '#', end: '#'}; - const SQL_STYLE = {start: '--', line: '--', end: '--'}; + const C_STYLE = {start: '/*', line: ' *', end: ' */', singleLine: '//'}; + const RUBY_STYLE = {start: '#', line: '#', end: '#', singleLine: '#'}; + const SQL_STYLE = {start: '--', line: '--', end: '--', singleLine: '--'}; assert.deepEqual(h.langToCommentStyle('bash'), RUBY_STYLE); assert.deepEqual(h.langToCommentStyle('c'), C_STYLE); assert.deepEqual(h.langToCommentStyle('cpp'), C_STYLE); assert.deepEqual(h.langToCommentStyle('csharp'), C_STYLE); assert.deepEqual(h.langToCommentStyle('golang'), C_STYLE); + assert.deepEqual(h.langToCommentStyle('php'), C_STYLE); assert.deepEqual(h.langToCommentStyle('java'), C_STYLE); assert.deepEqual(h.langToCommentStyle('javascript'), C_STYLE); assert.deepEqual(h.langToCommentStyle('mysql'), SQL_STYLE); - assert.deepEqual(h.langToCommentStyle('php'), C_STYLE); assert.deepEqual(h.langToCommentStyle('python'), RUBY_STYLE); assert.deepEqual(h.langToCommentStyle('python3'), RUBY_STYLE); assert.deepEqual(h.langToCommentStyle('ruby'), RUBY_STYLE); assert.deepEqual(h.langToCommentStyle('rust'), C_STYLE); assert.deepEqual(h.langToCommentStyle('scala'), C_STYLE); assert.deepEqual(h.langToCommentStyle('swift'), C_STYLE); + assert.deepEqual(h.langToCommentStyle('typescript'), C_STYLE); }); }); // #langToCommentStyle diff --git a/test/test_log.js b/test/test_log.js index 92e5ef4b..ceb46006 100644 --- a/test/test_log.js +++ b/test/test_log.js @@ -81,6 +81,11 @@ describe('log', function() { assert.equal(expected, 'some error'); }); + it('should ok with null/undefined args', function() { + log.info('value:', undefined, null); + assert.equal(expected, 'value: '); + }); + it('should ok with log.warn', function() { log.warn('some error'); assert.equal(expected, chalk.yellow('[WARN] some error')); @@ -92,8 +97,11 @@ describe('log', function() { }); it('should ok with log.fail', function() { + const savedExitCode = process.exitCode; log.fail({msg: 'some error', statusCode: 500}); assert.equal(expected, chalk.red('[ERROR] some error [code=500]')); + assert.equal(process.exitCode, 1); + process.exitCode = savedExitCode; log.fail('some error'); assert.equal(expected, chalk.red('[ERROR] some error')); diff --git a/test/test_plugin.js b/test/test_plugin.js index aa3a40be..584b350f 100644 --- a/test/test_plugin.js +++ b/test/test_plugin.js @@ -115,7 +115,7 @@ describe('plugin', function() { const deps = ['a', 'b:linux', 'b:darwin', 'b:win32', 'c:bad', 'd']; const p = new Plugin(100, 'test', '2017.12.26', 'desc', deps); p.install(function() { - assert.equal(expected, 'npm install --save a b d'); + assert.equal(expected, 'pnpm add a b d'); done(); }); });